1 11 package org.eclipse.jdt.internal.compiler.ast; 12 13 import org.eclipse.jdt.internal.compiler.ASTVisitor; 14 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 15 import org.eclipse.jdt.internal.compiler.codegen.CodeStream; 16 import org.eclipse.jdt.internal.compiler.flow.FlowContext; 17 import org.eclipse.jdt.internal.compiler.flow.FlowInfo; 18 import org.eclipse.jdt.internal.compiler.impl.Constant; 19 import org.eclipse.jdt.internal.compiler.lookup.Binding; 20 import org.eclipse.jdt.internal.compiler.lookup.BlockScope; 21 import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; 22 import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; 23 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; 24 import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding; 25 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; 26 import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding; 27 import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding; 28 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; 29 import org.eclipse.jdt.internal.compiler.lookup.TagBits; 30 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; 31 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; 32 import org.eclipse.jdt.internal.compiler.lookup.TypeIds; 33 34 40 public class QualifiedAllocationExpression extends AllocationExpression { 41 42 public Expression enclosingInstance; 44 public TypeDeclaration anonymousType; 45 public ReferenceBinding superTypeBinding; 46 47 public QualifiedAllocationExpression() { 48 } 50 51 public QualifiedAllocationExpression(TypeDeclaration anonymousType) { 52 this.anonymousType = anonymousType; 53 anonymousType.allocation = this; 54 } 55 56 public FlowInfo analyseCode( 57 BlockScope currentScope, 58 FlowContext flowContext, 59 FlowInfo flowInfo) { 60 61 if (this.enclosingInstance != null) { 63 flowInfo = this.enclosingInstance.analyseCode(currentScope, flowContext, flowInfo); 64 } 65 66 ReferenceBinding allocatedType = this.superTypeBinding == null ? this.binding.declaringClass : this.superTypeBinding; 68 checkCapturedLocalInitializationIfNecessary( 69 (ReferenceBinding) allocatedType.erasure(), 70 currentScope, 71 flowInfo); 72 73 if (this.arguments != null) { 75 for (int i = 0, count = this.arguments.length; i < count; i++) { 76 flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo); 77 } 78 } 79 80 if (this.anonymousType != null) { 82 flowInfo = this.anonymousType.analyseCode(currentScope, flowContext, flowInfo); 83 } 84 85 ReferenceBinding[] thrownExceptions; 87 if (((thrownExceptions = this.binding.thrownExceptions).length) != 0) { 88 flowContext.checkExceptionHandlers( 90 thrownExceptions, 91 this, 92 flowInfo.unconditionalCopy(), 93 currentScope); 94 } 95 manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); 96 manageSyntheticAccessIfNecessary(currentScope, flowInfo); 97 return flowInfo; 98 } 99 100 public Expression enclosingInstance() { 101 102 return this.enclosingInstance; 103 } 104 105 public void generateCode( 106 BlockScope currentScope, 107 CodeStream codeStream, 108 boolean valueRequired) { 109 110 int pc = codeStream.position; 111 ReferenceBinding allocatedType = this.codegenBinding.declaringClass; 112 codeStream.new_(allocatedType); 113 boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0; 114 if (valueRequired || isUnboxing) { 115 codeStream.dup(); 116 } 117 if (this.type != null) { codeStream.recordPositionsFrom(pc, this.type.sourceStart); 120 } else { 121 codeStream.ldc(String.valueOf(this.enumConstant.name)); 123 codeStream.generateInlinedValue(this.enumConstant.binding.id); 124 } 125 if (allocatedType.isNestedType()) { 127 codeStream.generateSyntheticEnclosingInstanceValues( 128 currentScope, 129 allocatedType, 130 enclosingInstance(), 131 this); 132 } 133 generateArguments(this.binding, this.arguments, currentScope, codeStream); 135 if (allocatedType.isNestedType()) { 137 codeStream.generateSyntheticOuterArgumentValues( 138 currentScope, 139 allocatedType, 140 this); 141 } 142 143 if (this.syntheticAccessor == null) { 145 codeStream.invokespecial(this.codegenBinding); 146 } else { 147 for (int i = 0, 149 max = this.syntheticAccessor.parameters.length - this.codegenBinding.parameters.length; 150 i < max; 151 i++) { 152 codeStream.aconst_null(); 153 } 154 codeStream.invokespecial(this.syntheticAccessor); 155 } 156 if (valueRequired) { 157 codeStream.generateImplicitConversion(implicitConversion); 158 } else if (isUnboxing) { 159 codeStream.generateImplicitConversion(implicitConversion); 161 switch (postConversionType(currentScope).id) { 162 case T_long : 163 case T_double : 164 codeStream.pop2(); 165 break; 166 default : 167 codeStream.pop(); 168 } 169 } 170 codeStream.recordPositionsFrom(pc, this.sourceStart); 171 172 if (this.anonymousType != null) { 173 this.anonymousType.generateCode(currentScope, codeStream); 174 } 175 } 176 177 public boolean isSuperAccess() { 178 179 return this.anonymousType != null; 181 } 182 183 190 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { 191 192 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { 193 ReferenceBinding allocatedTypeErasure = (ReferenceBinding) this.binding.declaringClass.erasure(); 194 195 if (allocatedTypeErasure.isNestedType() 197 && currentScope.enclosingSourceType().isLocalType()) { 198 199 if (allocatedTypeErasure.isLocalType()) { 200 ((LocalTypeBinding) allocatedTypeErasure).addInnerEmulationDependent(currentScope, this.enclosingInstance != null); 201 } else { 202 currentScope.propagateInnerEmulation(allocatedTypeErasure, this.enclosingInstance != null); 204 } 205 } 206 } 207 } 208 209 public StringBuffer printExpression(int indent, StringBuffer output) { 210 211 if (this.enclosingInstance != null) 212 this.enclosingInstance.printExpression(0, output).append('.'); 213 super.printExpression(0, output); 214 if (this.anonymousType != null) { 215 this.anonymousType.print(indent, output); 216 } 217 return output; 218 } 219 220 public TypeBinding resolveType(BlockScope scope) { 221 222 if (this.anonymousType == null && this.enclosingInstance == null) { 224 return super.resolveType(scope); 225 } 226 227 231 this.constant = Constant.NotAConstant; 232 TypeBinding enclosingInstanceType = null; 233 TypeBinding receiverType = null; 234 boolean hasError = false; 235 boolean enclosingInstanceContainsCast = false; 236 boolean argsContainCast = false; 237 238 if (this.enclosingInstance != null) { 239 if (this.enclosingInstance instanceof CastExpression) { 240 this.enclosingInstance.bits |= ASTNode.DisableUnnecessaryCastCheck; enclosingInstanceContainsCast = true; 242 } 243 if ((enclosingInstanceType = this.enclosingInstance.resolveType(scope)) == null){ 244 hasError = true; 245 } else if (enclosingInstanceType.isBaseType() || enclosingInstanceType.isArrayType()) { 246 scope.problemReporter().illegalPrimitiveOrArrayTypeForEnclosingInstance( 247 enclosingInstanceType, 248 this.enclosingInstance); 249 hasError = true; 250 } else if (this.type instanceof QualifiedTypeReference) { 251 scope.problemReporter().illegalUsageOfQualifiedTypeReference((QualifiedTypeReference)this.type); 252 hasError = true; 253 } else { 254 receiverType = ((SingleTypeReference) this.type).resolveTypeEnclosing(scope, (ReferenceBinding) enclosingInstanceType); 255 if (receiverType != null && enclosingInstanceContainsCast) { 256 CastExpression.checkNeedForEnclosingInstanceCast(scope, this.enclosingInstance, enclosingInstanceType, receiverType); 257 } 258 } 259 } else { 260 if (this.type == null) { 261 receiverType = scope.enclosingSourceType(); 263 } else { 264 receiverType = this.type.resolveType(scope, true ); 265 checkParameterizedAllocation: { 266 if (receiverType == null) break checkParameterizedAllocation; 267 if (this.type instanceof ParameterizedQualifiedTypeReference) { ReferenceBinding currentType = (ReferenceBinding)receiverType; 269 do { 270 if ((currentType.modifiers & ClassFileConstants.AccStatic) != 0) break checkParameterizedAllocation; 272 if (currentType.isRawType()) break checkParameterizedAllocation; 273 } while ((currentType = currentType.enclosingType())!= null); 274 ParameterizedQualifiedTypeReference qRef = (ParameterizedQualifiedTypeReference) this.type; 275 for (int i = qRef.typeArguments.length - 2; i >= 0; i--) { 276 if (qRef.typeArguments[i] != null) { 277 scope.problemReporter().illegalQualifiedParameterizedTypeAllocation(this.type, receiverType); 278 break; 279 } 280 } 281 } 282 } 283 } 284 } 285 if (receiverType == null) { 286 hasError = true; 287 } else if (((ReferenceBinding) receiverType).isFinal()) { 288 if (this.anonymousType != null) { 289 if (!receiverType.isEnum()) { 290 scope.problemReporter().anonymousClassCannotExtendFinalClass(this.type, receiverType); 291 hasError = true; 292 } 293 } else if (!receiverType.canBeInstantiated()) { 294 scope.problemReporter().cannotInstantiate(this.type, receiverType); 295 return this.resolvedType = receiverType; 296 } 297 } 298 if (this.typeArguments != null) { 300 int length = this.typeArguments.length; 301 this.genericTypeArguments = new TypeBinding[length]; 302 for (int i = 0; i < length; i++) { 303 TypeReference typeReference = this.typeArguments[i]; 304 TypeBinding argType = typeReference.resolveType(scope, true ); 305 if (argType == null) { 306 if (typeReference instanceof Wildcard) { 307 scope.problemReporter().illegalUsageOfWildcard(typeReference); 308 } 309 return null; } 311 this.genericTypeArguments[i] = argType; 312 } 313 } 314 315 TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; 317 if (this.arguments != null) { 318 int length = this.arguments.length; 319 argumentTypes = new TypeBinding[length]; 320 for (int i = 0; i < length; i++) { 321 Expression argument = this.arguments[i]; 322 if (argument instanceof CastExpression) { 323 argument.bits |= ASTNode.DisableUnnecessaryCastCheck; argsContainCast = true; 325 } 326 if ((argumentTypes[i] = argument.resolveType(scope)) == null){ 327 hasError = true; 328 } 329 } 330 } 331 if (hasError) { 333 if (receiverType instanceof ReferenceBinding) { 334 int length = this.arguments == null ? 0 : this.arguments.length; 336 TypeBinding[] pseudoArgs = new TypeBinding[length]; 337 for (int i = length; --i >= 0;) { 338 pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; } 340 this.binding = scope.findMethod((ReferenceBinding) receiverType, TypeConstants.INIT, pseudoArgs, this); 341 if (this.binding != null && !this.binding.isValidBinding()) { 342 MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch; 343 if (closestMatch != null) { 345 if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { closestMatch = scope.environment().createParameterizedGenericMethod(closestMatch.original(), (RawTypeBinding)null); 348 } 349 this.binding = closestMatch; 350 MethodBinding closestMatchOriginal = closestMatch.original(); 351 if ((closestMatchOriginal.isPrivate() || closestMatchOriginal.declaringClass.isLocalType()) && !scope.isDefinedInMethod(closestMatchOriginal)) { 352 closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; 354 } 355 } 356 } 357 358 } 359 return this.resolvedType = receiverType; 360 } 361 if (this.anonymousType == null) { 362 if (!receiverType.canBeInstantiated()) { 364 scope.problemReporter().cannotInstantiate(this.type, receiverType); 365 return this.resolvedType = receiverType; 366 } 367 ReferenceBinding allocationType = (ReferenceBinding) receiverType; 368 if ((this.binding = scope.getConstructor(allocationType, argumentTypes, this)).isValidBinding()) { 369 if (isMethodUseDeprecated(this.binding, scope, true)) { 370 scope.problemReporter().deprecatedMethod(this.binding, this); 371 } 372 checkInvocationArguments(scope, null, allocationType, this.binding, this.arguments, argumentTypes, argsContainCast, this); 373 } else { 374 if (this.binding.declaringClass == null) { 375 this.binding.declaringClass = allocationType; 376 } 377 scope.problemReporter().invalidConstructor(this, this.binding); 378 return this.resolvedType = receiverType; 379 } 380 381 ReferenceBinding expectedType = this.binding.declaringClass.enclosingType(); 383 if (expectedType != enclosingInstanceType) scope.compilationUnitScope().recordTypeConversion(expectedType, enclosingInstanceType); 385 if (enclosingInstanceType.isCompatibleWith(expectedType) || scope.isBoxingCompatibleWith(enclosingInstanceType, expectedType)) { 386 this.enclosingInstance.computeConversion(scope, expectedType, enclosingInstanceType); 387 return this.resolvedType = receiverType; 388 } 389 scope.problemReporter().typeMismatchError(enclosingInstanceType, expectedType, this.enclosingInstance); 390 return this.resolvedType = receiverType; 391 } 392 393 if (receiverType.isTypeVariable()) { 394 receiverType = new ProblemReferenceBinding(receiverType.sourceName(), (ReferenceBinding)receiverType, ProblemReasons.IllegalSuperTypeVariable); 395 scope.problemReporter().invalidType(this, receiverType); 396 return null; 397 } else if (this.type != null && receiverType.isEnum()) { scope.problemReporter().cannotInstantiate(this.type, receiverType); 399 return this.resolvedType = receiverType; 400 } 401 this.superTypeBinding = receiverType.isInterface() ? scope.getJavaLangObject() : (ReferenceBinding) receiverType; 404 scope.addAnonymousType(this.anonymousType, (ReferenceBinding) receiverType); 406 this.anonymousType.resolve(scope); 407 if (this.superTypeBinding.erasure().id == TypeIds.T_JavaLangEnum) { 408 scope.problemReporter().cannotExtendEnum(this.anonymousType.binding, this.type, this.superTypeBinding); 409 } 410 411 if ((receiverType.tagBits & TagBits.HasDirectWildcard) != 0) { 412 scope.problemReporter().superTypeCannotUseWildcard(this.anonymousType.binding, this.type, receiverType); 413 } 414 MethodBinding inheritedBinding = scope.getConstructor(this.superTypeBinding, argumentTypes, this); 416 if (!inheritedBinding.isValidBinding()) { 417 if (inheritedBinding.declaringClass == null) { 418 inheritedBinding.declaringClass = this.superTypeBinding; 419 } 420 scope.problemReporter().invalidConstructor(this, inheritedBinding); 421 return this.resolvedType = this.anonymousType.binding; 422 } 423 if (this.enclosingInstance != null) { 424 ReferenceBinding targetEnclosing = inheritedBinding.declaringClass.enclosingType(); 425 if (targetEnclosing == null) { 426 scope.problemReporter().unnecessaryEnclosingInstanceSpecification(this.enclosingInstance, (ReferenceBinding)receiverType); 427 return this.resolvedType = this.anonymousType.binding; 428 } else if (!enclosingInstanceType.isCompatibleWith(targetEnclosing) && !scope.isBoxingCompatibleWith(enclosingInstanceType, targetEnclosing)) { 429 scope.problemReporter().typeMismatchError(enclosingInstanceType, targetEnclosing, this.enclosingInstance); 430 return this.resolvedType = this.anonymousType.binding; 431 } 432 this.enclosingInstance.computeConversion(scope, targetEnclosing, enclosingInstanceType); 433 } 434 if (this.arguments != null) 435 checkInvocationArguments(scope, null, this.superTypeBinding, inheritedBinding, this.arguments, argumentTypes, argsContainCast, this); 436 437 this.binding = this.anonymousType.createDefaultConstructorWithBinding(inheritedBinding); 439 return this.resolvedType = this.anonymousType.binding; } 441 442 public void traverse(ASTVisitor visitor, BlockScope scope) { 443 444 if (visitor.visit(this, scope)) { 445 if (this.enclosingInstance != null) 446 this.enclosingInstance.traverse(visitor, scope); 447 if (this.typeArguments != null) { 448 for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) { 449 this.typeArguments[i].traverse(visitor, scope); 450 } 451 } 452 if (this.type != null) this.type.traverse(visitor, scope); 454 if (this.arguments != null) { 455 int argumentsLength = this.arguments.length; 456 for (int i = 0; i < argumentsLength; i++) 457 this.arguments[i].traverse(visitor, scope); 458 } 459 if (this.anonymousType != null) 460 this.anonymousType.traverse(visitor, scope); 461 } 462 visitor.endVisit(this, scope); 463 } 464 } 465 | Popular Tags |