50c264c75ffaa80e311171a4f8c4f42ed1eb97fc
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / CompilationUnit.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
12
13 import java.util.ArrayList;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.Map;
17
18 import net.sourceforge.phpdt.core.IBuffer;
19 import net.sourceforge.phpdt.core.IBufferFactory;
20 import net.sourceforge.phpdt.core.ICompilationUnit;
21 import net.sourceforge.phpdt.core.IJavaElement;
22 import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
23 import net.sourceforge.phpdt.core.IJavaProject;
24 import net.sourceforge.phpdt.core.IMember;
25 import net.sourceforge.phpdt.core.IMethod;
26 import net.sourceforge.phpdt.core.IOpenable;
27 import net.sourceforge.phpdt.core.IPackageDeclaration;
28 import net.sourceforge.phpdt.core.IPackageFragment;
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.compiler.CharOperation;
40 import net.sourceforge.phpdt.core.jdom.IDOMNode;
41 import net.sourceforge.phpdt.internal.compiler.IProblemFactory;
42 import net.sourceforge.phpdt.internal.compiler.SourceElementParser;
43 import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
44 import net.sourceforge.phpdt.internal.compiler.problem.DefaultProblemFactory;
45
46 import org.eclipse.core.resources.IContainer;
47 import org.eclipse.core.resources.IFile;
48 import org.eclipse.core.resources.IMarker;
49 import org.eclipse.core.resources.IResource;
50 import org.eclipse.core.runtime.IPath;
51 import org.eclipse.core.runtime.IProgressMonitor;
52 import org.eclipse.core.runtime.Path;
53
54 /** 
55  * @see ICompilationUnit
56  */
57
58 public class CompilationUnit extends Openable implements ICompilationUnit, net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit {
59         
60         public static boolean SHARED_WC_VERBOSE = false;
61         
62         // TODO: Remove when we are certain that every client is ready for this fix
63         public static final boolean FIX_BUG25184 = true;
64
65 /**
66  * Constructs a handle to a compilation unit with the given name in the
67  * specified package.
68  *
69  * @exception IllegalArgumentException if the name of the compilation unit
70  * does not end with ".java"
71  */
72 protected CompilationUnit(IPackageFragment parent, String name) {
73         super(COMPILATION_UNIT, parent, name);
74         if (!Util.isJavaFileName(name)) {
75                 throw new IllegalArgumentException(net.sourceforge.phpdt.internal.core.Util.bind("convention.unit.notJavaName")); //$NON-NLS-1$
76         }
77 }
78 /**
79  * Accepts the given visitor onto the parsed tree of this compilation unit, after
80  * having runned the name resolution.
81  * The visitor's corresponding <code>visit</code> method is called with the
82  * corresponding parse tree. If the visitor returns <code>true</code>, this method
83  * visits this parse node's members.
84  *
85  * @param visitor the visitor
86  * @exception JavaModelException if this method fails. Reasons include:
87  * <ul>
88  * <li> This element does not exist.</li>
89  * <li> The visitor failed with this exception.</li>
90  * </ul>
91  */
92 //public void accept(IAbstractSyntaxTreeVisitor visitor) throws JavaModelException {
93 //      CompilationUnitVisitor.visit(this, visitor);
94 //} 
95
96 protected void buildStructure(OpenableElementInfo info, IProgressMonitor monitor) throws JavaModelException {
97
98         if (monitor != null && monitor.isCanceled()) return;
99
100         // remove existing (old) infos
101         removeInfo();
102
103         HashMap newElements = new HashMap(11);
104         info.setIsStructureKnown(generateInfos(info, monitor, newElements, getResource()));
105         JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
106         for (Iterator iter = newElements.keySet().iterator(); iter.hasNext();) {
107                 IJavaElement key = (IJavaElement) iter.next();
108                 Object value = newElements.get(key);
109                 JavaModelManager.getJavaModelManager().putInfo(key, value);
110         }
111         // add the info for this at the end, to ensure that a getInfo cannot reply null in case the LRU cache needs
112         // to be flushed. Might lead to performance issues.
113         // see PR 1G2K5S7: ITPJCORE:ALL - NPE when accessing source for a binary type
114         JavaModelManager.getJavaModelManager().putInfo(this, info);     
115 }
116
117 ///**
118 // * @see ICodeAssist#codeComplete(int, ICompletionRequestor)
119 // */
120 //public void codeComplete(int offset, ICompletionRequestor requestor) throws JavaModelException {
121 //      codeComplete(this, isWorkingCopy() ? (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) getOriginalElement() : this, offset, requestor);
122 //}
123 /**
124  * @see ICodeAssist#codeSelect(int, int)
125  */
126 //public IJavaElement[] codeSelect(int offset, int length) throws JavaModelException {
127 //      return super.codeSelect(this, offset, length);
128 //}
129 /**
130  * @see IWorkingCopy#commit(boolean, IProgressMonitor)
131  */
132 public void commit(boolean force, IProgressMonitor monitor) throws JavaModelException {
133         throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, this));
134 }
135 /**
136  * @see ISourceManipulation#copy(IJavaElement, IJavaElement, String, boolean, IProgressMonitor)
137  */
138 public void copy(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor) throws JavaModelException {
139         if (container == null) {
140                 throw new IllegalArgumentException(Util.bind("operation.nullContainer")); //$NON-NLS-1$
141         }
142         IJavaElement[] elements = new IJavaElement[] {this};
143         IJavaElement[] containers = new IJavaElement[] {container};
144         String[] renamings = null;
145         if (rename != null) {
146                 renamings = new String[] {rename};
147         }
148         getJavaModel().copy(elements, containers, null, renamings, force, monitor);
149 }
150 /**
151  * Returns a new element info for this element.
152  */
153 protected OpenableElementInfo createElementInfo() {
154         return new CompilationUnitElementInfo();
155 }
156 ///**
157 // * @see ICompilationUnit#createImport(String, IJavaElement, IProgressMonitor)
158 // */
159 //public IImportDeclaration createImport(String name, IJavaElement sibling, IProgressMonitor monitor) throws JavaModelException {
160 //      CreateImportOperation op = new CreateImportOperation(name, this);
161 //      if (sibling != null) {
162 //              op.createBefore(sibling);
163 //      }
164 //      runOperation(op, monitor);
165 //      return getImport(name);
166 //}
167 /**
168  * @see ICompilationUnit#createPackageDeclaration(String, IProgressMonitor)
169  */
170 public IPackageDeclaration createPackageDeclaration(String name, IProgressMonitor monitor) throws JavaModelException {
171         
172         CreatePackageDeclarationOperation op= new CreatePackageDeclarationOperation(name, this);
173         runOperation(op, monitor);
174         return getPackageDeclaration(name);
175 }
176 ///**
177 // * @see ICompilationUnit#createType(String, IJavaElement, boolean, IProgressMonitor)
178 // */
179 //public IType createType(String content, IJavaElement sibling, boolean force, IProgressMonitor monitor) throws JavaModelException {
180 //      if (!exists()) {
181 //              //autogenerate this compilation unit
182 //              IPackageFragment pkg = (IPackageFragment) getParent();
183 //              String source = ""; //$NON-NLS-1$
184 //              if (pkg.getElementName().length() > 0) {
185 //                      //not the default package...add the package declaration
186 //                      source = "package " + pkg.getElementName() + ";"  + org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR + org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR; //$NON-NLS-1$ //$NON-NLS-2$
187 //              }
188 //              CreateCompilationUnitOperation op = new CreateCompilationUnitOperation(pkg, fName, source, force);
189 //              runOperation(op, monitor);
190 //      }
191 //      CreateTypeOperation op = new CreateTypeOperation(this, content, force);
192 //      if (sibling != null) {
193 //              op.createBefore(sibling);
194 //      }
195 //      runOperation(op, monitor);
196 //      return (IType) op.getResultElements()[0];
197 //}
198 /**
199  * @see ISourceManipulation#delete(boolean, IProgressMonitor)
200  */
201 public void delete(boolean force, IProgressMonitor monitor) throws JavaModelException {
202         IJavaElement[] elements= new IJavaElement[] {this};
203         getJavaModel().delete(elements, force, monitor);
204 }
205 /**
206  * This is not a working copy, do nothing.
207  *
208  * @see IWorkingCopy#destroy()
209  */
210 public void destroy() {
211 }
212
213
214 /**
215  * Returns true if this handle represents the same Java element
216  * as the given handle.
217  *
218  * <p>Compilation units must also check working copy state;
219  *
220  * @see Object#equals(java.lang.Object)
221  */
222 public boolean equals(Object o) {
223         return super.equals(o) && !((ICompilationUnit)o).isWorkingCopy();
224 }
225 /**
226  * @see JavaElement#equalsDOMNode(IDOMNode)
227  */
228 protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException {
229         String name = getElementName();
230         if (node.getNodeType() == IDOMNode.COMPILATION_UNIT && name != null ) {
231                 String nodeName = node.getName();
232                 if (nodeName == null) return false;             
233                 if (name.equals(nodeName)) {
234                         return true;
235                 } else {
236                         // iterate through all the types inside the receiver and see if one of them can fit
237                         IType[] types = getTypes();
238                         String typeNodeName = nodeName.substring(0, nodeName.indexOf(".java")); //$NON-NLS-1$
239                         for (int i = 0, max = types.length; i < max; i++) {
240                                 if (types[i].getElementName().equals(typeNodeName)) {
241                                         return true;
242                                 }
243                         }
244                 }
245         }
246         return false;
247 }
248 /**
249  * @see IWorkingCopy#findElements(IJavaElement)
250  */
251 public IJavaElement[] findElements(IJavaElement element) {
252         ArrayList children = new ArrayList();
253         while (element != null && element.getElementType() != IJavaElement.COMPILATION_UNIT) {
254                 children.add(element);
255                 element = element.getParent();
256         }
257         if (element == null) return null;
258         IJavaElement currentElement = this;
259         for (int i = children.size()-1; i >= 0; i--) {
260                 IJavaElement child = (IJavaElement)children.get(i);
261                 switch (child.getElementType()) {
262 //                      case IJavaElement.PACKAGE_DECLARATION:
263 //                              currentElement = ((ICompilationUnit)currentElement).getPackageDeclaration(child.getElementName());
264 //                              break;
265 //                      case IJavaElement.IMPORT_CONTAINER:
266 //                              currentElement = ((ICompilationUnit)currentElement).getImportContainer();
267 //                              break;
268 //                      case IJavaElement.IMPORT_DECLARATION:
269 //                              currentElement = ((IImportContainer)currentElement).getImport(child.getElementName());
270 //                              break;
271                         case IJavaElement.TYPE:
272                                 if (currentElement.getElementType() == IJavaElement.COMPILATION_UNIT) {
273                                         currentElement = ((ICompilationUnit)currentElement).getType(child.getElementName());
274                                 } else {
275                                         currentElement = ((IType)currentElement).getType(child.getElementName());
276                                 }
277                                 break;
278 //                      case IJavaElement.INITIALIZER:
279 //                              currentElement = ((IType)currentElement).getInitializer(((JavaElement)child).getOccurrenceCount());
280 //                              break;
281                         case IJavaElement.FIELD:
282                                 currentElement = ((IType)currentElement).getField(child.getElementName());
283                                 break;
284                         case IJavaElement.METHOD:
285                                 return ((IType)currentElement).findMethods((IMethod)child);
286                 }
287                 
288         }
289         if (currentElement != null && currentElement.exists()) {
290                 return new IJavaElement[] {currentElement};
291         } else {
292                 return null;
293         }
294 }
295 /**
296  * @see IWorkingCopy#findPrimaryType()
297  */
298 public IType findPrimaryType() {
299         String typeName = Signature.getQualifier(this.getElementName());
300         IType primaryType= this.getType(typeName);
301         if (primaryType.exists()) {
302                 return primaryType;
303         }
304         return null;
305 }
306
307 /**
308  * @see IWorkingCopy#findSharedWorkingCopy(IBufferFactory)
309  */
310 public IJavaElement findSharedWorkingCopy(IBufferFactory factory) {
311
312         // if factory is null, default factory must be used
313         if (factory == null) factory = this.getBufferManager().getDefaultBufferFactory();
314
315         // In order to be shared, working copies have to denote the same compilation unit 
316         // AND use the same buffer factory.
317         // Assuming there is a little set of buffer factories, then use a 2 level Map cache.
318         Map sharedWorkingCopies = JavaModelManager.getJavaModelManager().sharedWorkingCopies;
319         
320         Map perFactoryWorkingCopies = (Map) sharedWorkingCopies.get(factory);
321         if (perFactoryWorkingCopies == null) return null;
322         return (WorkingCopy)perFactoryWorkingCopies.get(this);
323 }
324
325 protected boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
326
327 //      if (getParent() instanceof JarPackageFragment) {
328 //              // ignore .java files in jar
329 //              throw newNotPresentException();
330 //      } else {
331                 // put the info now, because getting the contents requires it
332                 JavaModelManager.getJavaModelManager().putInfo(this, info);
333                 CompilationUnitElementInfo unitInfo = (CompilationUnitElementInfo) info;
334
335                 // generate structure
336                 CompilationUnitStructureRequestor requestor = new CompilationUnitStructureRequestor(this, unitInfo, newElements);
337                 IProblemFactory factory = new DefaultProblemFactory();
338                 SourceElementParser parser = new SourceElementParser(requestor, factory, new CompilerOptions(getJavaProject().getOptions(true)));
339 //        SourceElementParser parser = new SourceElementParser(requestor, factory);
340                 requestor.parser = parser;
341                 parser.parseCompilationUnit(this, false);
342                 if (isWorkingCopy()) {
343                         CompilationUnit original = (CompilationUnit) getOriginalElement();
344                         // might be IResource.NULL_STAMP if original does not exist
345                         unitInfo.fTimestamp = ((IFile) original.getResource()).getModificationStamp();
346                 }
347                 return unitInfo.isStructureKnown();
348 //      }
349 }
350 /**
351  * @see ICompilationUnit#getAllTypes()
352  */
353 public IType[] getAllTypes() throws JavaModelException {
354         IJavaElement[] types = getTypes();
355         int i;
356         ArrayList allTypes = new ArrayList(types.length);
357         ArrayList typesToTraverse = new ArrayList(types.length);
358         for (i = 0; i < types.length; i++) {
359                 typesToTraverse.add(types[i]);
360         }
361         while (!typesToTraverse.isEmpty()) {
362                 IType type = (IType) typesToTraverse.get(0);
363                 typesToTraverse.remove(type);
364                 allTypes.add(type);
365                 types = type.getTypes();
366                 for (i = 0; i < types.length; i++) {
367                         typesToTraverse.add(types[i]);
368                 }
369         } 
370         IType[] arrayOfAllTypes = new IType[allTypes.size()];
371         allTypes.toArray(arrayOfAllTypes);
372         return arrayOfAllTypes;
373 }
374 /**
375  * @see IMember#getCompilationUnit()
376  */
377 public ICompilationUnit getCompilationUnit() {
378         return this;
379 }
380 /**
381  * @see org.eclipse.jdt.internal.compiler.env.ICompilationUnit#getContents()
382  */
383 public char[] getContents() {
384         try {
385                 IBuffer buffer = this.getBuffer();
386                 return buffer == null ? null : buffer.getCharacters();
387         } catch (JavaModelException e) {
388                 return CharOperation.NO_CHAR;
389         }
390 }
391 /**
392  * A compilation unit has a corresponding resource unless it is contained
393  * in a jar.
394  *
395  * @see IJavaElement#getCorrespondingResource()
396  */
397 public IResource getCorrespondingResource() throws JavaModelException {
398         IPackageFragmentRoot root= (IPackageFragmentRoot)getParent().getParent();
399         if (root.isArchive()) {
400                 return null;
401         } else {
402                 return getUnderlyingResource();
403         }
404 }
405 /**
406  * @see ICompilationUnit#getElementAt(int)
407  */
408 public IJavaElement getElementAt(int position) throws JavaModelException {
409
410         IJavaElement e= getSourceElementAt(position);
411         if (e == this) {
412                 return null;
413         } else {
414                 return e;
415         }
416 }
417 public char[] getFileName(){
418         return getElementName().toCharArray();
419 }
420 /**
421  * @see JavaElement#getHandleMementoDelimiter()
422  */
423 protected char getHandleMementoDelimiter() {
424         return JavaElement.JEM_COMPILATIONUNIT;
425 }
426 /**
427  * @see ICompilationUnit#getImport(String)
428  */
429 //public IImportDeclaration getImport(String name) {
430 //      return new ImportDeclaration(getImportContainer(), name);
431 //}
432 ///**
433 // * @see ICompilationUnit#getImportContainer()
434 // */
435 //public IImportContainer getImportContainer() {
436 //      return new ImportContainer(this);
437 //}
438
439
440 /**
441  * @see ICompilationUnit#getImports()
442  */
443 //public IImportDeclaration[] getImports() throws JavaModelException {
444 //      IImportContainer container= getImportContainer();
445 //      if (container.exists()) {
446 //              IJavaElement[] elements= container.getChildren();
447 //              IImportDeclaration[] imprts= new IImportDeclaration[elements.length];
448 //              System.arraycopy(elements, 0, imprts, 0, elements.length);
449 //              return imprts;
450 //      } else if (!exists()) {
451 //                      throw newNotPresentException();
452 //      } else {
453 //              return new IImportDeclaration[0];
454 //      }
455 //
456 //}
457 /**
458  * @see org.eclipse.jdt.internal.compiler.env.ICompilationUnit#getMainTypeName()
459  */
460 public char[] getMainTypeName(){
461         String name= getElementName();
462         //remove the .java
463         name= name.substring(0, name.length() - 5);
464         return name.toCharArray();
465 }
466 /**
467  * Returns <code>null</code>, this is not a working copy.
468  *
469  * @see IWorkingCopy#getOriginal(IJavaElement)
470  */
471 public IJavaElement getOriginal(IJavaElement workingCopyElement) {
472         return null;
473 }
474 /**
475  * Returns <code>null</code>, this is not a working copy.
476  *
477  * @see IWorkingCopy#getOriginalElement()
478  */
479 public IJavaElement getOriginalElement() {
480         return null;
481 }
482 /**
483  * @see ICompilationUnit#getPackageDeclaration(String)
484  */
485 public IPackageDeclaration getPackageDeclaration(String name) {
486         return new PackageDeclaration(this, name);
487 }
488 /**
489  * @see ICompilationUnit#getPackageDeclarations()
490  */
491 public IPackageDeclaration[] getPackageDeclarations() throws JavaModelException {
492         ArrayList list = getChildrenOfType(PACKAGE_DECLARATION);
493         IPackageDeclaration[] array= new IPackageDeclaration[list.size()];
494         list.toArray(array);
495         return array;
496 }
497 /**
498  * @see org.eclipse.jdt.internal.compiler.env.ICompilationUnit#getPackageName()
499  */
500 public char[][] getPackageName() {
501         return null;
502 }
503 /**
504  * @see IJavaElement#getPath()
505  */
506 public IPath getPath() {
507         PackageFragmentRoot root = this.getPackageFragmentRoot();
508         if (root.isArchive()) {
509                 return root.getPath();
510         } else {
511                 return this.getParent().getPath().append(this.getElementName());
512         }
513 }
514 /**
515  * @see IJavaElement#getResource()
516  */
517 public IResource getResource() {
518         PackageFragmentRoot root = this.getPackageFragmentRoot();
519         if (root.isArchive()) {
520                 return root.getResource();
521         } else {
522                 return ((IContainer)this.getParent().getResource()).getFile(new Path(this.getElementName()));
523         }
524 }
525
526 /**
527  * @see ISourceReference#getSource()
528  */
529 public String getSource() throws JavaModelException {
530         IBuffer buffer = getBuffer();
531         if (buffer == null) return ""; //$NON-NLS-1$
532         return buffer.getContents();
533 }
534 /**
535  * @see ISourceReference#getSourceRange()
536  */
537 public ISourceRange getSourceRange() throws JavaModelException {
538         return ((CompilationUnitElementInfo) getElementInfo()).getSourceRange();
539 }
540 /**
541  * @see ICompilationUnit#getType(String)
542  */
543 public IType getType(String name) {
544         return new SourceType(this, name);
545 }
546 /**
547  * @see ICompilationUnit#getTypes()
548  */
549 public IType[] getTypes() throws JavaModelException {
550         ArrayList list = getChildrenOfType(TYPE);
551         IType[] array= new IType[list.size()];
552         list.toArray(array);
553         return array;
554 }
555 public IResource getUnderlyingResource() throws JavaModelException {
556         if (FIX_BUG25184) {
557                 return super.getUnderlyingResource();
558         } else {
559                 return getResource();
560         }
561 }
562 /**
563  * @see IWorkingCopy#getSharedWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)
564  */
565 public IJavaElement getSharedWorkingCopy(IProgressMonitor pm, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException {
566         
567         // if factory is null, default factory must be used
568         if (factory == null) factory = this.getBufferManager().getDefaultBufferFactory();
569
570         JavaModelManager manager = JavaModelManager.getJavaModelManager();
571         
572         // In order to be shared, working copies have to denote the same compilation unit 
573         // AND use the same buffer factory.
574         // Assuming there is a little set of buffer factories, then use a 2 level Map cache.
575         Map sharedWorkingCopies = manager.sharedWorkingCopies;
576         
577         Map perFactoryWorkingCopies = (Map) sharedWorkingCopies.get(factory);
578         if (perFactoryWorkingCopies == null){
579                 perFactoryWorkingCopies = new HashMap();
580                 sharedWorkingCopies.put(factory, perFactoryWorkingCopies);
581         }
582         WorkingCopy workingCopy = (WorkingCopy)perFactoryWorkingCopies.get(this);
583         if (workingCopy != null) {
584                 workingCopy.useCount++;
585
586                 if (SHARED_WC_VERBOSE) {
587                         System.out.println("Incrementing use count of shared working copy " + workingCopy.toStringWithAncestors()); //$NON-NLS-1$
588                 }
589
590                 return workingCopy;
591         } else {
592                 CreateWorkingCopyOperation op = new CreateWorkingCopyOperation(this, perFactoryWorkingCopies, factory, problemRequestor);
593                 runOperation(op, pm);
594                 return op.getResultElements()[0];
595         }
596 }
597 /**
598  * @see IWorkingCopy#getWorkingCopy()
599  */
600 public IJavaElement getWorkingCopy() throws JavaModelException {
601         return this.getWorkingCopy(null, null, null);
602 }
603
604 /**
605  * @see IWorkingCopy#getWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)
606  */
607 public IJavaElement getWorkingCopy(IProgressMonitor pm, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException {
608         CreateWorkingCopyOperation op = new CreateWorkingCopyOperation(this, null, factory, problemRequestor);
609         runOperation(op, pm);
610         return op.getResultElements()[0];
611 }
612
613 /**
614  * @see Openable#hasBuffer()
615  */
616 protected boolean hasBuffer() {
617         return true;
618 }
619 /**
620  * If I am not open, return true to avoid parsing.
621  *
622  * @see IParent#hasChildren()
623  */
624 public boolean hasChildren() throws JavaModelException {
625 //      if (isOpen()) {
626 //              return getChildren().length > 0;
627 //      } else {
628 //              return true;
629 //      }
630   return false;
631 }
632 /**
633  * Returns false, this is not a working copy.
634  *
635  * @see IWorkingCopy#isBasedOn(IResource)
636  */
637 public boolean isBasedOn(IResource resource) {
638         return false;
639 }
640 /**
641  * @see IOpenable#isConsistent()
642  */
643 public boolean isConsistent() throws JavaModelException {
644         return JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().get(this) == null;
645 }
646 /**
647  * @see Openable#isSourceElement()
648  */
649 protected boolean isSourceElement() {
650         return true;
651 }
652 /**
653  * @see IWorkingCopy#isWorkingCopy()
654  */
655 public boolean isWorkingCopy() {
656         return false;
657 }
658 /**
659  * @see IOpenable#makeConsistent(IProgressMonitor)
660  */
661 public void makeConsistent(IProgressMonitor monitor) throws JavaModelException {
662         if (!isConsistent()) { // TODO: this code isn't synchronized with regular opening of a working copy
663                 // create a new info and make it the current info
664                 OpenableElementInfo info = createElementInfo();
665                 buildStructure(info, monitor);
666         }
667 }
668
669 /**
670  * @see ISourceManipulation#move(IJavaElement, IJavaElement, String, boolean, IProgressMonitor)
671  */
672 public void move(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor) throws JavaModelException {
673         if (container == null) {
674                 throw new IllegalArgumentException(Util.bind("operation.nullContainer")); //$NON-NLS-1$
675         }
676         IJavaElement[] elements= new IJavaElement[] {this};
677         IJavaElement[] containers= new IJavaElement[] {container};
678         
679         String[] renamings= null;
680         if (rename != null) {
681                 renamings= new String[] {rename};
682         }
683         getJavaModel().move(elements, containers, null, renamings, force, monitor);
684 }
685
686 /**
687  * @see Openable#openBuffer(IProgressMonitor)
688  */
689 protected IBuffer openBuffer(IProgressMonitor pm) throws JavaModelException {
690
691         // create buffer -  compilation units only use default buffer factory
692         BufferManager bufManager = getBufferManager();
693         IBuffer buffer = getBufferFactory().createBuffer(this);
694         if (buffer == null) return null;
695         
696         // set the buffer source
697         if (buffer.getCharacters() == null){
698                 IFile file = (IFile)this.getResource();
699                 if (file == null || !file.exists()) throw newNotPresentException();
700                 buffer.setContents(Util.getResourceContentsAsCharArray(file));
701         }
702
703         // add buffer to buffer cache
704         bufManager.addBuffer(buffer);
705                         
706         // listen to buffer changes
707         buffer.addBufferChangedListener(this);
708         
709         return buffer;
710 }
711 protected void openParent(IProgressMonitor pm) throws JavaModelException {
712         if (FIX_BUG25184) {
713                 super.openParent(pm);
714         } else {
715                 try {
716                         super.openParent(pm);
717                 } catch(JavaModelException e){
718                         // allow parent to not exist for compilation units defined outside classpath
719                         if (!e.isDoesNotExist()){ 
720                                 throw e;
721                         }
722                 }
723         }
724 }
725 protected boolean parentExists() {
726         if (FIX_BUG25184) {
727                 return super.parentExists();
728         } else {
729                 return true; // tolerate units outside classpath
730         }
731 }
732
733 /**
734  * @see IWorkingCopy#reconcile()
735  */
736 public IMarker[] reconcile() throws JavaModelException {
737         // Reconciling is not supported on non working copies
738         return null;
739 }
740
741 /**
742  * @see IWorkingCopy#reconcile(boolean, IProgressMonitor)
743  */
744 public void reconcile(
745         boolean forceProblemDetection,
746         IProgressMonitor monitor)
747         throws JavaModelException {
748         // Reconciling is not supported on non working copies
749 }
750
751 /**
752  * @see ISourceManipulation#rename(String, boolean, IProgressMonitor)
753  */
754 public void rename(String name, boolean force, IProgressMonitor monitor) throws JavaModelException {
755         if (name == null) {
756                 throw new IllegalArgumentException(Util.bind("operation.nullName")); //$NON-NLS-1$
757         }
758         IJavaElement[] elements= new IJavaElement[] {this};
759         IJavaElement[] dests= new IJavaElement[] {this.getParent()};
760         String[] renamings= new String[] {name};
761         getJavaModel().rename(elements, dests, renamings, force, monitor);
762 }
763 /**
764  * Does nothing - this is not a working copy.
765  *
766  * @see IWorkingCopy#restore()
767  */
768 public void restore () throws JavaModelException {
769 }
770 /**
771  * @see ICodeAssist#codeComplete(int, ICodeCompletionRequestor)
772  * @deprecated - use codeComplete(int, ICompletionRequestor)
773  */
774 //public void codeComplete(int offset, final ICodeCompletionRequestor requestor) throws JavaModelException {
775 //      
776 //      if (requestor == null){
777 //              codeComplete(offset, (ICompletionRequestor)null);
778 //              return;
779 //      }
780 //      codeComplete(
781 //              offset,
782 //              new ICompletionRequestor(){
783 //                      public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
784 //                      }
785 //                      public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
786 //                              requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd);
787 //                      }
788 //                      public void acceptError(IProblem error) {
789 //                              if (true) return; // was disabled in 1.0
790 //
791 //                              try {
792 //                                      IMarker marker = ResourcesPlugin.getWorkspace().getRoot().createMarker(IJavaModelMarker.TRANSIENT_PROBLEM);
793 //                                      marker.setAttribute(IJavaModelMarker.ID, error.getID());
794 //                                      marker.setAttribute(IMarker.CHAR_START, error.getSourceStart());
795 //                                      marker.setAttribute(IMarker.CHAR_END, error.getSourceEnd() + 1);
796 //                                      marker.setAttribute(IMarker.LINE_NUMBER, error.getSourceLineNumber());
797 //                                      marker.setAttribute(IMarker.MESSAGE, error.getMessage());
798 //                                      marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
799 //                                      requestor.acceptError(marker);
800 //                              } catch(CoreException e){
801 //                              }
802 //                      }
803 //                      public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
804 //                              requestor.acceptField(declaringTypePackageName, declaringTypeName, name, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd);
805 //                      }
806 //                      public void acceptInterface(char[] packageName,char[] interfaceName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
807 //                              requestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart, completionEnd);
808 //                      }
809 //                      public void acceptKeyword(char[] keywordName,int completionStart,int completionEnd, int relevance){
810 //                              requestor.acceptKeyword(keywordName, completionStart, completionEnd);
811 //                      }
812 //                      public void acceptLabel(char[] labelName,int completionStart,int completionEnd, int relevance){
813 //                              requestor.acceptLabel(labelName, completionStart, completionEnd);
814 //                      }
815 //                      public void acceptLocalVariable(char[] name,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance){
816 //                              // ignore
817 //                      }
818 //                      public void acceptMethod(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
819 //                              // skip parameter names
820 //                              requestor.acceptMethod(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart, completionEnd);
821 //                      }
822 //                      public void acceptMethodDeclaration(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
823 //                              // ignore
824 //                      }
825 //                      public void acceptModifier(char[] modifierName,int completionStart,int completionEnd, int relevance){
826 //                              requestor.acceptModifier(modifierName, completionStart, completionEnd);
827 //                      }
828 //                      public void acceptPackage(char[] packageName,char[] completionName,int completionStart,int completionEnd, int relevance){
829 //                              requestor.acceptPackage(packageName, completionName, completionStart, completionEnd);
830 //                      }
831 //                      public void acceptType(char[] packageName,char[] typeName,char[] completionName,int completionStart,int completionEnd, int relevance){
832 //                              requestor.acceptType(packageName, typeName, completionName, completionStart, completionEnd);
833 //                      }
834 //                      public void acceptVariableName(char[] typePackageName,char[] typeName,char[] name,char[] completionName,int completionStart,int completionEnd, int relevance){
835 //                              // ignore
836 //                      }
837 //              });
838 //}
839 /**
840  * @see JavaElement#rootedAt(IJavaProject)
841  */
842 public IJavaElement rootedAt(IJavaProject project) {
843         return
844                 new CompilationUnit(
845                         (IPackageFragment)((JavaElement)fParent).rootedAt(project), 
846                         fName);
847 }
848
849 }