1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
13 import java.util.ArrayList;
14 import java.util.HashMap;
17 import net.sourceforge.phpdt.core.IBuffer;
18 import net.sourceforge.phpdt.core.IBufferFactory;
19 import net.sourceforge.phpdt.core.ICompilationUnit;
20 import net.sourceforge.phpdt.core.IImportContainer;
21 import net.sourceforge.phpdt.core.IImportDeclaration;
22 import net.sourceforge.phpdt.core.IJavaElement;
23 import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
24 import net.sourceforge.phpdt.core.IJavaProject;
25 import net.sourceforge.phpdt.core.IMember;
26 import net.sourceforge.phpdt.core.IMethod;
27 import net.sourceforge.phpdt.core.IOpenable;
28 import net.sourceforge.phpdt.core.IPackageDeclaration;
29 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
30 import net.sourceforge.phpdt.core.IParent;
31 import net.sourceforge.phpdt.core.IProblemRequestor;
32 import net.sourceforge.phpdt.core.ISourceManipulation;
33 import net.sourceforge.phpdt.core.ISourceRange;
34 import net.sourceforge.phpdt.core.ISourceReference;
35 import net.sourceforge.phpdt.core.IType;
36 import net.sourceforge.phpdt.core.IWorkingCopy;
37 import net.sourceforge.phpdt.core.JavaModelException;
38 import net.sourceforge.phpdt.core.Signature;
39 import net.sourceforge.phpdt.core.WorkingCopyOwner;
40 import net.sourceforge.phpdt.core.compiler.CharOperation;
41 import net.sourceforge.phpdt.core.jdom.IDOMNode;
42 import net.sourceforge.phpdt.internal.compiler.IProblemFactory;
43 import net.sourceforge.phpdt.internal.compiler.SourceElementParser;
44 import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
45 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
46 import net.sourceforge.phpdt.internal.compiler.problem.DefaultProblemFactory;
47 import net.sourceforge.phpdt.internal.core.util.MementoTokenizer;
48 import net.sourceforge.phpdt.internal.core.util.Util;
50 import org.eclipse.core.resources.IContainer;
51 import org.eclipse.core.resources.IFile;
52 import org.eclipse.core.resources.IMarker;
53 import org.eclipse.core.resources.IResource;
54 import org.eclipse.core.runtime.IPath;
55 import org.eclipse.core.runtime.IProgressMonitor;
56 import org.eclipse.core.runtime.Path;
59 * @see ICompilationUnit
62 public class CompilationUnit extends Openable implements ICompilationUnit,
63 net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit {
64 public WorkingCopyOwner owner;
66 * Constructs a handle to a compilation unit with the given name in the specified package for the specified owner
68 * @exception IllegalArgumentException
69 * if the name of the compilation unit does not end with ".java"
71 protected CompilationUnit(PackageFragment parent, String name, WorkingCopyOwner owner) {
77 * Accepts the given visitor onto the parsed tree of this compilation unit, after having runned the name resolution. The visitor's
78 * corresponding <code>visit</code> method is called with the corresponding parse tree. If the visitor returns <code>true</code>,
79 * this method visits this parse node's members.
83 * @exception JavaModelException
84 * if this method fails. Reasons include:
86 * <li>This element does not exist.</li>
87 * <li>The visitor failed with this exception.</li>
90 //public void accept(IAbstractSyntaxTreeVisitor visitor) throws JavaModelException {
91 // CompilationUnitVisitor.visit(this, visitor);
94 * @see ICompilationUnit#becomeWorkingCopy(IProblemRequestor, IProgressMonitor)
96 public void becomeWorkingCopy(IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException {
97 JavaModelManager manager = JavaModelManager.getJavaModelManager();
98 JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = manager.getPerWorkingCopyInfo(this, false/* don't create */,
99 true /* record usage */, null/* no problem requestor needed */);
100 if (perWorkingCopyInfo == null) {
101 // close cu and its children
104 BecomeWorkingCopyOperation operation = new BecomeWorkingCopyOperation(this, problemRequestor);
105 operation.runOperation(monitor);
109 //protected void buildStructure(OpenableElementInfo info, IProgressMonitor monitor) throws JavaModelException {
111 // if (monitor != null && monitor.isCanceled()) return;
113 // // remove existing (old) infos
116 // HashMap newElements = new HashMap(11);
117 // info.setIsStructureKnown(generateInfos(info, monitor, newElements, getResource()));
118 // JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
119 // for (Iterator iter = newElements.keySet().iterator(); iter.hasNext();) {
120 // IJavaElement key = (IJavaElement) iter.next();
121 // Object value = newElements.get(key);
122 // JavaModelManager.getJavaModelManager().putInfo(key, value);
124 // // add the info for this at the end, to ensure that a getInfo cannot reply null in case the LRU cache needs
125 // // to be flushed. Might lead to performance issues.
126 // // see PR 1G2K5S7: ITPJCORE:ALL - NPE when accessing source for a binary type
127 // JavaModelManager.getJavaModelManager().putInfo(this, info);
129 protected boolean buildStructure(OpenableElementInfo info, final IProgressMonitor pm, Map newElements,
130 IResource underlyingResource) throws JavaModelException {
132 // check if this compilation unit can be opened
133 if (!isWorkingCopy()) { // no check is done on root kind or exclusion pattern for working copies
134 if ( // ((IPackageFragment)getParent()).getKind() == IPackageFragmentRoot.K_BINARY||
135 !isValidCompilationUnit() || !underlyingResource.isAccessible()) {
136 throw newNotPresentException();
140 // prevents reopening of non-primary working copies (they are closed when they are discarded and should not be reopened)
141 if (!isPrimary() && getPerWorkingCopyInfo() == null) {
142 throw newNotPresentException();
145 CompilationUnitElementInfo unitInfo = (CompilationUnitElementInfo) info;
147 // get buffer contents
148 IBuffer buffer = getBufferManager().getBuffer(CompilationUnit.this);
149 if (buffer == null) {
150 buffer = openBuffer(pm, unitInfo); // open buffer independently from the info, since we are building the info
152 final char[] contents = buffer == null ? null : buffer.getCharacters();
154 // generate structure and compute syntax problems if needed
155 CompilationUnitStructureRequestor requestor = new CompilationUnitStructureRequestor(this, unitInfo, newElements);
156 JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = getPerWorkingCopyInfo();
157 IJavaProject project = getJavaProject();
158 boolean computeProblems = JavaProject.hasJavaNature(project.getProject()) && perWorkingCopyInfo != null
159 && perWorkingCopyInfo.isActive();
160 IProblemFactory problemFactory = new DefaultProblemFactory();
161 Map options = project.getOptions(true);
163 if (underlyingResource == null) {
164 underlyingResource = getResource();
167 SourceElementParser parser = new SourceElementParser(requestor, problemFactory,
168 new CompilerOptions(options));
169 //, true/*report local declarations*/);
170 requestor.parser = parser;
171 CompilationUnitDeclaration unit = parser.parseCompilationUnit(
172 new net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit() {
173 public char[] getContents() {
177 public char[] getMainTypeName() {
178 return CompilationUnit.this.getMainTypeName();
181 public char[][] getPackageName() {
182 return CompilationUnit.this.getPackageName();
185 public char[] getFileName() {
186 return CompilationUnit.this.getFileName();
189 public IResource getResource() {
190 return CompilationUnit.this.getResource();
192 }, true /* full parse to find local elements */);
194 // update timestamp (might be IResource.NULL_STAMP if original does not exist)
196 unitInfo.timestamp = ((IFile) underlyingResource).getModificationStamp();
197 // compute other problems if needed
198 CompilationUnitDeclaration compilationUnitDeclaration = null;
200 if (computeProblems) {
201 perWorkingCopyInfo.beginReporting();
202 compilationUnitDeclaration = CompilationUnitProblemFinder.process(unit, this, contents, parser, this.owner,
203 perWorkingCopyInfo, problemFactory, false/* don't cleanup cu */, pm);
204 perWorkingCopyInfo.endReporting();
207 // if (info instanceof ASTHolderCUInfo) {
208 // int astLevel = ((ASTHolderCUInfo) info).astLevel;
209 // net.sourceforge.phpdt.core.dom.CompilationUnit cu = AST.convertCompilationUnit(astLevel, unit, contents, options, pm);
210 // ((ASTHolderCUInfo) info).ast = cu;
213 if (compilationUnitDeclaration != null) {
214 compilationUnitDeclaration.cleanUp();
218 return unitInfo.isStructureKnown();
222 // * @see ICodeAssist#codeComplete(int, ICompletionRequestor)
224 //public void codeComplete(int offset, ICompletionRequestor requestor) throws JavaModelException {
225 // codeComplete(this, isWorkingCopy() ? (net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit) getOriginalElement() : this,
226 // offset, requestor);
229 * @see ICodeAssist#codeSelect(int, int)
231 //public IJavaElement[] codeSelect(int offset, int length) throws JavaModelException {
232 // return super.codeSelect(this, offset, length);
235 * @see IWorkingCopy#commit(boolean, IProgressMonitor)
237 public void commit(boolean force, IProgressMonitor monitor) throws JavaModelException {
238 commitWorkingCopy(force, monitor);
239 // throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, this));
243 * @see ICompilationUnit#commitWorkingCopy(boolean, IProgressMonitor)
245 public void commitWorkingCopy(boolean force, IProgressMonitor monitor) throws JavaModelException {
246 CommitWorkingCopyOperation op = new CommitWorkingCopyOperation(this, force);
247 op.runOperation(monitor);
251 * @see ISourceManipulation#copy(IJavaElement, IJavaElement, String, boolean, IProgressMonitor)
253 public void copy(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor)
254 throws JavaModelException {
255 if (container == null) {
256 throw new IllegalArgumentException(Util.bind("operation.nullContainer")); //$NON-NLS-1$
258 IJavaElement[] elements = new IJavaElement[] { this };
259 IJavaElement[] containers = new IJavaElement[] { container };
260 String[] renamings = null;
261 if (rename != null) {
262 renamings = new String[] { rename };
264 getJavaModel().copy(elements, containers, null, renamings, force, monitor);
268 * Returns a new element info for this element.
270 protected Object createElementInfo() {
271 return new CompilationUnitElementInfo();
275 // * @see ICompilationUnit#createImport(String, IJavaElement, IProgressMonitor)
277 //public IImportDeclaration createImport(String name, IJavaElement sibling, IProgressMonitor monitor) throws JavaModelException {
278 // CreateImportOperation op = new CreateImportOperation(name, this);
279 // if (sibling != null) {
280 // op.createBefore(sibling);
282 // runOperation(op, monitor);
283 // return getImport(name);
286 * @see ICompilationUnit#createPackageDeclaration(String, IProgressMonitor)
288 public IPackageDeclaration createPackageDeclaration(String name, IProgressMonitor monitor) throws JavaModelException {
290 CreatePackageDeclarationOperation op = new CreatePackageDeclarationOperation(name, this);
291 runOperation(op, monitor);
292 return getPackageDeclaration(name);
296 // * @see ICompilationUnit#createType(String, IJavaElement, boolean, IProgressMonitor)
298 //public IType createType(String content, IJavaElement sibling, boolean force, IProgressMonitor monitor) throws
299 // JavaModelException {
301 // //autogenerate this compilation unit
302 // IPackageFragment pkg = (IPackageFragment) getParent();
303 // String source = ""; //$NON-NLS-1$
304 // if (pkg.getElementName().length() > 0) {
305 // //not the default package...add the package declaration
306 // source = "package " + pkg.getElementName() + ";" + net.sourceforge.phpdt.internal.compiler.util.ProjectPrefUtil.LINE_SEPARATOR +
307 // net.sourceforge.phpdt.internal.compiler.util.ProjectPrefUtil.LINE_SEPARATOR; //$NON-NLS-1$ //$NON-NLS-2$
309 // CreateCompilationUnitOperation op = new CreateCompilationUnitOperation(pkg, fName, source, force);
310 // runOperation(op, monitor);
312 // CreateTypeOperation op = new CreateTypeOperation(this, content, force);
313 // if (sibling != null) {
314 // op.createBefore(sibling);
316 // runOperation(op, monitor);
317 // return (IType) op.getResultElements()[0];
320 * @see ISourceManipulation#delete(boolean, IProgressMonitor)
322 public void delete(boolean force, IProgressMonitor monitor) throws JavaModelException {
323 IJavaElement[] elements = new IJavaElement[] { this };
324 getJavaModel().delete(elements, force, monitor);
328 * @see IWorkingCopy#destroy()
331 public void destroy() {
333 discardWorkingCopy();
334 } catch (JavaModelException e) {
340 * @see ICompilationUnit#discardWorkingCopy
342 public void discardWorkingCopy() throws JavaModelException {
343 // discard working copy and its children
344 DiscardWorkingCopyOperation op = new DiscardWorkingCopyOperation(this);
345 op.runOperation(null);
349 * Returns true if this handle represents the same Java element as the given handle.
351 * @see Object#equals(java.lang.Object)
353 public boolean equals(Object obj) {
354 if (!(obj instanceof CompilationUnit))
356 CompilationUnit other = (CompilationUnit) obj;
357 return this.owner.equals(other.owner) && super.equals(obj);
361 * @see JavaElement#equalsDOMNode(IDOMNode)
363 protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException {
364 String name = getElementName();
365 if (node.getNodeType() == IDOMNode.COMPILATION_UNIT && name != null) {
366 String nodeName = node.getName();
367 if (nodeName == null)
369 if (name.equals(nodeName)) {
372 // iterate through all the types inside the receiver and see if one of them can fit
373 IType[] types = getTypes();
374 String typeNodeName = nodeName.substring(0, nodeName.indexOf(".java")); //$NON-NLS-1$
375 for (int i = 0, max = types.length; i < max; i++) {
376 if (types[i].getElementName().equals(typeNodeName)) {
386 * @see IWorkingCopy#findElements(IJavaElement)
388 public IJavaElement[] findElements(IJavaElement element) {
389 ArrayList children = new ArrayList();
390 while (element != null && element.getElementType() != IJavaElement.COMPILATION_UNIT) {
391 children.add(element);
392 element = element.getParent();
396 IJavaElement currentElement = this;
397 for (int i = children.size() - 1; i >= 0; i--) {
398 IJavaElement child = (IJavaElement) children.get(i);
399 switch (child.getElementType()) {
400 // case IJavaElement.PACKAGE_DECLARATION:
401 // currentElement = ((ICompilationUnit)currentElement).getPackageDeclaration(child.getElementName());
403 // case IJavaElement.IMPORT_CONTAINER:
404 // currentElement = ((ICompilationUnit)currentElement).getImportContainer();
406 // case IJavaElement.IMPORT_DECLARATION:
407 // currentElement = ((IImportContainer)currentElement).getImport(child.getElementName());
409 case IJavaElement.TYPE:
410 if (currentElement.getElementType() == IJavaElement.COMPILATION_UNIT) {
411 currentElement = ((ICompilationUnit) currentElement).getType(child.getElementName());
413 currentElement = ((IType) currentElement).getType(child.getElementName());
416 // case IJavaElement.INITIALIZER:
417 // currentElement = ((IType)currentElement).getInitializer(((JavaElement)child).getOccurrenceCount());
419 case IJavaElement.FIELD:
420 currentElement = ((IType) currentElement).getField(child.getElementName());
422 case IJavaElement.METHOD:
423 return ((IType) currentElement).findMethods((IMethod) child);
427 if (currentElement != null && currentElement.exists()) {
428 return new IJavaElement[] { currentElement };
435 * @see IWorkingCopy#findPrimaryType()
437 public IType findPrimaryType() {
438 String typeName = Signature.getQualifier(this.getElementName());
439 IType primaryType = this.getType(typeName);
440 if (primaryType.exists()) {
447 * @see IWorkingCopy#findSharedWorkingCopy(IBufferFactory)
450 public IJavaElement findSharedWorkingCopy(IBufferFactory factory) {
452 // if factory is null, default factory must be used
454 factory = this.getBufferManager().getDefaultBufferFactory();
456 return findWorkingCopy(BufferFactoryWrapper.create(factory));
460 * @see ICompilationUnit#findWorkingCopy(WorkingCopyOwner)
462 public ICompilationUnit findWorkingCopy(WorkingCopyOwner workingCopyOwner) {
463 CompilationUnit cu = new CompilationUnit((PackageFragment) this.parent, getElementName(), workingCopyOwner);
464 if (workingCopyOwner == DefaultWorkingCopyOwner.PRIMARY) {
467 // must be a working copy
468 JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = cu.getPerWorkingCopyInfo();
469 if (perWorkingCopyInfo != null) {
470 return perWorkingCopyInfo.getWorkingCopy();
477 //protected boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource)
478 // throws JavaModelException {
480 //// if (getParent() instanceof JarPackageFragment) {
481 //// // ignore .java files in jar
482 //// throw newNotPresentException();
484 // // put the info now, because getting the contents requires it
485 // JavaModelManager.getJavaModelManager().putInfo(this, info);
486 // CompilationUnitElementInfo unitInfo = (CompilationUnitElementInfo) info;
488 // // generate structure
489 // CompilationUnitStructureRequestor requestor = new CompilationUnitStructureRequestor(this, unitInfo, newElements);
490 // IProblemFactory factory = new DefaultProblemFactory();
491 // SourceElementParser parser = new SourceElementParser(requestor, factory, new
492 // CompilerOptions(getJavaProject().getOptions(true)));
493 //// SourceElementParser parser = new SourceElementParser(requestor, factory);
494 // requestor.parser = parser;
495 // parser.parseCompilationUnit(this, false);
496 // if (isWorkingCopy()) {
497 // CompilationUnit original = (CompilationUnit) getOriginalElement();
498 // // might be IResource.NULL_STAMP if original does not exist
499 // unitInfo.timestamp = ((IFile) original.getResource()).getModificationStamp();
501 // return unitInfo.isStructureKnown();
505 * @see ICompilationUnit#getAllTypes()
507 public IType[] getAllTypes() throws JavaModelException {
508 IJavaElement[] types = getTypes();
510 ArrayList allTypes = new ArrayList(types.length);
511 ArrayList typesToTraverse = new ArrayList(types.length);
512 for (i = 0; i < types.length; i++) {
513 typesToTraverse.add(types[i]);
515 while (!typesToTraverse.isEmpty()) {
516 IType type = (IType) typesToTraverse.get(0);
517 typesToTraverse.remove(type);
519 types = type.getTypes();
520 for (i = 0; i < types.length; i++) {
521 typesToTraverse.add(types[i]);
524 IType[] arrayOfAllTypes = new IType[allTypes.size()];
525 allTypes.toArray(arrayOfAllTypes);
526 return arrayOfAllTypes;
530 * @see IMember#getCompilationUnit()
532 public ICompilationUnit getCompilationUnit() {
537 * @see net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit#getContents()
539 public char[] getContents() {
541 IBuffer buffer = this.getBuffer();
542 return buffer == null ? null : buffer.getCharacters();
543 } catch (JavaModelException e) {
544 return CharOperation.NO_CHAR;
549 * A compilation unit has a corresponding resource unless it is contained in a jar.
551 * @see IJavaElement#getCorrespondingResource()
553 public IResource getCorrespondingResource() throws JavaModelException {
554 IPackageFragmentRoot root = (IPackageFragmentRoot) getParent().getParent();
555 if (root.isArchive()) {
558 return getUnderlyingResource();
563 * @see ICompilationUnit#getElementAt(int)
565 public IJavaElement getElementAt(int position) throws JavaModelException {
567 IJavaElement e = getSourceElementAt(position);
578 public int getElementType() {
579 return COMPILATION_UNIT;
582 public char[] getFileName() {
583 return getElementName().toCharArray();
588 public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner workingCopyOwner) {
589 switch (token.charAt(0)) {
591 return getHandleUpdatingCountFromMemento(memento, workingCopyOwner);
592 case JEM_IMPORTDECLARATION:
593 JavaElement container = (JavaElement)getImportContainer();
594 return container.getHandleFromMemento(token, memento, workingCopyOwner);
595 case JEM_PACKAGEDECLARATION:
596 String pkgName = memento.nextToken();
597 JavaElement pkgDecl = (JavaElement)getPackageDeclaration(pkgName);
598 return pkgDecl.getHandleFromMemento(memento, workingCopyOwner);
600 String typeName = memento.nextToken();
601 JavaElement type = (JavaElement)getType(typeName);
602 return type.getHandleFromMemento(memento, workingCopyOwner);
608 * @see JavaElement#getHandleMementoDelimiter()
610 protected char getHandleMementoDelimiter() {
611 return JavaElement.JEM_COMPILATIONUNIT;
614 * @see ICompilationUnit#getImport(String)
616 public IImportDeclaration getImport(String importName) {
617 return new ImportDeclaration((ImportContainer)getImportContainer(), importName);
620 * @see ICompilationUnit#getImportContainer()
622 public IImportContainer getImportContainer() {
623 return new ImportContainer(this);
628 * @see ICompilationUnit#getImports()
630 public IImportDeclaration[] getImports() throws JavaModelException {
631 IImportContainer container= getImportContainer();
632 if (container.exists()) {
633 IJavaElement[] elements= container.getChildren();
634 IImportDeclaration[] imprts= new IImportDeclaration[elements.length];
635 System.arraycopy(elements, 0, imprts, 0, elements.length);
637 } else if (!exists()) {
638 throw newNotPresentException();
640 return new IImportDeclaration[0];
646 * @see net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit#getMainTypeName()
648 public char[] getMainTypeName() {
649 String name = getElementName();
651 name = name.substring(0, name.length() - 5);
652 return name.toCharArray();
656 * @see IWorkingCopy#getOriginal(IJavaElement)
659 public IJavaElement getOriginal(IJavaElement workingCopyElement) {
660 // backward compatibility
661 if (!isWorkingCopy())
663 CompilationUnit cu = (CompilationUnit) workingCopyElement.getAncestor(COMPILATION_UNIT);
664 if (cu == null || !this.owner.equals(cu.owner)) {
668 return workingCopyElement.getPrimaryElement();
672 * @see IWorkingCopy#getOriginalElement()
675 public IJavaElement getOriginalElement() {
676 // backward compatibility
677 if (!isWorkingCopy())
680 return getPrimaryElement();
684 * @see ICompilationUnit#getOwner()
686 public WorkingCopyOwner getOwner() {
687 return isPrimary() || !isWorkingCopy() ? null : this.owner;
691 * @see ICompilationUnit#getPackageDeclaration(String)
693 public IPackageDeclaration getPackageDeclaration(String name) {
694 return new PackageDeclaration(this, name);
698 * @see ICompilationUnit#getPackageDeclarations()
700 public IPackageDeclaration[] getPackageDeclarations() throws JavaModelException {
701 ArrayList list = getChildrenOfType(PACKAGE_DECLARATION);
702 IPackageDeclaration[] array = new IPackageDeclaration[list.size()];
708 * @see net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit#getPackageName()
710 public char[][] getPackageName() {
715 * @see IJavaElement#getPath()
717 public IPath getPath() {
718 PackageFragmentRoot root = this.getPackageFragmentRoot();
719 if (root.isArchive()) {
720 return root.getPath();
722 return this.getParent().getPath().append(this.getElementName());
727 * 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
730 public JavaModelManager.PerWorkingCopyInfo getPerWorkingCopyInfo() {
731 return JavaModelManager.getJavaModelManager().getPerWorkingCopyInfo(this, false/* don't create */, false/* don't record usage */,
732 null/* no problem requestor needed */);
736 * @see ICompilationUnit#getPrimary()
738 public ICompilationUnit getPrimary() {
739 return (ICompilationUnit) getPrimaryElement(true);
743 * @see JavaElement#getPrimaryElement(boolean)
745 public IJavaElement getPrimaryElement(boolean checkOwner) {
746 if (checkOwner && isPrimary())
748 return new CompilationUnit((PackageFragment) getParent(), getElementName(), DefaultWorkingCopyOwner.PRIMARY);
752 * @see IJavaElement#getResource()
754 public IResource getResource() {
755 PackageFragmentRoot root = this.getPackageFragmentRoot();
756 if (root.isArchive()) {
757 return root.getResource();
759 return ((IContainer) this.getParent().getResource()).getFile(new Path(this.getElementName()));
764 * @see ISourceReference#getSource()
766 public String getSource() throws JavaModelException {
767 IBuffer buffer = getBuffer();
769 return ""; //$NON-NLS-1$
770 return buffer.getContents();
774 * @see ISourceReference#getSourceRange()
776 public ISourceRange getSourceRange() throws JavaModelException {
777 return ((CompilationUnitElementInfo) getElementInfo()).getSourceRange();
781 * @see ICompilationUnit#getType(String)
783 public IType getType(String name) {
784 return new SourceType(this, name);
788 * @see ICompilationUnit#getTypes()
790 public IType[] getTypes() throws JavaModelException {
791 ArrayList list = getChildrenOfType(TYPE);
792 IType[] array = new IType[list.size()];
800 public IResource getUnderlyingResource() throws JavaModelException {
801 if (isWorkingCopy() && !isPrimary())
803 return super.getUnderlyingResource();
807 // * @see IWorkingCopy#getSharedWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)
809 //public IJavaElement getSharedWorkingCopy(IProgressMonitor pm, IBufferFactory factory, IProblemRequestor problemRequestor)
810 // throws JavaModelException {
812 // // if factory is null, default factory must be used
813 // if (factory == null) factory = this.getBufferManager().getDefaultBufferFactory();
815 // JavaModelManager manager = JavaModelManager.getJavaModelManager();
817 // // In order to be shared, working copies have to denote the same compilation unit
818 // // AND use the same buffer factory.
819 // // Assuming there is a little set of buffer factories, then use a 2 level Map cache.
820 // Map sharedWorkingCopies = manager.sharedWorkingCopies;
822 // Map perFactoryWorkingCopies = (Map) sharedWorkingCopies.get(factory);
823 // if (perFactoryWorkingCopies == null){
824 // perFactoryWorkingCopies = new HashMap();
825 // sharedWorkingCopies.put(factory, perFactoryWorkingCopies);
827 // WorkingCopy workingCopy = (WorkingCopy)perFactoryWorkingCopies.get(this);
828 // if (workingCopy != null) {
829 // workingCopy.useCount++;
831 // if (SHARED_WC_VERBOSE) {
832 // System.out.println("Incrementing use count of shared working copy " + workingCopy.toStringWithAncestors()); //$NON-NLS-1$
835 // return workingCopy;
837 // CreateWorkingCopyOperation op = new CreateWorkingCopyOperation(this, perFactoryWorkingCopies, factory, problemRequestor);
838 // runOperation(op, pm);
839 // return op.getResultElements()[0];
843 // * @see IWorkingCopy#getWorkingCopy()
845 //public IJavaElement getWorkingCopy() throws JavaModelException {
846 // return this.getWorkingCopy(null, null, null);
850 // * @see IWorkingCopy#getWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)
852 //public IJavaElement getWorkingCopy(IProgressMonitor pm, IBufferFactory factory, IProblemRequestor problemRequestor) throws
853 // JavaModelException {
854 // CreateWorkingCopyOperation op = new CreateWorkingCopyOperation(this, null, factory, problemRequestor);
855 // runOperation(op, pm);
856 // return op.getResultElements()[0];
859 * @see IWorkingCopy#getSharedWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)
862 public IJavaElement getSharedWorkingCopy(IProgressMonitor pm, IBufferFactory factory, IProblemRequestor problemRequestor)
863 throws JavaModelException {
865 // if factory is null, default factory must be used
867 factory = this.getBufferManager().getDefaultBufferFactory();
869 return getWorkingCopy(BufferFactoryWrapper.create(factory), problemRequestor, pm);
873 * @see IWorkingCopy#getWorkingCopy()
876 public IJavaElement getWorkingCopy() throws JavaModelException {
877 return getWorkingCopy(null);
881 * @see ICompilationUnit#getWorkingCopy(IProgressMonitor)
883 public ICompilationUnit getWorkingCopy(IProgressMonitor monitor) throws JavaModelException {
884 return getWorkingCopy(new WorkingCopyOwner() {/* non shared working copy */
885 }, null/* no problem requestor */, monitor);
889 * @see IWorkingCopy#getWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)
892 public IJavaElement getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory, IProblemRequestor problemRequestor)
893 throws JavaModelException {
894 return getWorkingCopy(BufferFactoryWrapper.create(factory), problemRequestor, monitor);
898 * @see ICompilationUnit#getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)
900 public ICompilationUnit getWorkingCopy(WorkingCopyOwner workingCopyOwner, IProblemRequestor problemRequestor,
901 IProgressMonitor monitor) throws JavaModelException {
905 JavaModelManager manager = JavaModelManager.getJavaModelManager();
907 CompilationUnit workingCopy = new CompilationUnit((PackageFragment) getParent(), getElementName(), workingCopyOwner);
908 JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = manager.getPerWorkingCopyInfo(workingCopy, false/* don't create */,
909 true/* record usage */, null/* not used since don't create */);
910 if (perWorkingCopyInfo != null) {
911 return perWorkingCopyInfo.getWorkingCopy(); // return existing handle instead of the one created above
913 BecomeWorkingCopyOperation op = new BecomeWorkingCopyOperation(workingCopy, problemRequestor);
914 op.runOperation(monitor);
919 * If I am not open, return true to avoid parsing.
921 * @see IParent#hasChildren()
923 public boolean hasChildren() throws JavaModelException {
925 // return getChildren().length > 0;
933 * @see Openable#hasBuffer()
935 protected boolean hasBuffer() {
940 * @see ICompilationUnit#hasResourceChanged()
942 public boolean hasResourceChanged() {
943 if (!isWorkingCopy())
946 // if resource got deleted, then #getModificationStamp() will answer IResource.NULL_STAMP, which is always different from the
949 Object info = JavaModelManager.getJavaModelManager().getInfo(this);
952 return ((CompilationUnitElementInfo) info).timestamp != getResource().getModificationStamp();
956 * @see IWorkingCopy#isBasedOn(IResource)
959 public boolean isBasedOn(IResource resource) {
960 if (!isWorkingCopy())
962 if (!getResource().equals(resource))
964 return !hasResourceChanged();
968 * @see IOpenable#isConsistent()
970 public boolean isConsistent() {
971 return JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().get(this) == null;
978 public boolean isOpen() {
979 Object info = JavaModelManager.getJavaModelManager().getInfo(this);
980 return info != null && ((CompilationUnitElementInfo) info).isOpen();
983 public boolean isPrimary() {
984 return this.owner == DefaultWorkingCopyOwner.PRIMARY;
988 * @see Openable#isSourceElement()
990 protected boolean isSourceElement() {
994 protected boolean isValidCompilationUnit() {
995 IPackageFragmentRoot root = getPackageFragmentRoot();
997 if (root.getKind() != IPackageFragmentRoot.K_SOURCE)
999 } catch (JavaModelException e) {
1002 // IResource resource = getResource();
1003 // if (resource != null) {
1004 // char[][] inclusionPatterns = ((PackageFragmentRoot)root).fullInclusionPatternChars();
1005 // char[][] exclusionPatterns = ((PackageFragmentRoot)root).fullExclusionPatternChars();
1006 // if (ProjectPrefUtil.isExcluded(resource, inclusionPatterns, exclusionPatterns)) return false;
1008 if (!Util.isValidCompilationUnitName(getElementName()))
1014 * @see ICompilationUnit#isWorkingCopy()
1016 public boolean isWorkingCopy() {
1017 // For backward compatibility, non primary working copies are always returning true; in removal
1018 // delta, clients can still check that element was a working copy before being discarded.
1019 return !isPrimary() || getPerWorkingCopyInfo() != null;
1023 * @see IOpenable#makeConsistent(IProgressMonitor)
1025 public void makeConsistent(IProgressMonitor monitor) throws JavaModelException {
1026 makeConsistent(false/* don't create AST */, 0, monitor);
1029 public Object makeConsistent(boolean createAST, int astLevel, IProgressMonitor monitor) throws JavaModelException {
1033 // create a new info and make it the current info
1034 // (this will remove the info and its children just before storing the new infos)
1036 // ASTHolderCUInfo info = new ASTHolderCUInfo();
1037 // info.astLevel = astLevel;
1038 // openWhenClosed(info, monitor);
1039 // net.sourceforge.phpdt.core.dom.CompilationUnit result = info.ast;
1043 openWhenClosed(createElementInfo(), monitor);
1048 //public net.sourceforge.phpdt.core.dom.CompilationUnit makeConsistent(boolean createAST, int astLevel, IProgressMonitor monitor)
1049 // throws JavaModelException {
1050 // if (isConsistent()) return null;
1052 // // create a new info and make it the current info
1053 // // (this will remove the info and its children just before storing the new infos)
1055 // ASTHolderCUInfo info = new ASTHolderCUInfo();
1056 // info.astLevel = astLevel;
1057 // openWhenClosed(info, monitor);
1058 // net.sourceforge.phpdt.core.dom.CompilationUnit result = info.ast;
1062 // openWhenClosed(createElementInfo(), monitor);
1068 * @see ISourceManipulation#move(IJavaElement, IJavaElement, String, boolean, IProgressMonitor)
1070 public void move(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor)
1071 throws JavaModelException {
1072 if (container == null) {
1073 throw new IllegalArgumentException(Util.bind("operation.nullContainer")); //$NON-NLS-1$
1075 IJavaElement[] elements = new IJavaElement[] { this };
1076 IJavaElement[] containers = new IJavaElement[] { container };
1078 String[] renamings = null;
1079 if (rename != null) {
1080 renamings = new String[] { rename };
1082 getJavaModel().move(elements, containers, null, renamings, force, monitor);
1086 // * @see Openable#openBuffer(IProgressMonitor)
1088 //protected IBuffer openBuffer(IProgressMonitor pm) throws JavaModelException {
1090 // // create buffer - compilation units only use default buffer factory
1091 // BufferManager bufManager = getBufferManager();
1092 // IBuffer buffer = getBufferFactory().createBuffer(this);
1093 // if (buffer == null) return null;
1095 // // set the buffer source
1096 // if (buffer.getCharacters() == null){
1097 // IFile file = (IFile)this.getResource();
1098 // if (file == null || !file.exists()) throw newNotPresentException();
1099 // buffer.setContents(ProjectPrefUtil.getResourceContentsAsCharArray(file));
1102 // // add buffer to buffer cache
1103 // bufManager.addBuffer(buffer);
1105 // // listen to buffer changes
1106 // buffer.addBufferChangedListener(this);
1111 * @see Openable#openBuffer(IProgressMonitor, Object)
1113 protected IBuffer openBuffer(IProgressMonitor pm, Object info) throws JavaModelException {
1116 boolean isWorkingCopy = isWorkingCopy();
1117 IBuffer buffer = isWorkingCopy ? this.owner.createBuffer(this) : BufferManager.getDefaultBufferManager().createBuffer(this);
1121 // set the buffer source
1122 if (buffer.getCharacters() == null) {
1123 if (isWorkingCopy) {
1124 ICompilationUnit original;
1126 && (original = new CompilationUnit((PackageFragment) getParent(), getElementName(), DefaultWorkingCopyOwner.PRIMARY))
1128 buffer.setContents(original.getSource());
1130 IFile file = (IFile) getResource();
1131 if (file == null || !file.exists()) {
1132 // initialize buffer with empty contents
1133 buffer.setContents(CharOperation.NO_CHAR);
1135 buffer.setContents(Util.getResourceContentsAsCharArray(file));
1139 IFile file = (IFile) this.getResource();
1140 if (file == null || !file.exists())
1141 throw newNotPresentException();
1142 buffer.setContents(Util.getResourceContentsAsCharArray(file));
1146 // add buffer to buffer cache
1147 BufferManager bufManager = getBufferManager();
1148 bufManager.addBuffer(buffer);
1150 // listen to buffer changes
1151 buffer.addBufferChangedListener(this);
1157 * @see Openable#openParent
1159 protected void openParent(Object childInfo, HashMap newElements, IProgressMonitor pm) throws JavaModelException {
1161 super.openParent(childInfo, newElements, pm);
1162 } catch (JavaModelException e) {
1163 // allow parent to not exist for working copies defined outside classpath
1164 if (!isWorkingCopy() && !e.isDoesNotExist()) {
1171 * @see ICompilationUnit#reconcile()
1174 public IMarker[] reconcile() throws JavaModelException {
1175 reconcile(NO_AST, false/* don't force problem detection */, null/* use primary owner */, null/* no progress monitor */);
1180 * @see ICompilationUnit#reconcile(int, boolean, WorkingCopyOwner, IProgressMonitor)
1182 public void reconcile(boolean forceProblemDetection, IProgressMonitor monitor) throws JavaModelException {
1183 reconcile(NO_AST, forceProblemDetection, null/* use primary owner */, monitor);
1187 * @see ICompilationUnit#reconcile(int, boolean, WorkingCopyOwner, IProgressMonitor)
1190 //public net.sourceforge.phpdt.core.dom.CompilationUnit reconcile(
1191 public Object reconcile(int astLevel, boolean forceProblemDetection, WorkingCopyOwner workingCopyOwner, IProgressMonitor monitor)
1192 throws JavaModelException {
1194 if (!isWorkingCopy())
1195 return null; // Reconciling is not supported on non working copies
1196 if (workingCopyOwner == null)
1197 workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
1199 boolean createAST = false;
1200 // if (astLevel == AST.JLS2) {
1201 // // client asking for level 2 AST; these are supported
1202 // createAST = true;
1203 // } else if (astLevel == AST.JLS3) {
1204 // // client asking for level 3 ASTs; these are not supported
1205 // // TODO (jerome) - these should also be supported in 1.5 stream
1206 // createAST = false;
1208 // // client asking for no AST (0) or unknown ast level
1209 // // either way, request denied
1210 // createAST = false;
1212 ReconcileWorkingCopyOperation op = new ReconcileWorkingCopyOperation(this, createAST, astLevel, forceProblemDetection,
1214 op.runOperation(monitor);
1220 * @see ISourceManipulation#rename(String, boolean, IProgressMonitor)
1222 public void rename(String name, boolean force, IProgressMonitor monitor) throws JavaModelException {
1224 throw new IllegalArgumentException(Util.bind("operation.nullName")); //$NON-NLS-1$
1226 IJavaElement[] elements = new IJavaElement[] { this };
1227 IJavaElement[] dests = new IJavaElement[] { this.getParent() };
1228 String[] renamings = new String[] { name };
1229 getJavaModel().rename(elements, dests, renamings, force, monitor);
1233 * @see ICompilationUnit
1235 public void restore() throws JavaModelException {
1237 if (!isWorkingCopy())
1240 CompilationUnit original = (CompilationUnit) getOriginalElement();
1241 IBuffer buffer = this.getBuffer();
1244 buffer.setContents(original.getContents());
1245 updateTimeStamp(original);
1246 makeConsistent(null);
1250 // * @see ICodeAssist#codeComplete(int, ICodeCompletionRequestor)
1251 // * @deprecated - use codeComplete(int, ICompletionRequestor)
1253 //public void codeComplete(int offset, final ICodeCompletionRequestor requestor) throws JavaModelException {
1255 // if (requestor == null){
1256 // codeComplete(offset, (ICompletionRequestor)null);
1261 // new ICompletionRequestor(){
1262 // public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][]
1263 // parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int
1266 // public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int
1267 // completionEnd, int relevance) {
1268 // requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd);
1270 // public void acceptError(IProblem error) {
1271 // if (true) return; // was disabled in 1.0
1274 // IMarker marker = ResourcesPlugin.getWorkspace().getRoot().createMarker(IJavaModelMarker.TRANSIENT_PROBLEM);
1275 // marker.setAttribute(IJavaModelMarker.ID, error.getID());
1276 // marker.setAttribute(IMarker.CHAR_START, error.getSourceStart());
1277 // marker.setAttribute(IMarker.CHAR_END, error.getSourceEnd() + 1);
1278 // marker.setAttribute(IMarker.LINE_NUMBER, error.getSourceLineNumber());
1279 // marker.setAttribute(IMarker.MESSAGE, error.getMessage());
1280 // marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
1281 // requestor.acceptError(marker);
1282 // } catch(CoreException e){
1285 // public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, char[] typePackageName, char[]
1286 // typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
1287 // requestor.acceptField(declaringTypePackageName, declaringTypeName, name, typePackageName, typeName, completionName, modifiers,
1288 // completionStart, completionEnd);
1290 // public void acceptInterface(char[] packageName,char[] interfaceName,char[] completionName,int modifiers,int completionStart,int
1291 // completionEnd, int relevance) {
1292 // requestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart, completionEnd);
1294 // public void acceptKeyword(char[] keywordName,int completionStart,int completionEnd, int relevance){
1295 // requestor.acceptKeyword(keywordName, completionStart, completionEnd);
1297 // public void acceptLabel(char[] labelName,int completionStart,int completionEnd, int relevance){
1298 // requestor.acceptLabel(labelName, completionStart, completionEnd);
1300 // public void acceptLocalVariable(char[] name,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int
1301 // completionEnd, int relevance){
1304 // public void acceptMethod(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][]
1305 // parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[]
1306 // returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
1307 // // skip parameter names
1308 // requestor.acceptMethod(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames,
1309 // returnTypePackageName, returnTypeName, completionName, modifiers, completionStart, completionEnd);
1311 // public void acceptMethodDeclaration(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][]
1312 // parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[]
1313 // returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
1316 // public void acceptModifier(char[] modifierName,int completionStart,int completionEnd, int relevance){
1317 // requestor.acceptModifier(modifierName, completionStart, completionEnd);
1319 // public void acceptPackage(char[] packageName,char[] completionName,int completionStart,int completionEnd, int relevance){
1320 // requestor.acceptPackage(packageName, completionName, completionStart, completionEnd);
1322 // public void acceptType(char[] packageName,char[] typeName,char[] completionName,int completionStart,int completionEnd, int
1324 // requestor.acceptType(packageName, typeName, completionName, completionStart, completionEnd);
1326 // public void acceptVariableName(char[] typePackageName,char[] typeName,char[] name,char[] completionName,int completionStart,int
1327 // completionEnd, int relevance){
1333 // * @see JavaElement#rootedAt(IJavaProject)
1335 //public IJavaElement rootedAt(IJavaProject project) {
1337 // new CompilationUnit(
1338 // (IPackageFragment)((JavaElement)parent).rootedAt(project),
1343 * Assume that this is a working copy
1345 protected void updateTimeStamp(CompilationUnit original) throws JavaModelException {
1346 long timeStamp = ((IFile) original.getResource()).getModificationStamp();
1347 if (timeStamp == IResource.NULL_STAMP) {
1348 throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_RESOURCE));
1350 ((CompilationUnitElementInfo) getElementInfo()).timestamp = timeStamp;