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