KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > ast > ParameterizedQualifiedTypeReference


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.ast;
12
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.internal.compiler.ASTVisitor;
15 import org.eclipse.jdt.internal.compiler.impl.Constant;
16 import org.eclipse.jdt.internal.compiler.lookup.*;
17
18 /**
19  * Syntactic representation of a reference to a generic type.
20  * Note that it might also have a dimension.
21  */

22 public class ParameterizedQualifiedTypeReference extends ArrayQualifiedTypeReference {
23
24     public TypeReference[][] typeArguments;
25
26     /**
27      * @param tokens
28      * @param dim
29      * @param positions
30      */

31     public ParameterizedQualifiedTypeReference(char[][] tokens, TypeReference[][] typeArguments, int dim, long[] positions) {
32         
33         super(tokens, dim, positions);
34         this.typeArguments = typeArguments;
35     }
36     public void checkBounds(Scope scope) {
37         if (this.resolvedType == null) return;
38
39         checkBounds(
40             (ReferenceBinding) this.resolvedType.leafComponentType(),
41             scope,
42             this.typeArguments.length - 1);
43     }
44     public void checkBounds(ReferenceBinding type, Scope scope, int index) {
45         // recurse on enclosing type if any, and assuming explictly part of the reference (index>0)
46
if (index > 0 && type.enclosingType() != null) {
47             checkBounds(type.enclosingType(), scope, index - 1);
48         }
49         if (type.isParameterizedType()) {
50             ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) type;
51             ReferenceBinding currentType = parameterizedType.genericType();
52             TypeVariableBinding[] typeVariables = currentType.typeVariables();
53             TypeBinding[] argTypes = parameterizedType.arguments;
54             if (argTypes != null && typeVariables != null) { // argTypes may be null in error cases
55
parameterizedType.boundCheck(scope, this.typeArguments[index]);
56             }
57         }
58     }
59     public TypeReference copyDims(int dim){
60         return new ParameterizedQualifiedTypeReference(this.tokens, this.typeArguments, dim, this.sourcePositions);
61     }
62     
63     /**
64      * @return char[][]
65      */

66     public char [][] getParameterizedTypeName(){
67         int length = this.tokens.length;
68         char[][] qParamName = new char[length][];
69         for (int i = 0; i < length; i++) {
70             TypeReference[] arguments = this.typeArguments[i];
71             if (arguments == null) {
72                 qParamName[i] = this.tokens[i];
73             } else {
74                 StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(5);
75                 buffer.append(this.tokens[i]);
76                 buffer.append('<');
77                 for (int j = 0, argLength =arguments.length; j < argLength; j++) {
78                     if (j > 0) buffer.append(',');
79                     buffer.append(CharOperation.concatWith(arguments[j].getParameterizedTypeName(), '.'));
80                 }
81                 buffer.append('>');
82                 int nameLength = buffer.length();
83                 qParamName[i] = new char[nameLength];
84                 buffer.getChars(0, nameLength, qParamName[i], 0);
85             }
86         }
87         int dim = this.dimensions;
88         if (dim > 0) {
89             char[] dimChars = new char[dim*2];
90             for (int i = 0; i < dim; i++) {
91                 int index = i*2;
92                 dimChars[index] = '[';
93                 dimChars[index+1] = ']';
94             }
95             qParamName[length-1] = CharOperation.concat(qParamName[length-1], dimChars);
96         }
97         return qParamName;
98     }
99     
100     /* (non-Javadoc)
101      * @see org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
102      */

103     protected TypeBinding getTypeBinding(Scope scope) {
104         return null; // not supported here - combined with resolveType(...)
105
}
106     
107     /*
108      * No need to check for reference to raw type per construction
109      */

110     private TypeBinding internalResolveType(Scope scope, boolean checkBounds) {
111
112         // handle the error here
113
this.constant = Constant.NotAConstant;
114         if ((this.bits & ASTNode.DidResolve) != 0) { // is a shared type reference which was already resolved
115
if (this.resolvedType != null && !this.resolvedType.isValidBinding())
116                 return null; // already reported error
117
return this.resolvedType;
118         }
119         this.bits |= ASTNode.DidResolve;
120         boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
121         Binding binding = scope.getPackage(this.tokens);
122         if (binding != null && !binding.isValidBinding()) {
123             this.resolvedType = (ReferenceBinding) binding;
124             reportInvalidType(scope);
125             // be resilient, still attempt resolving arguments
126
for (int i = 0, max = this.tokens.length; i < max; i++) {
127                 TypeReference[] args = this.typeArguments[i];
128                 if (args != null) {
129                     int argLength = args.length;
130                     for (int j = 0; j < argLength; j++) {
131                         TypeReference typeArgument = args[j];
132                         if (isClassScope) {
133                             typeArgument.resolveType((ClassScope) scope);
134                         } else {
135                             typeArgument.resolveType((BlockScope) scope, checkBounds);
136                         }
137                     }
138                 }
139             }
140             return null;
141         }
142
143         PackageBinding packageBinding = binding == null ? null : (PackageBinding) binding;
144         boolean typeIsConsistent = true;
145         ReferenceBinding qualifiedType = null;
146         for (int i = packageBinding == null ? 0 : packageBinding.compoundName.length, max = this.tokens.length; i < max; i++) {
147             findNextTypeBinding(i, scope, packageBinding);
148             if (!(this.resolvedType.isValidBinding())) {
149                 reportInvalidType(scope);
150                 // be resilient, still attempt resolving arguments
151
for (int j = i; j < max; j++) {
152                     TypeReference[] args = this.typeArguments[j];
153                     if (args != null) {
154                         int argLength = args.length;
155                         for (int k = 0; k < argLength; k++) {
156                             TypeReference typeArgument = args[k];
157                             if (isClassScope) {
158                                 typeArgument.resolveType((ClassScope) scope);
159                             } else {
160                                 typeArgument.resolveType((BlockScope) scope);
161                             }
162                         }
163                     }
164                 }
165                 return null;
166             }
167             ReferenceBinding currentType = (ReferenceBinding) this.resolvedType;
168             if (qualifiedType == null) {
169                 qualifiedType = currentType.enclosingType(); // if member type
170
if (qualifiedType != null && (qualifiedType.isGenericType() || qualifiedType.isParameterizedType())) {
171                     qualifiedType = currentType.isStatic()
172                         ? (ReferenceBinding) scope.environment().convertToRawType(qualifiedType)
173                         : scope.environment().convertToParameterizedType(qualifiedType);
174                 }
175             }
176             if (typeIsConsistent && currentType.isStatic() && qualifiedType != null && (qualifiedType.isParameterizedType() || qualifiedType.isGenericType())) {
177                 scope.problemReporter().staticMemberOfParameterizedType(this, scope.environment().createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifiedType));
178                 typeIsConsistent = false;
179             }
180             // check generic and arity
181
TypeReference[] args = this.typeArguments[i];
182             if (args != null) {
183                 TypeReference keep = null;
184                 if (isClassScope) {
185                     keep = ((ClassScope) scope).superTypeReference;
186                     ((ClassScope) scope).superTypeReference = null;
187                 }
188                 int argLength = args.length;
189                 TypeBinding[] argTypes = new TypeBinding[argLength];
190                 boolean argHasError = false;
191                 for (int j = 0; j < argLength; j++) {
192                     TypeReference arg = args[j];
193                     TypeBinding argType = isClassScope
194                         ? arg.resolveTypeArgument((ClassScope) scope, currentType, j)
195                         : arg.resolveTypeArgument((BlockScope) scope, currentType, j);
196                     if (argType == null) {
197                         argHasError = true;
198                     } else {
199                         argTypes[j] = argType;
200                     }
201                 }
202                 if (argHasError) {
203                     return null;
204                 }
205                 if (isClassScope) {
206                     ((ClassScope) scope).superTypeReference = keep;
207                     if (((ClassScope) scope).detectHierarchyCycle(currentType, this))
208                         return null;
209                 }
210
211                 TypeVariableBinding[] typeVariables = currentType.typeVariables();
212                 if (typeVariables == Binding.NO_TYPE_VARIABLES) { // check generic
213
scope.problemReporter().nonGenericTypeCannotBeParameterized(i, this, currentType, argTypes);
214                     return null;
215                 } else if (argLength != typeVariables.length) { // check arity
216
scope.problemReporter().incorrectArityForParameterizedType(this, currentType, argTypes);
217                     return null;
218                 }
219                 // check parameterizing non-static member type of raw type
220
if (typeIsConsistent && !currentType.isStatic()) {
221                     ReferenceBinding actualEnclosing = currentType.enclosingType();
222                     if (actualEnclosing != null && actualEnclosing.isRawType()) {
223                         scope.problemReporter().rawMemberTypeCannotBeParameterized(
224                                 this, scope.environment().createRawType((ReferenceBinding)currentType.erasure(), actualEnclosing), argTypes);
225                         typeIsConsistent = false;
226                     }
227                 }
228                 ParameterizedTypeBinding parameterizedType = scope.environment().createParameterizedType((ReferenceBinding)currentType.erasure(), argTypes, qualifiedType);
229                 // check argument type compatibility
230
if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution
231
parameterizedType.boundCheck(scope, args);
232                 qualifiedType = parameterizedType;
233             } else {
234                 if (isClassScope)
235                     if (((ClassScope) scope).detectHierarchyCycle(currentType, this))
236                         return null;
237                 ReferenceBinding currentErasure = (ReferenceBinding)currentType.erasure();
238                 if (currentErasure.isGenericType()) {
239                     if (typeIsConsistent && qualifiedType != null && qualifiedType.isParameterizedType()) {
240                         scope.problemReporter().parameterizedMemberTypeMissingArguments(this, scope.environment().createParameterizedType(currentErasure, null, qualifiedType));
241                         typeIsConsistent = false;
242                     }
243                     qualifiedType = scope.environment().createRawType(currentErasure, qualifiedType); // raw type
244
} else {
245                     qualifiedType = (qualifiedType != null && qualifiedType.isParameterizedType())
246                                                     ? scope.environment().createParameterizedType(currentErasure, null, qualifiedType)
247                                                     : currentType;
248                 }
249             }
250             if (isTypeUseDeprecated(qualifiedType, scope))
251                 reportDeprecatedType(qualifiedType, scope);
252             this.resolvedType = qualifiedType;
253         }
254 // this.resolvedType = qualifiedType;
255
// array type ?
256
if (this.dimensions > 0) {
257             if (dimensions > 255)
258                 scope.problemReporter().tooManyDimensions(this);
259             this.resolvedType = scope.createArrayType(this.resolvedType, dimensions);
260         }
261         return this.resolvedType;
262     }
263     
264     public StringBuffer JavaDoc printExpression(int indent, StringBuffer JavaDoc output) {
265         int length = tokens.length;
266         for (int i = 0; i < length - 1; i++) {
267             output.append(tokens[i]);
268             TypeReference[] typeArgument = typeArguments[i];
269             if (typeArgument != null) {
270                 output.append('<');
271                 int max = typeArgument.length - 1;
272                 for (int j = 0; j < max; j++) {
273                     typeArgument[j].print(0, output);
274                     output.append(", ");//$NON-NLS-1$
275
}
276                 typeArgument[max].print(0, output);
277                 output.append('>');
278             }
279             output.append('.');
280         }
281         output.append(tokens[length - 1]);
282         TypeReference[] typeArgument = typeArguments[length - 1];
283         if (typeArgument != null) {
284             output.append('<');
285             int max = typeArgument.length - 1;
286             for (int j = 0; j < max; j++) {
287                 typeArgument[j].print(0, output);
288                 output.append(", ");//$NON-NLS-1$
289
}
290             typeArgument[max].print(0, output);
291             output.append('>');
292         }
293         if ((this.bits & IsVarArgs) != 0) {
294             for (int i= 0 ; i < dimensions - 1; i++) {
295                 output.append("[]"); //$NON-NLS-1$
296
}
297             output.append("..."); //$NON-NLS-1$
298
} else {
299             for (int i= 0 ; i < dimensions; i++) {
300                 output.append("[]"); //$NON-NLS-1$
301
}
302         }
303         return output;
304     }
305     
306     public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
307         return internalResolveType(scope, checkBounds);
308     }
309     public TypeBinding resolveType(ClassScope scope) {
310         return internalResolveType(scope, false);
311     }
312     public void traverse(ASTVisitor visitor, BlockScope scope) {
313         if (visitor.visit(this, scope)) {
314             for (int i = 0, max = this.typeArguments.length; i < max; i++) {
315                 if (this.typeArguments[i] != null) {
316                     for (int j = 0, max2 = this.typeArguments[i].length; j < max2; j++) {
317                         this.typeArguments[i][j].traverse(visitor, scope);
318                     }
319                 }
320             }
321         }
322         visitor.endVisit(this, scope);
323     }
324     
325     public void traverse(ASTVisitor visitor, ClassScope scope) {
326         if (visitor.visit(this, scope)) {
327             for (int i = 0, max = this.typeArguments.length; i < max; i++) {
328                 if (this.typeArguments[i] != null) {
329                     for (int j = 0, max2 = this.typeArguments[i].length; j < max2; j++) {
330                         this.typeArguments[i][j].traverse(visitor, scope);
331                     }
332                 }
333             }
334         }
335         visitor.endVisit(this, scope);
336     }
337
338 }
339
Popular Tags