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.lookup.*; 18 19 public class ExplicitConstructorCall extends Statement implements InvocationSite { 20 21 public Expression[] arguments; 22 public Expression qualification; 23 public MethodBinding binding; protected MethodBinding codegenBinding; MethodBinding syntheticAccessor; public int accessMode; 27 public TypeReference[] typeArguments; 28 public TypeBinding[] genericTypeArguments; 29 30 public final static int ImplicitSuper = 1; 31 public final static int Super = 2; 32 public final static int This = 3; 33 34 public VariableBinding[][] implicitArguments; 35 36 public int typeArgumentsSourceStart; 38 39 public ExplicitConstructorCall(int accessMode) { 40 this.accessMode = accessMode; 41 } 42 43 public FlowInfo analyseCode( 44 BlockScope currentScope, 45 FlowContext flowContext, 46 FlowInfo flowInfo) { 47 48 50 try { 51 ((MethodScope) currentScope).isConstructorCall = true; 52 53 if (qualification != null) { 55 flowInfo = 56 qualification 57 .analyseCode(currentScope, flowContext, flowInfo) 58 .unconditionalInits(); 59 } 60 if (arguments != null) { 62 for (int i = 0, max = arguments.length; i < max; i++) { 63 flowInfo = 64 arguments[i] 65 .analyseCode(currentScope, flowContext, flowInfo) 66 .unconditionalInits(); 67 } 68 } 69 70 ReferenceBinding[] thrownExceptions; 71 if ((thrownExceptions = binding.thrownExceptions) != Binding.NO_EXCEPTIONS) { 72 flowContext.checkExceptionHandlers( 74 thrownExceptions, 75 (accessMode == ImplicitSuper) 76 ? (ASTNode) currentScope.methodScope().referenceContext 77 : (ASTNode) this, 78 flowInfo, 79 currentScope); 80 } 81 manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); 82 manageSyntheticAccessIfNecessary(currentScope, flowInfo); 83 return flowInfo; 84 } finally { 85 ((MethodScope) currentScope).isConstructorCall = false; 86 } 87 } 88 89 95 public void generateCode(BlockScope currentScope, CodeStream codeStream) { 96 97 if ((bits & IsReachable) == 0) { 98 return; 99 } 100 try { 101 ((MethodScope) currentScope).isConstructorCall = true; 102 103 int pc = codeStream.position; 104 codeStream.aload_0(); 105 106 ReferenceBinding targetType = this.codegenBinding.declaringClass; 107 108 if (targetType.erasure().id == T_JavaLangEnum || targetType.isEnum()) { 110 codeStream.aload_1(); codeStream.iload_2(); } 113 if (targetType.isNestedType()) { 116 codeStream.generateSyntheticEnclosingInstanceValues( 117 currentScope, 118 targetType, 119 (this.bits & ASTNode.DiscardEnclosingInstance) != 0 ? null : qualification, 120 this); 121 } 122 generateArguments(binding, arguments, currentScope, codeStream); 124 125 if (targetType.isNestedType()) { 127 codeStream.generateSyntheticOuterArgumentValues( 128 currentScope, 129 targetType, 130 this); 131 } 132 if (syntheticAccessor != null) { 133 for (int i = 0, 135 max = syntheticAccessor.parameters.length - this.codegenBinding.parameters.length; 136 i < max; 137 i++) { 138 codeStream.aconst_null(); 139 } 140 codeStream.invokespecial(syntheticAccessor); 141 } else { 142 codeStream.invokespecial(this.codegenBinding); 143 } 144 codeStream.recordPositionsFrom(pc, this.sourceStart); 145 } finally { 146 ((MethodScope) currentScope).isConstructorCall = false; 147 } 148 } 149 152 public TypeBinding[] genericTypeArguments() { 153 return this.genericTypeArguments; 154 } 155 public boolean isImplicitSuper() { 156 158 return (accessMode == ImplicitSuper); 159 } 160 161 public boolean isSuperAccess() { 162 163 return accessMode != This; 164 } 165 166 public boolean isTypeAccess() { 167 168 return true; 169 } 170 171 178 void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { 179 ReferenceBinding superTypeErasure = (ReferenceBinding) binding.declaringClass.erasure(); 180 181 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { 182 if (superTypeErasure.isNestedType() 184 && currentScope.enclosingSourceType().isLocalType()) { 185 186 if (superTypeErasure.isLocalType()) { 187 ((LocalTypeBinding) superTypeErasure).addInnerEmulationDependent(currentScope, qualification != null); 188 } else { 189 currentScope.propagateInnerEmulation(superTypeErasure, qualification != null); 191 } 192 } 193 } 194 } 195 196 public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { 197 198 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { 199 this.codegenBinding = this.binding.original(); 201 202 if (binding.isPrivate() && accessMode != This) { 204 ReferenceBinding declaringClass = this.codegenBinding.declaringClass; 205 if ((declaringClass.tagBits & TagBits.IsLocalType) != 0 && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) { 207 this.codegenBinding.tagBits |= TagBits.ClearPrivateModifier; 209 } else { 210 syntheticAccessor = ((SourceTypeBinding) declaringClass).addSyntheticMethod(this.codegenBinding, isSuperAccess()); 211 currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this); 212 } 213 } 214 } 215 } 216 217 public StringBuffer printStatement(int indent, StringBuffer output) { 218 219 printIndent(indent, output); 220 if (qualification != null) qualification.printExpression(0, output).append('.'); 221 if (typeArguments != null) { 222 output.append('<'); 223 int max = typeArguments.length - 1; 224 for (int j = 0; j < max; j++) { 225 typeArguments[j].print(0, output); 226 output.append(", "); } 228 typeArguments[max].print(0, output); 229 output.append('>'); 230 } 231 if (accessMode == This) { 232 output.append("this("); } else { 234 output.append("super("); } 236 if (arguments != null) { 237 for (int i = 0; i < arguments.length; i++) { 238 if (i > 0) output.append(", "); arguments[i].printExpression(0, output); 240 } 241 } 242 return output.append(");"); } 244 245 public void resolve(BlockScope scope) { 246 249 MethodScope methodScope = scope.methodScope(); 252 try { 253 AbstractMethodDeclaration methodDeclaration = methodScope.referenceMethod(); 254 if (methodDeclaration == null 255 || !methodDeclaration.isConstructor() 256 || ((ConstructorDeclaration) methodDeclaration).constructorCall != this) { 257 scope.problemReporter().invalidExplicitConstructorCall(this); 258 if (this.qualification != null) { 260 this.qualification.resolveType(scope); 261 } 262 if (this.typeArguments != null) { 263 for (int i = 0, max = this.typeArguments.length; i < max; i++) { 264 this.typeArguments[i].resolveType(scope, true ); 265 } 266 } 267 if (this.arguments != null) { 268 for (int i = 0, max = this.arguments.length; i < max; i++) { 269 this.arguments[i].resolveType(scope); 270 } 271 } 272 return; 273 } 274 methodScope.isConstructorCall = true; 275 ReferenceBinding receiverType = scope.enclosingReceiverType(); 276 if (accessMode != This) 277 receiverType = receiverType.superclass(); 278 279 if (receiverType == null) { 280 return; 281 } 282 if (this.accessMode == Super && receiverType.erasure().id == T_JavaLangEnum) { 284 scope.problemReporter().cannotInvokeSuperConstructorInEnum(this, methodScope.referenceMethod().binding); 285 } 286 if (qualification != null) { 288 if (accessMode != Super) { 289 scope.problemReporter().unnecessaryEnclosingInstanceSpecification( 290 qualification, 291 receiverType); 292 } 293 ReferenceBinding enclosingType = receiverType.enclosingType(); 294 if (enclosingType == null) { 295 scope.problemReporter().unnecessaryEnclosingInstanceSpecification( 296 qualification, 297 receiverType); 298 this.bits |= ASTNode.DiscardEnclosingInstance; 299 } else { 300 TypeBinding qTb = qualification.resolveTypeExpecting(scope, enclosingType); 301 qualification.computeConversion(scope, qTb, qTb); 302 } 303 } 304 if (this.typeArguments != null) { 306 int length = this.typeArguments.length; 307 boolean argHasError = false; this.genericTypeArguments = new TypeBinding[length]; 309 for (int i = 0; i < length; i++) { 310 TypeReference typeReference = this.typeArguments[i]; 311 if ((this.genericTypeArguments[i] = typeReference.resolveType(scope, true )) == null) { 312 argHasError = true; 313 } 314 if (argHasError && typeReference instanceof Wildcard) { 315 scope.problemReporter().illegalUsageOfWildcard(typeReference); 316 } 317 } 318 if (argHasError) { 319 return; 320 } 321 } 322 323 TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; 325 boolean argsContainCast = false; 326 if (arguments != null) { 327 boolean argHasError = false; int length = arguments.length; 329 argumentTypes = new TypeBinding[length]; 330 for (int i = 0; i < length; i++) { 331 Expression argument = this.arguments[i]; 332 if (argument instanceof CastExpression) { 333 argument.bits |= DisableUnnecessaryCastCheck; argsContainCast = true; 335 } 336 if ((argumentTypes[i] = argument.resolveType(scope)) == null) { 337 argHasError = true; 338 } 339 } 340 if (argHasError) { 341 TypeBinding[] pseudoArgs = new TypeBinding[length]; 343 for (int i = length; --i >= 0;) { 344 pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; } 346 this.binding = scope.findMethod(receiverType, TypeConstants.INIT, pseudoArgs, this); 347 if (this.binding != null && !this.binding.isValidBinding()) { 348 MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch; 349 if (closestMatch != null) { 351 if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { closestMatch = scope.environment().createParameterizedGenericMethod(closestMatch.original(), (RawTypeBinding)null); 354 } 355 this.binding = closestMatch; 356 MethodBinding closestMatchOriginal = closestMatch.original(); 357 if ((closestMatchOriginal.isPrivate() || closestMatchOriginal.declaringClass.isLocalType()) && !scope.isDefinedInMethod(closestMatchOriginal)) { 358 closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; 360 } 361 } 362 } 363 return; 364 } 365 } else if (receiverType.erasure().id == T_JavaLangEnum) { 366 argumentTypes = new TypeBinding[] { scope.getJavaLangString(), TypeBinding.INT }; 368 } 369 if ((binding = scope.getConstructor(receiverType, argumentTypes, this)).isValidBinding()) { 370 if (isMethodUseDeprecated(this.binding, scope, this.accessMode != ImplicitSuper)) 371 scope.problemReporter().deprecatedMethod(binding, this); 372 checkInvocationArguments(scope, null, receiverType, binding, this.arguments, argumentTypes, argsContainCast, this); 373 if (binding.isPrivate() || receiverType.isLocalType()) { 374 binding.original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed; 375 } 376 } else { 377 if (binding.declaringClass == null) 378 binding.declaringClass = receiverType; 379 scope.problemReporter().invalidConstructor(this, binding); 380 } 381 } finally { 382 methodScope.isConstructorCall = false; 383 } 384 } 385 386 public void setActualReceiverType(ReferenceBinding receiverType) { 387 } 389 390 public void setDepth(int depth) { 391 } 393 394 public void setFieldIndex(int depth) { 395 } 397 398 public void traverse(ASTVisitor visitor, BlockScope scope) { 399 400 if (visitor.visit(this, scope)) { 401 if (this.qualification != null) { 402 this.qualification.traverse(visitor, scope); 403 } 404 if (this.typeArguments != null) { 405 for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) { 406 this.typeArguments[i].traverse(visitor, scope); 407 } 408 } 409 if (this.arguments != null) { 410 for (int i = 0, argumentLength = this.arguments.length; i < argumentLength; i++) 411 this.arguments[i].traverse(visitor, scope); 412 } 413 } 414 visitor.endVisit(this, scope); 415 } 416 } 417 | Popular Tags |