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