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