Organized imports
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / SourceType.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
15 import net.sourceforge.phpdt.core.ICompilationUnit;
16 import net.sourceforge.phpdt.core.IField;
17 import net.sourceforge.phpdt.core.IJavaElement;
18 import net.sourceforge.phpdt.core.IMember;
19 import net.sourceforge.phpdt.core.IMethod;
20 import net.sourceforge.phpdt.core.IPackageFragment;
21 import net.sourceforge.phpdt.core.IParent;
22 import net.sourceforge.phpdt.core.IType;
23 import net.sourceforge.phpdt.core.ITypeHierarchy;
24 import net.sourceforge.phpdt.core.IWorkingCopy;
25 import net.sourceforge.phpdt.core.JavaModelException;
26 import net.sourceforge.phpdt.core.jdom.IDOMNode;
27 import net.sourceforge.phpdt.internal.core.util.Util;
28 import net.sourceforge.phpdt.internal.corext.Assert;
29
30 import org.eclipse.core.runtime.IProgressMonitor;
31
32 /**
33  * Handle for a source type. Info object is a SourceTypeElementInfo.
34  * 
35  * Note: Parent is either an IClassFile, an ICompilationUnit or an IType.
36  * 
37  * @see IType
38  */
39
40 public class SourceType extends Member implements IType {
41   /**
42    * An empty list of Strings
43    */
44   protected static final String[] fgEmptyList = new String[] {};
45   protected SourceType(JavaElement parent, String name) {
46     super(parent, name);
47     Assert.isTrue(name.indexOf('.') == -1, Util.bind("sourcetype.invalidName", name)); //$NON-NLS-1$
48   }
49
50   /**
51    * @see IType
52    */
53   //public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][]
54   // localVariableNames,int[] localVariableModifiers,boolean isStatic,ICompletionRequestor requestor) throws JavaModelException {
55   //    if (requestor == null) {
56   //            throw new IllegalArgumentException(ProjectPrefUtil.bind("codeAssist.nullRequestor")); //$NON-NLS-1$
57   //    }
58   //    
59   //    JavaProject project = (JavaProject) getJavaProject();
60   //    SearchableEnvironment environment = (SearchableEnvironment) project.getSearchableNameEnvironment();
61   //    NameLookup nameLookup = project.getNameLookup();
62   //    CompletionEngine engine = new CompletionEngine(environment, new CompletionRequestorWrapper(requestor,nameLookup),
63   // project.getOptions(true), project);
64   //    
65   //    String source = getCompilationUnit().getSource();
66   //    if (source != null && insertion > -1 && insertion < source.length()) {
67   //            String encoding = project.getOption(JavaCore.CORE_ENCODING, true);
68   //            
69   //            char[] prefix = CharOperation.concat(source.substring(0, insertion).toCharArray(), new char[]{'{'});
70   //            char[] suffix = CharOperation.concat(new char[]{'}'}, source.substring(insertion).toCharArray());
71   //            char[] fakeSource = CharOperation.concat(prefix, snippet, suffix);
72   //            
73   //            BasicCompilationUnit cu =
74   //                    new BasicCompilationUnit(
75   //                            fakeSource,
76   //                            null,
77   //                            getElementName(),
78   //                            encoding);
79   //
80   //            engine.complete(cu, prefix.length + position, prefix.length);
81   //    } else {
82   //            engine.complete(this, snippet, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic);
83   //    }
84   //}
85   /**
86    * @see IType
87    */
88   //public IField createField(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor) throws
89   // JavaModelException {
90   //    CreateFieldOperation op = new CreateFieldOperation(this, contents, force);
91   //    if (sibling != null) {
92   //            op.createBefore(sibling);
93   //    }
94   //    runOperation(op, monitor);
95   //    return (IField) op.getResultElements()[0];
96   //}
97   /**
98    * @see IType
99    */
100   //public IInitializer createInitializer(String contents, IJavaElement sibling, IProgressMonitor monitor) throws
101   // JavaModelException {
102   //    CreateInitializerOperation op = new CreateInitializerOperation(this, contents);
103   //    if (sibling != null) {
104   //            op.createBefore(sibling);
105   //    }
106   //    runOperation(op, monitor);
107   //    return (IInitializer) op.getResultElements()[0];
108   //}
109   /**
110    * @see IType
111    */
112   //public IMethod createMethod(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor) throws
113   // JavaModelException {
114   //    CreateMethodOperation op = new CreateMethodOperation(this, contents, force);
115   //    if (sibling != null) {
116   //            op.createBefore(sibling);
117   //    }
118   //    runOperation(op, monitor);
119   //    return (IMethod) op.getResultElements()[0];
120   //}
121   /**
122    * @see IType
123    */
124   //public IType createType(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor) throws
125   // JavaModelException {
126   //    CreateTypeOperation op = new CreateTypeOperation(this, contents, force);
127   //    if (sibling != null) {
128   //            op.createBefore(sibling);
129   //    }
130   //    runOperation(op, monitor);
131   //    return (IType) op.getResultElements()[0];
132   //}
133   /**
134    * @see JavaElement#equalsDOMNode
135    */
136   protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException {
137     return (node.getNodeType() == IDOMNode.TYPE) && super.equalsDOMNode(node);
138   }
139
140   /*
141    * @see IType
142    */
143   public IMethod[] findMethods(IMethod method) {
144     try {
145       return this.findMethods(method, this.getMethods());
146     } catch (JavaModelException e) {
147       // if type doesn't exist, no matching method can exist
148       return null;
149     }
150   }
151
152   /**
153    * @see IMember
154    */
155   public IType getDeclaringType() {
156     IJavaElement parent = getParent();
157     while (parent != null) {
158       if (parent.getElementType() == IJavaElement.TYPE) {
159         return (IType) parent;
160       } else if (parent instanceof IMember) {
161         parent = parent.getParent();
162       } else {
163         return null;
164       }
165     }
166     return null;
167   }
168
169   /**
170    * @see IJavaElement
171    */
172   public int getElementType() {
173     return TYPE;
174   }
175
176   /**
177    * @see IType#getField
178    */
179   public IField getField(String name) {
180     return new SourceField(this, name);
181   }
182
183   /**
184    * @see IType
185    */
186   public IField[] getFields() throws JavaModelException {
187     ArrayList list = getChildrenOfType(FIELD);
188     IField[] array = new IField[list.size()];
189     list.toArray(array);
190     return array;
191   }
192
193   /**
194    * @see IType#getFullyQualifiedName
195    */
196   public String getFullyQualifiedName() {
197     return this.getFullyQualifiedName('$');
198   }
199
200   /**
201    * @see IType#getFullyQualifiedName(char)
202    */
203   public String getFullyQualifiedName(char enclosingTypeSeparator) {
204     String packageName = getPackageFragment().getElementName();
205     if (packageName.equals(IPackageFragment.DEFAULT_PACKAGE_NAME)) {
206       return getTypeQualifiedName(enclosingTypeSeparator);
207     }
208     return packageName + '.' + getTypeQualifiedName(enclosingTypeSeparator);
209   }
210
211   /**
212    * @see IType
213    */
214   //public IInitializer getInitializer(int occurrenceCount) {
215   //    return new Initializer(this, occurrenceCount);
216   //}
217   /**
218    * @see IType
219    */
220   //public IInitializer[] getInitializers() throws JavaModelException {
221   //    ArrayList list = getChildrenOfType(INITIALIZER);
222   //    IInitializer[] array= new IInitializer[list.size()];
223   //    list.toArray(array);
224   //    return array;
225   //}
226   /**
227    * @see IType#getMethod
228    */
229   public IMethod getMethod(String name, String[] parameterTypeSignatures) {
230     return new SourceMethod(this, name, parameterTypeSignatures);
231   }
232
233   /**
234    * @see IType
235    */
236   public IMethod[] getMethods() throws JavaModelException {
237     ArrayList list = getChildrenOfType(METHOD);
238     IMethod[] array = new IMethod[list.size()];
239     list.toArray(array);
240     return array;
241   }
242
243   /**
244    * @see IType
245    */
246   public IPackageFragment getPackageFragment() {
247     IJavaElement parentElement = this.parent;
248     while (parentElement != null) {
249       if (parentElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
250         return (IPackageFragment) parentElement;
251       } else {
252         parentElement = parentElement.getParent();
253       }
254     }
255     Assert.isTrue(false); // should not happen
256     return null;
257   }
258
259   /**
260    * @see IType
261    */
262   public String getSuperclassName() throws JavaModelException {
263     SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
264     char[] superclassName = info.getSuperclassName();
265     if (superclassName == null) {
266       return null;
267     }
268     return new String(superclassName);
269   }
270
271   /**
272    * @see IType
273    */
274   public String[] getSuperInterfaceNames() throws JavaModelException {
275     SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
276     char[][] names = info.getInterfaceNames();
277     if (names == null) {
278       return fgEmptyList;
279     }
280     String[] strings = new String[names.length];
281     for (int i = 0; i < names.length; i++) {
282       strings[i] = new String(names[i]);
283     }
284     return strings;
285   }
286
287   /**
288    * @see IType
289    */
290   public IType getType(String name) {
291     return new SourceType(this, name);
292   }
293
294   /**
295    * @see IType#getTypeQualifiedName
296    */
297   public String getTypeQualifiedName() {
298     return this.getTypeQualifiedName('$');
299   }
300
301   /**
302    * @see IType#getTypeQualifiedName(char)
303    */
304   public String getTypeQualifiedName(char enclosingTypeSeparator) {
305     if (parent.getElementType() == IJavaElement.COMPILATION_UNIT) {
306       return name;
307     } else {
308       return ((IType) parent).getTypeQualifiedName(enclosingTypeSeparator) + enclosingTypeSeparator + name;
309     }
310   }
311
312   /**
313    * @see IType
314    */
315   public IType[] getTypes() throws JavaModelException {
316     ArrayList list = getChildrenOfType(TYPE);
317     IType[] array = new IType[list.size()];
318     list.toArray(array);
319     return array;
320   }
321
322   /**
323    * @see IParent
324    */
325   public boolean hasChildren() throws JavaModelException {
326     return getChildren().length > 0;
327   }
328
329   /**
330    * @see IType#isAnonymous()
331    */
332   public boolean isAnonymous() throws JavaModelException {
333     return false; // cannot create source handle onto anonymous types
334   }
335
336   /**
337    * @see IType
338    */
339   public boolean isClass() throws JavaModelException {
340     return !isInterface();
341   }
342
343   /**
344    * @see IType
345    */
346   public boolean isInterface() throws JavaModelException {
347     Object obj = getElementInfo(); 
348     if (obj instanceof SourceTypeElementInfo) {
349       SourceTypeElementInfo info = (SourceTypeElementInfo) getElementInfo();
350       return info.isInterface();
351     }
352     return false;
353   }
354
355   /**
356    * @see IType#isLocal()
357    */
358   public boolean isLocal() throws JavaModelException {
359     return false; // cannot create source handle onto local types
360   }
361
362   /**
363    * @see IType#isMember()
364    */
365   public boolean isMember() throws JavaModelException {
366     return getDeclaringType() != null;
367   }
368
369   /**
370    * @see IType
371    */
372 //  public ITypeHierarchy loadTypeHierachy(InputStream input, IProgressMonitor monitor) throws JavaModelException {
373 //      return loadTypeHierachy(input, DefaultWorkingCopyOwner.PRIMARY, monitor);
374 //  }
375   /**
376    * NOTE: This method is not part of the API has it is not clear clients would easily use it: they would need to
377    * first make sure all working copies for the given owner exist before calling it. This is especially har at startup 
378    * time.
379    * In case clients want this API, here is how it should be specified:
380    * <p>
381    * Loads a previously saved ITypeHierarchy from an input stream. A type hierarchy can
382    * be stored using ITypeHierachy#store(OutputStream). A compilation unit of a
383    * loaded type has the given owner if such a working copy exists, otherwise the type's 
384    * compilation unit is a primary compilation unit.
385    * 
386    * Only hierarchies originally created by the following methods can be loaded:
387    * <ul>
388    * <li>IType#newSupertypeHierarchy(IProgressMonitor)</li>
389    * <li>IType#newSupertypeHierarchy(WorkingCopyOwner, IProgressMonitor)</li>
390    * <li>IType#newTypeHierarchy(IJavaProject, IProgressMonitor)</li>
391    * <li>IType#newTypeHierarchy(IJavaProject, WorkingCopyOwner, IProgressMonitor)</li>
392    * <li>IType#newTypeHierarchy(IProgressMonitor)</li>
393    * <li>IType#newTypeHierarchy(WorkingCopyOwner, IProgressMonitor)</li>
394    * </u>
395    * 
396    * @param input stream where hierarchy will be read
397    * @param monitor the given progress monitor
398    * @return the stored hierarchy
399    * @exception JavaModelException if the hierarchy could not be restored, reasons include:
400    *      - type is not the focus of the hierarchy or 
401    *            - unable to read the input stream (wrong format, IOException during reading, ...)
402    * @see ITypeHierarchy#store(java.io.OutputStream, IProgressMonitor)
403    * @since 3.0
404    */
405 //  public ITypeHierarchy loadTypeHierachy(InputStream input, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException {
406 //      // TODO monitor should be passed to TypeHierarchy.load(...)
407 //      return TypeHierarchy.load(this, input, owner);
408 //  }
409   /**
410    * @see IType
411    */
412 //  public ITypeHierarchy newSupertypeHierarchy(IProgressMonitor monitor) throws JavaModelException {
413 //      return this.newSupertypeHierarchy(DefaultWorkingCopyOwner.PRIMARY, monitor);
414 //  }
415   /*
416    * @see IType#newSupertypeHierarchy(ICompilationUnit[], IProgressMonitor)
417    */
418 //  public ITypeHierarchy newSupertypeHierarchy(
419 //      ICompilationUnit[] workingCopies,
420 //      IProgressMonitor monitor)
421 //      throws JavaModelException {
422 //
423 //      CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, workingCopies, SearchEngine.createWorkspaceScope(), false);
424 //      op.runOperation(monitor);
425 //      return op.getResult();
426 //  }
427   /**
428    * @param workingCopies the working copies that take precedence over their original compilation units
429    * @param monitor the given progress monitor
430    * @return a type hierarchy for this type containing this type and all of its supertypes
431    * @exception JavaModelException if this element does not exist or if an
432    *            exception occurs while accessing its corresponding resource.
433    *
434    * @see IType#newSupertypeHierarchy(IWorkingCopy[], IProgressMonitor)
435    * @deprecated
436    */
437   public ITypeHierarchy newSupertypeHierarchy(
438         IWorkingCopy[] workingCopies,
439         IProgressMonitor monitor)
440         throws JavaModelException {
441
442         ICompilationUnit[] copies;
443         if (workingCopies == null) {
444                 copies = null;
445         } else {
446                 int length = workingCopies.length;
447                 System.arraycopy(workingCopies, 0, copies = new ICompilationUnit[length], 0, length);
448         }
449         return newSupertypeHierarchy(copies, monitor);
450   }
451   /**
452    * @see IType#newSupertypeHierarchy(WorkingCopyOwner, IProgressMonitor)
453    */
454 //  public ITypeHierarchy newSupertypeHierarchy(
455 //      WorkingCopyOwner owner,
456 //      IProgressMonitor monitor)
457 //      throws JavaModelException {
458 //
459 //      ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
460 //      CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, workingCopies, SearchEngine.createWorkspaceScope(), false);
461 //      op.runOperation(monitor);
462 //      return op.getResult();
463 //  }
464   /**
465    * @see IType
466    */
467 //  public ITypeHierarchy newTypeHierarchy(IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
468 //      return newTypeHierarchy(project, DefaultWorkingCopyOwner.PRIMARY, monitor);
469 //  }
470   /**
471    * @see IType#newTypeHierarchy(IJavaProject, WorkingCopyOwner, IProgressMonitor)
472    */
473 //  public ITypeHierarchy newTypeHierarchy(IJavaProject project, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException {
474 //      if (project == null) {
475 //              throw new IllegalArgumentException(Util.bind("hierarchy.nullProject")); //$NON-NLS-1$
476 //      }
477 //      ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
478 //      ICompilationUnit[] projectWCs = null;
479 //      if (workingCopies != null) {
480 //              int length = workingCopies.length;
481 //              projectWCs = new ICompilationUnit[length];
482 //              int index = 0;
483 //              for (int i = 0; i < length; i++) {
484 //                      ICompilationUnit wc = workingCopies[i];
485 //                      if (project.equals(wc.getJavaProject())) {
486 //                              projectWCs[index++] = wc;
487 //                      }
488 //              }
489 //              if (index != length) {
490 //                      System.arraycopy(projectWCs, 0, projectWCs = new ICompilationUnit[index], 0, index);
491 //              }
492 //      }
493 //      CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(
494 //              this, 
495 //              projectWCs,
496 //              project, 
497 //              true);
498 //      op.runOperation(monitor);
499 //      return op.getResult();
500 //  }
501   /**
502    * @see IType
503    */
504 //  public ITypeHierarchy newTypeHierarchy(IProgressMonitor monitor) throws JavaModelException {
505 //      CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, null, SearchEngine.createWorkspaceScope(), true);
506 //      op.runOperation(monitor);
507 //      return op.getResult();
508 //  }
509   /*
510    * @see IType#newTypeHierarchy(ICompilationUnit[], IProgressMonitor)
511    */
512 //  public ITypeHierarchy newTypeHierarchy(
513 //      ICompilationUnit[] workingCopies,
514 //      IProgressMonitor monitor)
515 //      throws JavaModelException {
516 //              
517 //      CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, workingCopies, SearchEngine.createWorkspaceScope(), true);
518 //      op.runOperation(monitor);
519 //      return op.getResult();
520 //  }
521   /**
522    * @see IType#newTypeHierarchy(IWorkingCopy[], IProgressMonitor)
523    * @deprecated
524    */
525   public ITypeHierarchy newTypeHierarchy(
526         IWorkingCopy[] workingCopies,
527         IProgressMonitor monitor)
528         throws JavaModelException {
529                 
530         ICompilationUnit[] copies;
531         if (workingCopies == null) {
532                 copies = null;
533         } else {
534                 int length = workingCopies.length;
535                 System.arraycopy(workingCopies, 0, copies = new ICompilationUnit[length], 0, length);
536         }
537         return newTypeHierarchy(copies, monitor);
538   }
539   /**
540    * @see IType#newTypeHierarchy(WorkingCopyOwner, IProgressMonitor)
541    */
542 //  public ITypeHierarchy newTypeHierarchy(
543 //      WorkingCopyOwner owner,
544 //      IProgressMonitor monitor)
545 //      throws JavaModelException {
546 //              
547 //      ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
548 //      CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, workingCopies, SearchEngine.createWorkspaceScope(), true);
549 //      op.runOperation(monitor);
550 //      return op.getResult();  
551 //  }
552
553   // public String[][] resolveType(String typeName) throws JavaModelException {
554   //    ISourceType info = (ISourceType) this.getElementInfo();
555   //    ISearchableNameEnvironment environment = ((JavaProject)getJavaProject()).getSearchableNameEnvironment();
556   //
557   //    class TypeResolveRequestor implements ISelectionRequestor {
558   //            String[][] answers = null;
559   //            void acceptType(String[] answer){
560   //                    if (answers == null) {
561   //                            answers = new String[][]{ answer };
562   //                    } else {
563   //                            // grow
564   //                            int length = answers.length;
565   //                            System.arraycopy(answers, 0, answers = new String[length+1][], 0, length);
566   //                            answers[length] = answer;
567   //                    }
568   //            }
569   //            public void acceptClass(char[] packageName, char[] className, boolean needQualification) {
570   //                    acceptType(new String[] { new String(packageName), new String(className) });
571   //            }
572   //            
573   //            public void acceptInterface(char[] packageName, char[] interfaceName, boolean needQualification) {
574   //                    acceptType(new String[] { new String(packageName), new String(interfaceName) });
575   //            }
576   //
577   //            public void acceptError(IProblem error) {}
578   //            public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name) {}
579   //            public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, char[][]
580   // parameterPackageNames, char[][] parameterTypeNames, boolean isConstructor) {}
581   //            public void acceptPackage(char[] packageName){}
582   //
583   //    }
584   //    TypeResolveRequestor requestor = new TypeResolveRequestor();
585   //    SelectionEngine engine =
586   //            new SelectionEngine(environment, requestor, this.getJavaProject().getOptions(true));
587   //            
588   //    IType[] topLevelTypes = this.getCompilationUnit().getTypes();
589   //    int length = topLevelTypes.length;
590   //    ISourceType[] topLevelInfos = new ISourceType[length];
591   //    for (int i = 0; i < length; i++) {
592   //            topLevelInfos[i] = (ISourceType)((SourceType)topLevelTypes[i]).getElementInfo();
593   //    }
594   //            
595   //    engine.selectType(info, typeName.toCharArray(), topLevelInfos, false);
596   //    return requestor.answers;
597   //}
598   /**
599    * @private Debugging purposes
600    */
601   protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
602     buffer.append(this.tabString(tab));
603     if (info == null) {
604       buffer.append(this.getElementName());
605       buffer.append(" (not open)"); //$NON-NLS-1$
606     } else if (info == NO_INFO) {
607       buffer.append(getElementName());
608     } else {
609       try {
610         if (this.isInterface()) {
611           buffer.append("interface "); //$NON-NLS-1$
612         } else {
613           buffer.append("class "); //$NON-NLS-1$
614         }
615         buffer.append(this.getElementName());
616       } catch (JavaModelException e) {
617         buffer.append("<JavaModelException in toString of " + getElementName()); //$NON-NLS-1$
618       }
619     }
620   }
621 }