1 /******************************************************************************* 2 * Copyright (c) 2000, 2004 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 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.lookup.*; 16 17 /** 18 * Syntactic representation of a reference to a generic type. 19 * Note that it might also have a dimension. 20 */ 21 public class ParameterizedSingleTypeReference extends ArrayTypeReference { 22 23 public TypeReference[] typeArguments; 24 private boolean didResolve = false; 25 ParameterizedSingleTypeReference(char[] name, TypeReference[] typeArguments, int dim, long pos)26 public ParameterizedSingleTypeReference(char[] name, TypeReference[] typeArguments, int dim, long pos){ 27 super(name, dim, pos); 28 this.typeArguments = typeArguments; 29 } checkBounds(Scope scope)30 public void checkBounds(Scope scope) { 31 if (this.resolvedType == null) return; 32 33 if (this.resolvedType.leafComponentType() instanceof ParameterizedTypeBinding) { 34 ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) this.resolvedType.leafComponentType(); 35 ReferenceBinding currentType = parameterizedType.type; 36 TypeVariableBinding[] typeVariables = currentType.typeVariables(); 37 TypeBinding[] argTypes = parameterizedType.arguments; 38 if (argTypes != null && typeVariables != null) { // may be null in error cases 39 for (int i = 0, argLength = typeVariables.length; i < argLength; i++) 40 if (!typeVariables[i].boundCheck(parameterizedType, argTypes[i])) 41 scope.problemReporter().typeMismatchError(argTypes[i], typeVariables[i], currentType, this.typeArguments[i]); 42 } 43 } 44 } 45 /** 46 * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#copyDims(int) 47 */ copyDims(int dim)48 public TypeReference copyDims(int dim) { 49 this.dimensions = dim; 50 return this; 51 } 52 53 /** 54 * @return char[][] 55 */ getParameterizedTypeName()56 public char [][] getParameterizedTypeName(){ 57 StringBuffer buffer = new StringBuffer(5); 58 buffer.append(this.token).append('<'); 59 for (int i = 0, length = this.typeArguments.length; i < length; i++) { 60 if (i > 0) buffer.append(','); 61 buffer.append(CharOperation.concatWith(this.typeArguments[i].getParameterizedTypeName(), '.')); 62 } 63 buffer.append('>'); 64 int nameLength = buffer.length(); 65 char[] name = new char[nameLength]; 66 buffer.getChars(0, nameLength, name, 0); 67 int dim = this.dimensions; 68 if (dim > 0) { 69 char[] dimChars = new char[dim*2]; 70 for (int i = 0; i < dim; i++) { 71 int index = i*2; 72 dimChars[index] = '['; 73 dimChars[index+1] = ']'; 74 } 75 name = CharOperation.concat(name, dimChars); 76 } 77 return new char[][]{ name }; 78 } 79 /** 80 * @see org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope) 81 */ getTypeBinding(Scope scope)82 protected TypeBinding getTypeBinding(Scope scope) { 83 return null; // not supported here - combined with resolveType(...) 84 } 85 86 /* 87 * No need to check for reference to raw type per construction 88 */ internalResolveType(Scope scope, ReferenceBinding enclosingType)89 private TypeBinding internalResolveType(Scope scope, ReferenceBinding enclosingType) { 90 91 // handle the error here 92 this.constant = NotAConstant; 93 if (this.didResolve) { // is a shared type reference which was already resolved 94 if (this.resolvedType != null && !this.resolvedType.isValidBinding()) 95 return null; // already reported error 96 return this.resolvedType; 97 } 98 this.didResolve = true; 99 if (enclosingType == null) { 100 this.resolvedType = scope.getType(token); 101 if (!(this.resolvedType.isValidBinding())) { 102 reportInvalidType(scope); 103 return null; 104 } 105 } else { // resolving member type (relatively to enclosingType) 106 this.resolvedType = scope.getMemberType(token, (ReferenceBinding)enclosingType.erasure()); 107 if (!this.resolvedType.isValidBinding()) { 108 scope.problemReporter().invalidEnclosingType(this, this.resolvedType, enclosingType); 109 return null; 110 } 111 if (isTypeUseDeprecated(this.resolvedType, scope)) 112 scope.problemReporter().deprecatedType(this.resolvedType, this); 113 } 114 115 // check generic and arity 116 boolean isClassScope = scope.kind == Scope.CLASS_SCOPE; 117 ReferenceBinding currentType = (ReferenceBinding) this.resolvedType; 118 int argLength = this.typeArguments.length; 119 TypeBinding[] argTypes = new TypeBinding[argLength]; 120 boolean argHasError = false; 121 for (int i = 0; i < argLength; i++) { 122 TypeReference typeArgument = this.typeArguments[i]; 123 TypeBinding argType = isClassScope 124 ? typeArgument.resolveTypeArgument((ClassScope) scope, currentType, i) 125 : typeArgument.resolveTypeArgument((BlockScope) scope, currentType, i); 126 if (argType == null) { 127 argHasError = true; 128 } else { 129 argTypes[i] = argType; 130 } 131 } 132 if (argHasError) return null; 133 // TODO (philippe) if ((this.bits & ASTNode.IsSuperType) != 0) 134 if (isClassScope) 135 if (((ClassScope) scope).detectCycle(currentType, this, argTypes)) 136 return null; 137 138 TypeVariableBinding[] typeVariables = currentType.typeVariables(); 139 if (typeVariables == NoTypeVariables) { // check generic 140 scope.problemReporter().nonGenericTypeCannotBeParameterized(this, currentType, argTypes); 141 return null; 142 } else if (argLength != typeVariables.length) { // check arity 143 scope.problemReporter().incorrectArityForParameterizedType(this, currentType, argTypes); 144 return null; 145 } 146 // if generic type X<T> is referred to as parameterized X<T>, then answer itself 147 checkGeneric: { 148 for (int i = 0; i < argLength; i++) 149 if (typeVariables[i] != argTypes[i]) 150 break checkGeneric; 151 return currentType; 152 } 153 ParameterizedTypeBinding parameterizedType = scope.createParameterizedType(currentType, argTypes, enclosingType); 154 // check argument type compatibility now if not a class scope 155 if (!isClassScope) // otherwise will do it in Scope.connectTypeVariables() 156 for (int i = 0; i < argLength; i++) 157 if (!typeVariables[i].boundCheck(parameterizedType, argTypes[i])) 158 scope.problemReporter().typeMismatchError(argTypes[i], typeVariables[i], currentType, this.typeArguments[i]); 159 160 this.resolvedType = parameterizedType; 161 if (isTypeUseDeprecated(this.resolvedType, scope)) 162 reportDeprecatedType(scope); 163 // array type ? 164 if (this.dimensions > 0) { 165 if (dimensions > 255) 166 scope.problemReporter().tooManyDimensions(this); 167 this.resolvedType = scope.createArrayType(parameterizedType, dimensions); 168 } 169 return this.resolvedType; 170 } 171 printExpression(int indent, StringBuffer output)172 public StringBuffer printExpression(int indent, StringBuffer output){ 173 output.append(token); 174 output.append("<"); //$NON-NLS-1$ 175 int max = typeArguments.length - 1; 176 for (int i= 0; i < max; i++) { 177 typeArguments[i].print(0, output); 178 output.append(", ");//$NON-NLS-1$ 179 } 180 typeArguments[max].print(0, output); 181 output.append(">"); //$NON-NLS-1$ 182 for (int i= 0 ; i < dimensions ; i++) { 183 output.append("[]"); //$NON-NLS-1$ 184 } 185 return output; 186 } 187 resolveType(BlockScope scope)188 public TypeBinding resolveType(BlockScope scope) { 189 return internalResolveType(scope, null); 190 } 191 resolveType(ClassScope scope)192 public TypeBinding resolveType(ClassScope scope) { 193 return internalResolveType(scope, null); 194 } 195 resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType)196 public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) { 197 return internalResolveType(scope, enclosingType); 198 } 199 traverse(ASTVisitor visitor, BlockScope scope)200 public void traverse(ASTVisitor visitor, BlockScope scope) { 201 if (visitor.visit(this, scope)) { 202 for (int i = 0, max = this.typeArguments.length; i < max; i++) { 203 this.typeArguments[i].traverse(visitor, scope); 204 } 205 } 206 visitor.endVisit(this, scope); 207 } 208 traverse(ASTVisitor visitor, ClassScope scope)209 public void traverse(ASTVisitor visitor, ClassScope scope) { 210 if (visitor.visit(this, scope)) { 211 for (int i = 0, max = this.typeArguments.length; i < max; i++) { 212 this.typeArguments[i].traverse(visitor, scope); 213 } 214 } 215 visitor.endVisit(this, scope); 216 } 217 } 218