001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.compiler.ast;
011:
012: import org.eclipse.jdt.core.compiler.CharOperation;
013: import org.eclipse.jdt.internal.compiler.ASTVisitor;
014: import org.eclipse.jdt.internal.compiler.impl.Constant;
015: import org.eclipse.jdt.internal.compiler.lookup.*;
016:
017: /**
018: * Syntactic representation of a reference to a generic type.
019: * Note that it might also have a dimension.
020: */
021: public class ParameterizedSingleTypeReference extends
022: ArrayTypeReference {
023:
024: public TypeReference[] typeArguments;
025:
026: public ParameterizedSingleTypeReference(char[] name,
027: TypeReference[] typeArguments, int dim, long pos) {
028: super (name, dim, pos);
029: this .originalSourceEnd = this .sourceEnd;
030: this .typeArguments = typeArguments;
031: }
032:
033: public void checkBounds(Scope scope) {
034: if (this .resolvedType == null)
035: return;
036:
037: if (this .resolvedType.leafComponentType() instanceof ParameterizedTypeBinding) {
038: ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) this .resolvedType
039: .leafComponentType();
040: ReferenceBinding currentType = parameterizedType
041: .genericType();
042: TypeVariableBinding[] typeVariables = currentType
043: .typeVariables();
044: TypeBinding[] argTypes = parameterizedType.arguments;
045: if (argTypes != null && typeVariables != null) { // may be null in error cases
046: parameterizedType.boundCheck(scope, this .typeArguments);
047: }
048: }
049: }
050:
051: /**
052: * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#copyDims(int)
053: */
054: public TypeReference copyDims(int dim) {
055: return new ParameterizedSingleTypeReference(token,
056: typeArguments, dim, (((long) sourceStart) << 32)
057: + sourceEnd);
058: }
059:
060: /**
061: * @return char[][]
062: */
063: public char[][] getParameterizedTypeName() {
064: StringBuffer buffer = new StringBuffer(5);
065: buffer.append(this .token).append('<');
066: for (int i = 0, length = this .typeArguments.length; i < length; i++) {
067: if (i > 0)
068: buffer.append(',');
069: buffer.append(CharOperation.concatWith(
070: this .typeArguments[i].getParameterizedTypeName(),
071: '.'));
072: }
073: buffer.append('>');
074: int nameLength = buffer.length();
075: char[] name = new char[nameLength];
076: buffer.getChars(0, nameLength, name, 0);
077: int dim = this .dimensions;
078: if (dim > 0) {
079: char[] dimChars = new char[dim * 2];
080: for (int i = 0; i < dim; i++) {
081: int index = i * 2;
082: dimChars[index] = '[';
083: dimChars[index + 1] = ']';
084: }
085: name = CharOperation.concat(name, dimChars);
086: }
087: return new char[][] { name };
088: }
089:
090: /**
091: * @see org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
092: */
093: protected TypeBinding getTypeBinding(Scope scope) {
094: return null; // not supported here - combined with resolveType(...)
095: }
096:
097: /*
098: * No need to check for reference to raw type per construction
099: */
100: private TypeBinding internalResolveType(Scope scope,
101: ReferenceBinding enclosingType, boolean checkBounds) {
102:
103: // handle the error here
104: this .constant = Constant.NotAConstant;
105: if ((this .bits & ASTNode.DidResolve) != 0) { // is a shared type reference which was already resolved
106: if (this .resolvedType != null
107: && !this .resolvedType.isValidBinding())
108: return null; // already reported error
109: return this .resolvedType;
110: }
111: this .bits |= ASTNode.DidResolve;
112: if (enclosingType == null) {
113: this .resolvedType = scope.getType(token);
114: if (!(this .resolvedType.isValidBinding())) {
115: reportInvalidType(scope);
116: // be resilient, still attempt resolving arguments
117: boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
118: int argLength = this .typeArguments.length;
119: for (int i = 0; i < argLength; i++) {
120: TypeReference typeArgument = this .typeArguments[i];
121: if (isClassScope) {
122: typeArgument.resolveType((ClassScope) scope);
123: } else {
124: typeArgument.resolveType((BlockScope) scope,
125: checkBounds);
126: }
127: }
128: return null;
129: }
130: enclosingType = this .resolvedType.enclosingType(); // if member type
131: if (enclosingType != null
132: && (enclosingType.isGenericType() || enclosingType
133: .isParameterizedType())) {
134: ReferenceBinding currentType = (ReferenceBinding) this .resolvedType;
135: enclosingType = currentType.isStatic() ? (ReferenceBinding) scope
136: .environment().convertToRawType(enclosingType)
137: : scope.environment()
138: .convertToParameterizedType(
139: enclosingType);
140: }
141: } else { // resolving member type (relatively to enclosingType)
142: this .resolvedType = scope.getMemberType(token,
143: enclosingType);
144: if (!this .resolvedType.isValidBinding()) {
145: scope.problemReporter().invalidEnclosingType(this ,
146: this .resolvedType, enclosingType);
147: return null;
148: }
149: if (isTypeUseDeprecated(this .resolvedType, scope))
150: scope.problemReporter().deprecatedType(
151: this .resolvedType, this );
152: }
153:
154: // check generic and arity
155: boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
156: TypeReference keep = null;
157: if (isClassScope) {
158: keep = ((ClassScope) scope).super TypeReference;
159: ((ClassScope) scope).super TypeReference = null;
160: }
161: ReferenceBinding currentType = (ReferenceBinding) this .resolvedType;
162: int argLength = this .typeArguments.length;
163: TypeBinding[] argTypes = new TypeBinding[argLength];
164: boolean argHasError = false;
165: for (int i = 0; i < argLength; i++) {
166: TypeReference typeArgument = this .typeArguments[i];
167: TypeBinding argType = isClassScope ? typeArgument
168: .resolveTypeArgument((ClassScope) scope,
169: currentType, i) : typeArgument
170: .resolveTypeArgument((BlockScope) scope,
171: currentType, i);
172: if (argType == null) {
173: argHasError = true;
174: } else {
175: argTypes[i] = argType;
176: }
177: }
178: if (argHasError)
179: return null;
180: if (isClassScope) {
181: ((ClassScope) scope).super TypeReference = keep;
182: if (((ClassScope) scope).detectHierarchyCycle(currentType,
183: this ))
184: return null;
185: }
186:
187: TypeVariableBinding[] typeVariables = currentType
188: .typeVariables();
189: if (typeVariables == Binding.NO_TYPE_VARIABLES) { // check generic
190: scope.problemReporter()
191: .nonGenericTypeCannotBeParameterized(this ,
192: currentType, argTypes);
193: return null;
194: } else if (argLength != typeVariables.length) { // check arity
195: scope.problemReporter().incorrectArityForParameterizedType(
196: this , currentType, argTypes);
197: return null;
198: } else if (!currentType.isStatic()) {
199: ReferenceBinding actualEnclosing = currentType
200: .enclosingType();
201: if (actualEnclosing != null && actualEnclosing.isRawType()) {
202: scope.problemReporter()
203: .rawMemberTypeCannotBeParameterized(
204: this ,
205: scope.environment().createRawType(
206: (ReferenceBinding) currentType
207: .erasure(),
208: actualEnclosing), argTypes);
209: return null;
210: }
211: }
212:
213: ParameterizedTypeBinding parameterizedType = scope
214: .environment().createParameterizedType(
215: (ReferenceBinding) currentType.erasure(),
216: argTypes, enclosingType);
217: // check argument type compatibility
218: if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution
219: parameterizedType.boundCheck(scope, this .typeArguments);
220:
221: this .resolvedType = parameterizedType;
222: if (isTypeUseDeprecated(this .resolvedType, scope))
223: reportDeprecatedType(this .resolvedType, scope);
224:
225: // array type ?
226: if (this .dimensions > 0) {
227: if (dimensions > 255)
228: scope.problemReporter().tooManyDimensions(this );
229: this .resolvedType = scope.createArrayType(
230: this .resolvedType, dimensions);
231: }
232: return this .resolvedType;
233: }
234:
235: public StringBuffer printExpression(int indent, StringBuffer output) {
236: output.append(token);
237: output.append("<"); //$NON-NLS-1$
238: int max = typeArguments.length - 1;
239: for (int i = 0; i < max; i++) {
240: typeArguments[i].print(0, output);
241: output.append(", ");//$NON-NLS-1$
242: }
243: typeArguments[max].print(0, output);
244: output.append(">"); //$NON-NLS-1$
245: if ((this .bits & IsVarArgs) != 0) {
246: for (int i = 0; i < dimensions - 1; i++) {
247: output.append("[]"); //$NON-NLS-1$
248: }
249: output.append("..."); //$NON-NLS-1$
250: } else {
251: for (int i = 0; i < dimensions; i++) {
252: output.append("[]"); //$NON-NLS-1$
253: }
254: }
255: return output;
256: }
257:
258: public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
259: return internalResolveType(scope, null, checkBounds);
260: }
261:
262: public TypeBinding resolveType(ClassScope scope) {
263: return internalResolveType(scope, null, false /*no bounds check in classScope*/);
264: }
265:
266: public TypeBinding resolveTypeEnclosing(BlockScope scope,
267: ReferenceBinding enclosingType) {
268: return internalResolveType(scope, enclosingType, true/*check bounds*/);
269: }
270:
271: public void traverse(ASTVisitor visitor, BlockScope scope) {
272: if (visitor.visit(this , scope)) {
273: for (int i = 0, max = this .typeArguments.length; i < max; i++) {
274: this .typeArguments[i].traverse(visitor, scope);
275: }
276: }
277: visitor.endVisit(this , scope);
278: }
279:
280: public void traverse(ASTVisitor visitor, ClassScope scope) {
281: if (visitor.visit(this , scope)) {
282: for (int i = 0, max = this.typeArguments.length; i < max; i++) {
283: this.typeArguments[i].traverse(visitor, scope);
284: }
285: }
286: visitor.endVisit(this, scope);
287: }
288: }
|