1 /******************************************************************************* 2 * Copyright (c) 2000, 2014 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 * Stephan Herrmann - Contributions for 11 * bug 342671 - ClassCastException: org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding cannot be cast to org.eclipse.jdt.internal.compiler.lookup.ArrayBinding 12 * bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis 13 * Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099 14 * Bug 416181 – [1.8][compiler][null] Invalid assignment is not rejected by the compiler 15 * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault 16 * Bug 434600 - Incorrect null analysis error reporting on type parameters 17 * Andy Clement - Contributions for 18 * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) 19 *******************************************************************************/ 20 package org.eclipse.jdt.internal.compiler.ast; 21 22 import org.eclipse.jdt.core.compiler.CharOperation; 23 import org.eclipse.jdt.internal.compiler.ASTVisitor; 24 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 25 import org.eclipse.jdt.internal.compiler.impl.Constant; 26 import org.eclipse.jdt.internal.compiler.lookup.*; 27 28 /** 29 * Syntactic representation of a reference to a generic type. 30 * Note that it might also have a dimension. 31 */ 32 public class ParameterizedQualifiedTypeReference extends ArrayQualifiedTypeReference { 33 34 public TypeReference[][] typeArguments; 35 36 /** 37 * @param tokens 38 * @param dim 39 * @param positions 40 */ ParameterizedQualifiedTypeReference(char[][] tokens, TypeReference[][] typeArguments, int dim, long[] positions)41 public ParameterizedQualifiedTypeReference(char[][] tokens, TypeReference[][] typeArguments, int dim, long[] positions) { 42 43 super(tokens, dim, positions); 44 this.typeArguments = typeArguments; 45 annotationSearch: for (int i = 0, max = typeArguments.length; i < max; i++) { 46 TypeReference[] typeArgumentsOnTypeComponent = typeArguments[i]; 47 if (typeArgumentsOnTypeComponent != null) { 48 for (int j = 0, max2 = typeArgumentsOnTypeComponent.length; j < max2; j++) { 49 if ((typeArgumentsOnTypeComponent[j].bits & ASTNode.HasTypeAnnotations) != 0) { 50 this.bits |= ASTNode.HasTypeAnnotations; 51 break annotationSearch; 52 } 53 } 54 } 55 } 56 } ParameterizedQualifiedTypeReference(char[][] tokens, TypeReference[][] typeArguments, int dim, Annotation[][] annotationsOnDimensions, long[] positions)57 public ParameterizedQualifiedTypeReference(char[][] tokens, TypeReference[][] typeArguments, int dim, Annotation[][] annotationsOnDimensions, long[] positions) { 58 this(tokens, typeArguments, dim, positions); 59 setAnnotationsOnDimensions(annotationsOnDimensions); 60 if (annotationsOnDimensions != null) { 61 this.bits |= ASTNode.HasTypeAnnotations; 62 } 63 } checkBounds(Scope scope)64 public void checkBounds(Scope scope) { 65 if (this.resolvedType == null) return; 66 67 checkBounds( 68 (ReferenceBinding) this.resolvedType.leafComponentType(), 69 scope, 70 this.typeArguments.length - 1); 71 } checkBounds(ReferenceBinding type, Scope scope, int index)72 public void checkBounds(ReferenceBinding type, Scope scope, int index) { 73 // recurse on enclosing type if any, and assuming explictly part of the reference (index>0) 74 if (index > 0 && type.enclosingType() != null) { 75 checkBounds(type.enclosingType(), scope, index - 1); 76 } 77 if (type.isParameterizedTypeWithActualArguments()) { 78 ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) type; 79 ReferenceBinding currentType = parameterizedType.genericType(); 80 TypeVariableBinding[] typeVariables = currentType.typeVariables(); 81 if (typeVariables != null) { // argTypes may be null in error cases 82 parameterizedType.boundCheck(scope, this.typeArguments[index]); 83 } 84 } 85 checkNullConstraints(scope, this.typeArguments[index]); 86 } augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs)87 public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs) { 88 int totalDimensions = this.dimensions() + additionalDimensions; 89 Annotation [][] allAnnotations = getMergedAnnotationsOnDimensions(additionalDimensions, additionalAnnotations); 90 ParameterizedQualifiedTypeReference pqtr = new ParameterizedQualifiedTypeReference(this.tokens, this.typeArguments, totalDimensions, allAnnotations, this.sourcePositions); 91 pqtr.annotations = this.annotations; 92 pqtr.bits |= (this.bits & ASTNode.HasTypeAnnotations); 93 if (!isVarargs) 94 pqtr.extendedDimensions = additionalDimensions; 95 return pqtr; 96 } isParameterizedTypeReference()97 public boolean isParameterizedTypeReference() { 98 return true; 99 } 100 101 /** 102 * @return char[][] 103 */ getParameterizedTypeName()104 public char [][] getParameterizedTypeName(){ 105 int length = this.tokens.length; 106 char[][] qParamName = new char[length][]; 107 for (int i = 0; i < length; i++) { 108 TypeReference[] arguments = this.typeArguments[i]; 109 if (arguments == null) { 110 qParamName[i] = this.tokens[i]; 111 } else { 112 StringBuffer buffer = new StringBuffer(5); 113 buffer.append(this.tokens[i]); 114 buffer.append('<'); 115 for (int j = 0, argLength =arguments.length; j < argLength; j++) { 116 if (j > 0) buffer.append(','); 117 buffer.append(CharOperation.concatWith(arguments[j].getParameterizedTypeName(), '.')); 118 } 119 buffer.append('>'); 120 int nameLength = buffer.length(); 121 qParamName[i] = new char[nameLength]; 122 buffer.getChars(0, nameLength, qParamName[i], 0); 123 } 124 } 125 int dim = this.dimensions; 126 if (dim > 0) { 127 char[] dimChars = new char[dim*2]; 128 for (int i = 0; i < dim; i++) { 129 int index = i*2; 130 dimChars[index] = '['; 131 dimChars[index+1] = ']'; 132 } 133 qParamName[length-1] = CharOperation.concat(qParamName[length-1], dimChars); 134 } 135 return qParamName; 136 } 137 getTypeArguments()138 public TypeReference[][] getTypeArguments() { 139 return this.typeArguments; 140 } 141 142 /* (non-Javadoc) 143 * @see org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope) 144 */ getTypeBinding(Scope scope)145 protected TypeBinding getTypeBinding(Scope scope) { 146 return null; // not supported here - combined with resolveType(...) 147 } 148 149 /* 150 * No need to check for reference to raw type per construction 151 */ internalResolveType(Scope scope, boolean checkBounds, int location)152 private TypeBinding internalResolveType(Scope scope, boolean checkBounds, int location) { 153 // handle the error here 154 this.constant = Constant.NotAConstant; 155 if ((this.bits & ASTNode.DidResolve) != 0) { // is a shared type reference which was already resolved 156 if (this.resolvedType != null) { // is a shared type reference which was already resolved 157 if (this.resolvedType.isValidBinding()) { 158 return this.resolvedType; 159 } else { 160 switch (this.resolvedType.problemId()) { 161 case ProblemReasons.NotFound : 162 case ProblemReasons.NotVisible : 163 case ProblemReasons.InheritedNameHidesEnclosingName : 164 TypeBinding type = this.resolvedType.closestMatch(); 165 return type; 166 default : 167 return null; 168 } 169 } 170 } 171 } 172 this.bits |= ASTNode.DidResolve; 173 TypeBinding type = internalResolveLeafType(scope, checkBounds); 174 createArrayType(scope); 175 resolveAnnotations(scope, location); 176 if (this.typeArguments != null && checkBounds) 177 // relevant null annotations are on the inner most type: 178 checkNullConstraints(scope, this.typeArguments[this.typeArguments.length-1]); 179 return type == null ? type : this.resolvedType; 180 } internalResolveLeafType(Scope scope, boolean checkBounds)181 private TypeBinding internalResolveLeafType(Scope scope, boolean checkBounds) { 182 boolean isClassScope = scope.kind == Scope.CLASS_SCOPE; 183 Binding binding = scope.getPackage(this.tokens); 184 if (binding != null && !binding.isValidBinding()) { 185 this.resolvedType = (ReferenceBinding) binding; 186 reportInvalidType(scope); 187 // be resilient, still attempt resolving arguments 188 for (int i = 0, max = this.tokens.length; i < max; i++) { 189 TypeReference[] args = this.typeArguments[i]; 190 if (args != null) { 191 int argLength = args.length; 192 for (int j = 0; j < argLength; j++) { 193 TypeReference typeArgument = args[j]; 194 if (isClassScope) { 195 typeArgument.resolveType((ClassScope) scope); 196 } else { 197 typeArgument.resolveType((BlockScope) scope, checkBounds); 198 } 199 } 200 } 201 } 202 return null; 203 } 204 205 PackageBinding packageBinding = binding == null ? null : (PackageBinding) binding; 206 rejectAnnotationsOnPackageQualifiers(scope, packageBinding); 207 208 boolean typeIsConsistent = true; 209 ReferenceBinding qualifyingType = null; 210 for (int i = packageBinding == null ? 0 : packageBinding.compoundName.length, max = this.tokens.length; i < max; i++) { 211 findNextTypeBinding(i, scope, packageBinding); 212 if (!(this.resolvedType.isValidBinding())) { 213 reportInvalidType(scope); 214 // be resilient, still attempt resolving arguments 215 for (int j = i; j < max; j++) { 216 TypeReference[] args = this.typeArguments[j]; 217 if (args != null) { 218 int argLength = args.length; 219 for (int k = 0; k < argLength; k++) { 220 TypeReference typeArgument = args[k]; 221 if (isClassScope) { 222 typeArgument.resolveType((ClassScope) scope); 223 } else { 224 typeArgument.resolveType((BlockScope) scope); 225 } 226 } 227 } 228 } 229 return null; 230 } 231 ReferenceBinding currentType = (ReferenceBinding) this.resolvedType; 232 if (qualifyingType == null) { 233 qualifyingType = currentType.enclosingType(); // if member type 234 if (qualifyingType != null) { 235 qualifyingType = currentType.isStatic() 236 ? (ReferenceBinding) scope.environment().convertToRawType(qualifyingType, false /*do not force conversion of enclosing types*/) 237 : scope.environment().convertToParameterizedType(qualifyingType); 238 } 239 } else { 240 if (this.annotations != null) 241 rejectAnnotationsOnStaticMemberQualififer(scope, currentType, this.annotations[i-1]); 242 if (typeIsConsistent && currentType.isStatic() 243 && (qualifyingType.isParameterizedTypeWithActualArguments() || qualifyingType.isGenericType())) { 244 scope.problemReporter().staticMemberOfParameterizedType(this, scope.environment().createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifyingType), i); 245 typeIsConsistent = false; 246 } 247 ReferenceBinding enclosingType = currentType.enclosingType(); 248 if (enclosingType != null && TypeBinding.notEquals(enclosingType.erasure(), qualifyingType.erasure())) { // qualifier != declaring/enclosing 249 qualifyingType = enclosingType; // inherited member type, leave it associated with its enclosing rather than subtype 250 } 251 } 252 253 // check generic and arity 254 TypeReference[] args = this.typeArguments[i]; 255 if (args != null) { 256 TypeReference keep = null; 257 if (isClassScope) { 258 keep = ((ClassScope) scope).superTypeReference; 259 ((ClassScope) scope).superTypeReference = null; 260 } 261 int argLength = args.length; 262 boolean isDiamond = argLength == 0 && (i == (max -1)) && ((this.bits & ASTNode.IsDiamond) != 0); 263 TypeBinding[] argTypes = new TypeBinding[argLength]; 264 boolean argHasError = false; 265 ReferenceBinding currentOriginal = (ReferenceBinding)currentType.original(); 266 for (int j = 0; j < argLength; j++) { 267 TypeReference arg = args[j]; 268 TypeBinding argType = isClassScope 269 ? arg.resolveTypeArgument((ClassScope) scope, currentOriginal, j) 270 : arg.resolveTypeArgument((BlockScope) scope, currentOriginal, j); 271 if (argType == null) { 272 argHasError = true; 273 } else { 274 argTypes[j] = argType; 275 } 276 } 277 if (argHasError) { 278 return null; 279 } 280 if (isClassScope) { 281 ((ClassScope) scope).superTypeReference = keep; 282 if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this)) 283 return null; 284 } 285 286 TypeVariableBinding[] typeVariables = currentOriginal.typeVariables(); 287 if (typeVariables == Binding.NO_TYPE_VARIABLES) { // check generic 288 if (scope.compilerOptions().originalSourceLevel >= ClassFileConstants.JDK1_5) { // below 1.5, already reported as syntax error 289 scope.problemReporter().nonGenericTypeCannotBeParameterized(i, this, currentType, argTypes); 290 return null; 291 } 292 this.resolvedType = (qualifyingType != null && qualifyingType.isParameterizedType()) 293 ? scope.environment().createParameterizedType(currentOriginal, null, qualifyingType) 294 : currentType; 295 return this.resolvedType; 296 } else if (argLength != typeVariables.length) { 297 if (!isDiamond) { // check arity 298 scope.problemReporter().incorrectArityForParameterizedType(this, currentType, argTypes, i); 299 return null; 300 } 301 } 302 // check parameterizing non-static member type of raw type 303 if (typeIsConsistent && !currentType.isStatic()) { 304 ReferenceBinding actualEnclosing = currentType.enclosingType(); 305 if (actualEnclosing != null && actualEnclosing.isRawType()) { 306 scope.problemReporter().rawMemberTypeCannotBeParameterized( 307 this, scope.environment().createRawType(currentOriginal, actualEnclosing), argTypes); 308 typeIsConsistent = false; 309 } 310 } 311 ParameterizedTypeBinding parameterizedType = scope.environment().createParameterizedType(currentOriginal, argTypes, qualifyingType); 312 // check argument type compatibility for non <> cases - <> case needs no bounds check, we will scream foul if needed during inference. 313 if (!isDiamond) { 314 if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution 315 parameterizedType.boundCheck(scope, args); 316 else 317 scope.deferBoundCheck(this); 318 } 319 qualifyingType = parameterizedType; 320 } else { 321 ReferenceBinding currentOriginal = (ReferenceBinding)currentType.original(); 322 if (isClassScope) 323 if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this)) 324 return null; 325 if (currentOriginal.isGenericType()) { 326 if (typeIsConsistent && qualifyingType != null && qualifyingType.isParameterizedType()) { 327 scope.problemReporter().parameterizedMemberTypeMissingArguments(this, scope.environment().createParameterizedType(currentOriginal, null, qualifyingType), i); 328 typeIsConsistent = false; 329 } 330 qualifyingType = scope.environment().createRawType(currentOriginal, qualifyingType); // raw type 331 } else { 332 qualifyingType = (qualifyingType != null && qualifyingType.isParameterizedType()) 333 ? scope.environment().createParameterizedType(currentOriginal, null, qualifyingType) 334 : currentType; 335 } 336 } 337 if (isTypeUseDeprecated(qualifyingType, scope)) 338 reportDeprecatedType(qualifyingType, scope, i); 339 this.resolvedType = qualifyingType; 340 recordResolution(scope.environment(), this.resolvedType); 341 } 342 return this.resolvedType; 343 } createArrayType(Scope scope)344 private void createArrayType(Scope scope) { 345 if (this.dimensions > 0) { 346 if (this.dimensions > 255) 347 scope.problemReporter().tooManyDimensions(this); 348 this.resolvedType = scope.createArrayType(this.resolvedType, this.dimensions); 349 } 350 } 351 printExpression(int indent, StringBuffer output)352 public StringBuffer printExpression(int indent, StringBuffer output) { 353 int length = this.tokens.length; 354 for (int i = 0; i < length - 1; i++) { 355 if (this.annotations != null && this.annotations[i] != null) { 356 printAnnotations(this.annotations[i], output); 357 output.append(' '); 358 } 359 output.append(this.tokens[i]); 360 TypeReference[] typeArgument = this.typeArguments[i]; 361 if (typeArgument != null) { 362 output.append('<'); 363 int typeArgumentLength = typeArgument.length; 364 if (typeArgumentLength > 0) { 365 int max = typeArgumentLength - 1; 366 for (int j = 0; j < max; j++) { 367 typeArgument[j].print(0, output); 368 output.append(", ");//$NON-NLS-1$ 369 } 370 typeArgument[max].print(0, output); 371 } 372 output.append('>'); 373 } 374 output.append('.'); 375 } 376 if (this.annotations != null && this.annotations[length - 1] != null) { 377 output.append(" "); //$NON-NLS-1$ 378 printAnnotations(this.annotations[length - 1], output); 379 output.append(' '); 380 } 381 output.append(this.tokens[length - 1]); 382 TypeReference[] typeArgument = this.typeArguments[length - 1]; 383 if (typeArgument != null) { 384 output.append('<'); 385 int typeArgumentLength = typeArgument.length; 386 if (typeArgumentLength > 0) { 387 int max = typeArgumentLength - 1; 388 for (int j = 0; j < max; j++) { 389 typeArgument[j].print(0, output); 390 output.append(", ");//$NON-NLS-1$ 391 } 392 typeArgument[max].print(0, output); 393 } 394 output.append('>'); 395 } 396 Annotation [][] annotationsOnDimensions = this.getAnnotationsOnDimensions(); 397 if ((this.bits & IsVarArgs) != 0) { 398 for (int i= 0 ; i < this.dimensions - 1; i++) { 399 if (annotationsOnDimensions != null && annotationsOnDimensions[i] != null) { 400 output.append(" "); //$NON-NLS-1$ 401 printAnnotations(annotationsOnDimensions[i], output); 402 output.append(" "); //$NON-NLS-1$ 403 } 404 output.append("[]"); //$NON-NLS-1$ 405 } 406 if (annotationsOnDimensions != null && annotationsOnDimensions[this.dimensions - 1] != null) { 407 output.append(" "); //$NON-NLS-1$ 408 printAnnotations(annotationsOnDimensions[this.dimensions - 1], output); 409 output.append(" "); //$NON-NLS-1$ 410 } 411 output.append("..."); //$NON-NLS-1$ 412 } else { 413 for (int i= 0 ; i < this.dimensions; i++) { 414 if (annotationsOnDimensions != null && annotationsOnDimensions[i] != null) { 415 output.append(" "); //$NON-NLS-1$ 416 printAnnotations(annotationsOnDimensions[i], output); 417 output.append(" "); //$NON-NLS-1$ 418 } 419 output.append("[]"); //$NON-NLS-1$ 420 } 421 } 422 return output; 423 } 424 resolveType(BlockScope scope, boolean checkBounds, int location)425 public TypeBinding resolveType(BlockScope scope, boolean checkBounds, int location) { 426 return internalResolveType(scope, checkBounds, location); 427 } resolveType(ClassScope scope, int location)428 public TypeBinding resolveType(ClassScope scope, int location) { 429 return internalResolveType(scope, false, location); 430 } traverse(ASTVisitor visitor, BlockScope scope)431 public void traverse(ASTVisitor visitor, BlockScope scope) { 432 if (visitor.visit(this, scope)) { 433 if (this.annotations != null) { 434 int annotationsLevels = this.annotations.length; 435 for (int i = 0; i < annotationsLevels; i++) { 436 int annotationsLength = this.annotations[i] == null ? 0 : this.annotations[i].length; 437 for (int j = 0; j < annotationsLength; j++) 438 this.annotations[i][j].traverse(visitor, scope); 439 } 440 } 441 Annotation [][] annotationsOnDimensions = getAnnotationsOnDimensions(true); 442 if (annotationsOnDimensions != null) { 443 for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) { 444 Annotation[] annotations2 = annotationsOnDimensions[i]; 445 for (int j = 0, max2 = annotations2 == null ? 0 : annotations2.length; j < max2; j++) { 446 Annotation annotation = annotations2[j]; 447 annotation.traverse(visitor, scope); 448 } 449 } 450 } 451 for (int i = 0, max = this.typeArguments.length; i < max; i++) { 452 if (this.typeArguments[i] != null) { 453 for (int j = 0, max2 = this.typeArguments[i].length; j < max2; j++) { 454 this.typeArguments[i][j].traverse(visitor, scope); 455 } 456 } 457 } 458 } 459 visitor.endVisit(this, scope); 460 } 461 traverse(ASTVisitor visitor, ClassScope scope)462 public void traverse(ASTVisitor visitor, ClassScope scope) { 463 if (visitor.visit(this, scope)) { 464 if (this.annotations != null) { 465 int annotationsLevels = this.annotations.length; 466 for (int i = 0; i < annotationsLevels; i++) { 467 int annotationsLength = this.annotations[i] == null ? 0 : this.annotations[i].length; 468 for (int j = 0; j < annotationsLength; j++) 469 this.annotations[i][j].traverse(visitor, scope); 470 } 471 } 472 Annotation [][] annotationsOnDimensions = getAnnotationsOnDimensions(true); 473 if (annotationsOnDimensions != null) { 474 for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) { 475 Annotation[] annotations2 = annotationsOnDimensions[i]; 476 for (int j = 0, max2 = annotations2 == null ? 0 : annotations2.length; j < max2; j++) { 477 Annotation annotation = annotations2[j]; 478 annotation.traverse(visitor, scope); 479 } 480 } 481 } 482 for (int i = 0, max = this.typeArguments.length; i < max; i++) { 483 if (this.typeArguments[i] != null) { 484 for (int j = 0, max2 = this.typeArguments[i].length; j < max2; j++) { 485 this.typeArguments[i][j].traverse(visitor, scope); 486 } 487 } 488 } 489 } 490 visitor.endVisit(this, scope); 491 } 492 493 } 494