88f52b7335410fd63c6862f2e1bd9b5a86243544
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / TypeConverter.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v0.5 
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v05.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  ******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
12
13 import net.sourceforge.phpdt.core.IField;
14 import net.sourceforge.phpdt.core.IMethod;
15 import net.sourceforge.phpdt.core.IType;
16 import net.sourceforge.phpdt.core.JavaModelException;
17 import net.sourceforge.phpdt.core.Signature;
18 import net.sourceforge.phpdt.internal.compiler.CompilationResult;
19 import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
20 import net.sourceforge.phpdt.internal.compiler.ast.Argument;
21 import net.sourceforge.phpdt.internal.compiler.ast.ArrayQualifiedTypeReference;
22 import net.sourceforge.phpdt.internal.compiler.ast.ArrayTypeReference;
23 import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
24 import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
25 import net.sourceforge.phpdt.internal.compiler.ast.MemberTypeDeclaration;
26 import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
27 import net.sourceforge.phpdt.internal.compiler.ast.QualifiedTypeReference;
28 import net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference;
29 import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
30 import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
31 import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
32 import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
33
34 /**
35  * Converter from a type to an AST type declaration.
36  */
37 public class TypeConverter {
38         
39         /**
40          * Convert a type into an AST type declaration and put it in the given compilation unit.
41          */
42 //      public static TypeDeclaration buildTypeDeclaration(IType type, CompilationUnitDeclaration compilationUnit, CompilationResult compilationResult, ProblemReporter problemReporter)  throws JavaModelException {
43 //              char[] packageName = type.getPackageFragment().getElementName().toCharArray();
44 //              
45 //              if (packageName != null && packageName.length > 0) { 
46 //                      compilationUnit.currentPackage = new ImportReference(CharOperation.splitOn('.', packageName), new long[]{0}, false);
47 //              }
48 //      
49 //              /* convert type */
50 //              TypeDeclaration typeDeclaration = convert(type, null, null, compilationResult);
51 //              
52 //              IType alreadyComputedMember = type;
53 //              IType parent = type.getDeclaringType();
54 //              TypeDeclaration previousDeclaration = typeDeclaration;
55 //              while(parent != null) {
56 //                      TypeDeclaration declaration = convert(parent, alreadyComputedMember, (MemberTypeDeclaration)previousDeclaration, compilationResult);
57 //                      
58 //                      alreadyComputedMember = parent;
59 //                      previousDeclaration = declaration;
60 //                      parent = parent.getDeclaringType();
61 //              }
62 //              
63 //              compilationUnit.types = new TypeDeclaration[]{previousDeclaration};
64 //
65 //              return typeDeclaration;
66 //      }
67         
68         private static FieldDeclaration convert(IField field, IType type) throws JavaModelException {
69
70                 FieldDeclaration fieldDeclaration = new FieldDeclaration();
71
72                 fieldDeclaration.name = field.getElementName().toCharArray();
73                 fieldDeclaration.type = createTypeReference(Signature.toString(field.getTypeSignature()).toCharArray(), type);
74                 fieldDeclaration.modifiers = field.getFlags();
75
76                 return fieldDeclaration;
77         }
78         
79         private static AbstractMethodDeclaration convert(IMethod method, IType type, CompilationResult compilationResult) throws JavaModelException {
80
81                 AbstractMethodDeclaration methodDeclaration;
82
83                 if (method.isConstructor()) {
84                         ConstructorDeclaration decl = new ConstructorDeclaration(compilationResult);
85                         decl.isDefaultConstructor = false;
86                         methodDeclaration = decl;
87                 } else {
88                         MethodDeclaration decl = new MethodDeclaration(compilationResult);
89                         /* convert return type */
90                         decl.returnType = createTypeReference(Signature.toString(method.getReturnType()).toCharArray(), type);
91                         methodDeclaration = decl;
92                 }
93                 methodDeclaration.selector = method.getElementName().toCharArray();
94                 methodDeclaration.modifiers = method.getFlags();
95
96                 /* convert arguments */
97                 String[] argumentTypeNames = method.getParameterTypes();
98                 String[] argumentNames = method.getParameterNames();
99                 int argumentCount = argumentTypeNames == null ? 0 : argumentTypeNames.length;
100                 methodDeclaration.arguments = new Argument[argumentCount];
101                 for (int i = 0; i < argumentCount; i++) {
102                         methodDeclaration.arguments[i] = new Argument(
103                                 argumentNames[i].toCharArray(),
104                                 0,
105                                 createTypeReference(Signature.toString(argumentTypeNames[i]).toCharArray(), type),
106                                 CompilerModifiers.AccDefault);
107                         // do not care whether was final or not
108                 }
109
110                 /* convert thrown exceptions */
111                 String[] exceptionTypeNames = method.getExceptionTypes();
112                 int exceptionCount = exceptionTypeNames == null ? 0 : exceptionTypeNames.length;
113                 if(exceptionCount > 0) {
114                         methodDeclaration.thrownExceptions = new TypeReference[exceptionCount];
115                         for (int i = 0; i < exceptionCount; i++) {
116                                 methodDeclaration.thrownExceptions[i] =
117                                         createTypeReference(Signature.toString(exceptionTypeNames[i]).toCharArray(), type);
118                         }
119                 }
120                 return methodDeclaration;
121         }
122         
123         private static TypeDeclaration convert(IType type, IType alreadyComputedMember,MemberTypeDeclaration alreadyComputedMemberDeclaration, CompilationResult compilationResult) throws JavaModelException {
124                 /* create type declaration - can be member type */
125                 TypeDeclaration typeDeclaration;
126                 if (type.getDeclaringType() == null) {
127                         typeDeclaration = new TypeDeclaration(compilationResult);
128                 } else {
129                         typeDeclaration = new MemberTypeDeclaration(compilationResult);
130                 }
131                 typeDeclaration.name = type.getElementName().toCharArray();
132                 typeDeclaration.modifiers = type.getFlags();
133
134
135                 /* set superclass and superinterfaces */
136                 if (type.getSuperclassName() != null) {
137                         typeDeclaration.superclass = createTypeReference(type.getSuperclassName().toCharArray(), type);
138                 }
139                 String[] interfaceNames = type.getSuperInterfaceNames();
140                 int interfaceCount = interfaceNames == null ? 0 : interfaceNames.length;
141                 typeDeclaration.superInterfaces = new TypeReference[interfaceCount];
142                 for (int i = 0; i < interfaceCount; i++) {
143                         typeDeclaration.superInterfaces[i] = createTypeReference(interfaceNames[i].toCharArray(), type);
144                 }
145                 
146                 /* convert member types */
147                 IType[] memberTypes = type.getTypes();
148                 int memberTypeCount =   memberTypes == null ? 0 : memberTypes.length;
149                 typeDeclaration.memberTypes = new MemberTypeDeclaration[memberTypeCount];
150                 for (int i = 0; i < memberTypeCount; i++) {
151                         if(alreadyComputedMember != null && alreadyComputedMember.getFullyQualifiedName().equals(memberTypes[i].getFullyQualifiedName())) {
152                                 typeDeclaration.memberTypes[i] = alreadyComputedMemberDeclaration;
153                         } else {
154                                 typeDeclaration.memberTypes[i] =
155                                         (MemberTypeDeclaration) convert(memberTypes[i], null, null, compilationResult);
156                         }
157                 }
158
159                 /* convert fields */
160                 IField[] fields = type.getFields();
161                 int fieldCount = fields == null ? 0 : fields.length;
162                 typeDeclaration.fields = new FieldDeclaration[fieldCount];
163                 for (int i = 0; i < fieldCount; i++) {
164                         typeDeclaration.fields[i] = convert(fields[i], type);
165                 }
166
167                 /* convert methods - need to add default constructor if necessary */
168                 IMethod[] methods = type.getMethods();
169                 int methodCount = methods == null ? 0 : methods.length;
170
171                 /* source type has a constructor ?           */
172                 /* by default, we assume that one is needed. */
173                 int neededCount = 1;
174                 for (int i = 0; i < methodCount; i++) {
175                         if (methods[i].isConstructor()) {
176                                 neededCount = 0;
177                                 // Does not need the extra constructor since one constructor already exists.
178                                 break;
179                         }
180                 }
181                 typeDeclaration.methods = new AbstractMethodDeclaration[methodCount + neededCount];
182                 if (neededCount != 0) { // add default constructor in first position
183                         typeDeclaration.methods[0] = typeDeclaration.createsInternalConstructor(false, false);
184                 }
185                 boolean isInterface = type.isInterface();
186                 for (int i = 0; i < methodCount; i++) {
187                         AbstractMethodDeclaration method =convert(methods[i], type, compilationResult);
188                         if (isInterface || method.isAbstract()) { // fix-up flag 
189                                 method.modifiers |= CompilerModifiers.AccSemicolonBody;
190                         }
191                         typeDeclaration.methods[neededCount + i] = method;
192                 }
193                 return typeDeclaration;
194         }
195         
196         private static TypeReference createTypeReference(char[] type, IType contextType) {
197                 try {
198                         String[][] resolvedName = contextType.resolveType(new String(type));
199                         char[] superClassName = null;
200                         if(resolvedName != null && resolvedName.length == 1) {
201                                 type= CharOperation.concat(resolvedName[0][0].toCharArray(), resolvedName[0][1].toCharArray(), '.');
202                         }
203                 } catch (JavaModelException e) {
204                         
205                 }
206                 
207                 /* count identifiers and dimensions */
208                 int max = type.length;
209                 int dimStart = max;
210                 int dim = 0;
211                 int identCount = 1;
212                 for (int i = 0; i < max; i++) {
213                         switch (type[i]) {
214                                 case '[' :
215                                         if (dim == 0)
216                                                 dimStart = i;
217                                         dim++;
218                                         break;
219                                 case '.' :
220                                         identCount++;
221                                         break;
222                         }
223                 }
224                 /* rebuild identifiers and dimensions */
225                 if (identCount == 1) { // simple type reference
226                         if (dim == 0) {
227                                 return new SingleTypeReference(type, 0);
228                         } else {
229                                 char[] identifier = new char[dimStart];
230                                 System.arraycopy(type, 0, identifier, 0, dimStart);
231                                 return new ArrayTypeReference(identifier, dim, 0);
232                         }
233                 } else { // qualified type reference
234                         char[][] identifiers =  CharOperation.splitOn('.', type, 0, dimStart - 1);
235                         if (dim == 0) {
236                                 return new QualifiedTypeReference(identifiers, new long[]{0});
237                         } else {
238                                 return new ArrayQualifiedTypeReference(identifiers, dim, new long[]{0});
239                         }
240                 }
241         }
242 }