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.*; 16 import org.eclipse.jdt.internal.compiler.flow.*; 17 import org.eclipse.jdt.internal.compiler.impl.Constant; 18 import org.eclipse.jdt.internal.compiler.lookup.*; 19 20 public class AllocationExpression extends Expression implements InvocationSite { 21 22 public TypeReference type; 23 public Expression[] arguments; 24 public MethodBinding binding; protected MethodBinding codegenBinding; MethodBinding syntheticAccessor; public TypeReference[] typeArguments; 28 public TypeBinding[] genericTypeArguments; 29 public FieldDeclaration enumConstant; 31 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { 32 checkCapturedLocalInitializationIfNecessary((ReferenceBinding)this.binding.declaringClass.erasure(), currentScope, flowInfo); 34 35 if (arguments != null) { 37 for (int i = 0, count = arguments.length; i < count; i++) { 38 flowInfo = 39 arguments[i] 40 .analyseCode(currentScope, flowContext, flowInfo) 41 .unconditionalInits(); 42 } 43 } 44 ReferenceBinding[] thrownExceptions; 46 if (((thrownExceptions = this.binding.thrownExceptions).length) != 0) { 47 flowContext.checkExceptionHandlers( 49 thrownExceptions, 50 this, 51 flowInfo.unconditionalCopy(), 52 currentScope); 53 } 54 manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); 55 manageSyntheticAccessIfNecessary(currentScope, flowInfo); 56 57 return flowInfo; 58 } 59 60 public void checkCapturedLocalInitializationIfNecessary(ReferenceBinding checkedType, BlockScope currentScope, FlowInfo flowInfo) { 61 if (checkedType.isLocalType() 62 && !checkedType.isAnonymousType() 63 && !currentScope.isDefinedInType(checkedType)) { NestedTypeBinding nestedType = (NestedTypeBinding) checkedType; 65 SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables(); 66 if (syntheticArguments != null) 67 for (int i = 0, count = syntheticArguments.length; i < count; i++){ 68 SyntheticArgumentBinding syntheticArgument = syntheticArguments[i]; 69 LocalVariableBinding targetLocal; 70 if ((targetLocal = syntheticArgument.actualOuterLocalVariable) == null) continue; 71 if (targetLocal.declaration != null && !flowInfo.isDefinitelyAssigned(targetLocal)){ 72 currentScope.problemReporter().uninitializedLocalVariable(targetLocal, this); 73 } 74 } 75 } 76 } 77 78 public Expression enclosingInstance() { 79 return null; 80 } 81 82 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) { 83 int pc = codeStream.position; 84 ReferenceBinding allocatedType = this.codegenBinding.declaringClass; 85 86 codeStream.new_(allocatedType); 87 boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0; 88 if (valueRequired || isUnboxing) { 89 codeStream.dup(); 90 } 91 if (this.type != null) { codeStream.recordPositionsFrom(pc, this.type.sourceStart); 94 } else { 95 codeStream.ldc(String.valueOf(enumConstant.name)); 97 codeStream.generateInlinedValue(enumConstant.binding.id); 98 } 99 100 if (allocatedType.isNestedType()) { 102 codeStream.generateSyntheticEnclosingInstanceValues( 103 currentScope, 104 allocatedType, 105 enclosingInstance(), 106 this); 107 } 108 generateArguments(binding, arguments, currentScope, codeStream); 110 if (allocatedType.isNestedType()) { 112 codeStream.generateSyntheticOuterArgumentValues( 113 currentScope, 114 allocatedType, 115 this); 116 } 117 if (syntheticAccessor == null) { 119 codeStream.invokespecial(this.codegenBinding); 120 } else { 121 for (int i = 0, 123 max = syntheticAccessor.parameters.length - this.codegenBinding.parameters.length; 124 i < max; 125 i++) { 126 codeStream.aconst_null(); 127 } 128 codeStream.invokespecial(syntheticAccessor); 129 } 130 if (valueRequired) { 131 codeStream.generateImplicitConversion(this.implicitConversion); 132 } else if (isUnboxing) { 133 codeStream.generateImplicitConversion(this.implicitConversion); 135 switch (postConversionType(currentScope).id) { 136 case T_long : 137 case T_double : 138 codeStream.pop2(); 139 break; 140 default : 141 codeStream.pop(); 142 } 143 } 144 codeStream.recordPositionsFrom(pc, this.sourceStart); 145 } 146 147 150 public TypeBinding[] genericTypeArguments() { 151 return this.genericTypeArguments; 152 } 153 154 public boolean isSuperAccess() { 155 return false; 156 } 157 158 public boolean isTypeAccess() { 159 return true; 160 } 161 162 169 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { 170 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return; 171 ReferenceBinding allocatedTypeErasure = (ReferenceBinding) binding.declaringClass.erasure(); 172 173 if (allocatedTypeErasure.isNestedType() 175 && currentScope.enclosingSourceType().isLocalType()) { 176 177 if (allocatedTypeErasure.isLocalType()) { 178 ((LocalTypeBinding) allocatedTypeErasure).addInnerEmulationDependent(currentScope, false); 179 } else { 181 currentScope.propagateInnerEmulation(allocatedTypeErasure, false); 183 } 185 } 186 } 187 188 public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { 189 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return; 190 this.codegenBinding = this.binding.original(); 192 193 ReferenceBinding declaringClass; 194 if (this.codegenBinding.isPrivate() && currentScope.enclosingSourceType() != (declaringClass = this.codegenBinding.declaringClass)) { 195 196 if ((declaringClass.tagBits & TagBits.IsLocalType) != 0 && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) { 198 this.codegenBinding.tagBits |= TagBits.ClearPrivateModifier; 200 } else { 201 syntheticAccessor = ((SourceTypeBinding) declaringClass).addSyntheticMethod(this.codegenBinding, isSuperAccess()); 202 currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this); 203 } 204 } 205 } 206 207 public StringBuffer printExpression(int indent, StringBuffer output) { 208 if (this.type != null) { output.append("new "); } 211 if (typeArguments != null) { 212 output.append('<'); 213 int max = typeArguments.length - 1; 214 for (int j = 0; j < max; j++) { 215 typeArguments[j].print(0, output); 216 output.append(", "); } 218 typeArguments[max].print(0, output); 219 output.append('>'); 220 } 221 if (type != null) { type.printExpression(0, output); 223 } 224 output.append('('); 225 if (arguments != null) { 226 for (int i = 0; i < arguments.length; i++) { 227 if (i > 0) output.append(", "); arguments[i].printExpression(0, output); 229 } 230 } 231 return output.append(')'); 232 } 233 234 public TypeBinding resolveType(BlockScope scope) { 235 constant = Constant.NotAConstant; 237 if (this.type == null) { 238 this.resolvedType = scope.enclosingReceiverType(); 240 } else { 241 this.resolvedType = this.type.resolveType(scope, true ); 242 checkParameterizedAllocation: { 243 if (this.type instanceof ParameterizedQualifiedTypeReference) { ReferenceBinding currentType = (ReferenceBinding)this.resolvedType; 245 if (currentType == null) return null; 246 do { 247 if ((currentType.modifiers & ClassFileConstants.AccStatic) != 0) break checkParameterizedAllocation; 249 if (currentType.isRawType()) break checkParameterizedAllocation; 250 } while ((currentType = currentType.enclosingType())!= null); 251 ParameterizedQualifiedTypeReference qRef = (ParameterizedQualifiedTypeReference) this.type; 252 for (int i = qRef.typeArguments.length - 2; i >= 0; i--) { 253 if (qRef.typeArguments[i] != null) { 254 scope.problemReporter().illegalQualifiedParameterizedTypeAllocation(this.type, this.resolvedType); 255 break; 256 } 257 } 258 } 259 } 260 } 261 263 if (this.typeArguments != null) { 265 int length = this.typeArguments.length; 266 boolean argHasError = false; this.genericTypeArguments = new TypeBinding[length]; 268 for (int i = 0; i < length; i++) { 269 TypeReference typeReference = this.typeArguments[i]; 270 if ((this.genericTypeArguments[i] = typeReference.resolveType(scope, true )) == null) { 271 argHasError = true; 272 } 273 if (argHasError && typeReference instanceof Wildcard) { 274 scope.problemReporter().illegalUsageOfWildcard(typeReference); 275 } 276 } 277 if (argHasError) { 278 return null; 279 } 280 } 281 282 boolean argsContainCast = false; 284 TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; 285 if (arguments != null) { 286 boolean argHasError = false; 287 int length = arguments.length; 288 argumentTypes = new TypeBinding[length]; 289 for (int i = 0; i < length; i++) { 290 Expression argument = this.arguments[i]; 291 if (argument instanceof CastExpression) { 292 argument.bits |= DisableUnnecessaryCastCheck; argsContainCast = true; 294 } 295 if ((argumentTypes[i] = argument.resolveType(scope)) == null) { 296 argHasError = true; 297 } 298 } 299 if (argHasError) { 300 if (this.resolvedType instanceof ReferenceBinding) { 301 TypeBinding[] pseudoArgs = new TypeBinding[length]; 303 for (int i = length; --i >= 0;) { 304 pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; } 306 this.binding = scope.findMethod((ReferenceBinding) this.resolvedType, TypeConstants.INIT, pseudoArgs, this); 307 if (this.binding != null && !this.binding.isValidBinding()) { 308 MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch; 309 if (closestMatch != null) { 311 if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { closestMatch = scope.environment().createParameterizedGenericMethod(closestMatch.original(), (RawTypeBinding)null); 314 } 315 this.binding = closestMatch; 316 MethodBinding closestMatchOriginal = closestMatch.original(); 317 if ((closestMatchOriginal.isPrivate() || closestMatchOriginal.declaringClass.isLocalType()) && !scope.isDefinedInMethod(closestMatchOriginal)) { 318 closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; 320 } 321 } 322 } 323 } 324 return this.resolvedType; 325 } 326 } 327 if (this.resolvedType == null) 328 return null; 329 330 if (this.type != null && !this.resolvedType.canBeInstantiated()) { 332 scope.problemReporter().cannotInstantiate(type, this.resolvedType); 333 return this.resolvedType; 334 } 335 ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType; 336 if (!(binding = scope.getConstructor(allocationType, argumentTypes, this)).isValidBinding()) { 337 if (binding.declaringClass == null) 338 binding.declaringClass = allocationType; 339 scope.problemReporter().invalidConstructor(this, binding); 340 return this.resolvedType; 341 } 342 if (isMethodUseDeprecated(binding, scope, true)) 343 scope.problemReporter().deprecatedMethod(binding, this); 344 checkInvocationArguments(scope, null, allocationType, this.binding, this.arguments, argumentTypes, argsContainCast, this); 345 346 return allocationType; 347 } 348 349 public void setActualReceiverType(ReferenceBinding receiverType) { 350 } 352 353 public void setDepth(int i) { 354 } 356 357 public void setFieldIndex(int i) { 358 } 360 361 public void traverse(ASTVisitor visitor, BlockScope scope) { 362 if (visitor.visit(this, scope)) { 363 if (this.typeArguments != null) { 364 for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) { 365 this.typeArguments[i].traverse(visitor, scope); 366 } 367 } 368 if (this.type != null) { this.type.traverse(visitor, scope); 370 } 371 if (this.arguments != null) { 372 for (int i = 0, argumentsLength = this.arguments.length; i < argumentsLength; i++) 373 this.arguments[i].traverse(visitor, scope); 374 } 375 } 376 visitor.endVisit(this, scope); 377 } 378 } 379 | Popular Tags |