001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: * Nick Teryaev - fix for bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=40752)
011: *******************************************************************************/package org.eclipse.jdt.internal.compiler.ast;
012:
013: import org.eclipse.jdt.core.compiler.CharOperation;
014: import org.eclipse.jdt.internal.compiler.ASTVisitor;
015: import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
016: import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
017: import org.eclipse.jdt.internal.compiler.flow.FlowContext;
018: import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
019: import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
020: import org.eclipse.jdt.internal.compiler.impl.Constant;
021: import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
022: import org.eclipse.jdt.internal.compiler.lookup.Binding;
023: import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
024: import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
025: import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
026: import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
027: import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
028: import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
029: import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
030: import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
031: import org.eclipse.jdt.internal.compiler.lookup.Scope;
032: import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
033: import org.eclipse.jdt.internal.compiler.lookup.TagBits;
034: import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
035: import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
036: import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
037: import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
038:
039: public class MessageSend extends Expression implements InvocationSite {
040:
041: public Expression receiver;
042: public char[] selector;
043: public Expression[] arguments;
044: public MethodBinding binding; // exact binding resulting from lookup
045: protected MethodBinding codegenBinding; // actual binding used for code generation (if no synthetic accessor)
046: MethodBinding syntheticAccessor; // synthetic accessor for inner-emulation
047: public TypeBinding expectedType; // for generic method invocation (return type inference)
048:
049: public long nameSourcePosition; //(start<<32)+end
050:
051: public TypeBinding actualReceiverType;
052: public TypeBinding receiverGenericCast; // extra reference type cast to perform on generic receiver
053: public TypeBinding valueCast; // extra reference type cast to perform on method returned value
054: public TypeReference[] typeArguments;
055: public TypeBinding[] genericTypeArguments;
056:
057: public FlowInfo analyseCode(BlockScope currentScope,
058: FlowContext flowContext, FlowInfo flowInfo) {
059:
060: boolean nonStatic = !this .binding.isStatic();
061: flowInfo = this .receiver.analyseCode(currentScope, flowContext,
062: flowInfo, nonStatic).unconditionalInits();
063: if (nonStatic) {
064: this .receiver.checkNPE(currentScope, flowContext, flowInfo);
065: }
066:
067: if (this .arguments != null) {
068: int length = this .arguments.length;
069: for (int i = 0; i < length; i++) {
070: flowInfo = this .arguments[i].analyseCode(currentScope,
071: flowContext, flowInfo).unconditionalInits();
072: }
073: }
074: ReferenceBinding[] thrownExceptions;
075: if ((thrownExceptions = this .binding.thrownExceptions) != Binding.NO_EXCEPTIONS) {
076: // must verify that exceptions potentially thrown by this expression are caught in the method
077: flowContext.checkExceptionHandlers(thrownExceptions, this ,
078: flowInfo.copy(), currentScope);
079: // TODO (maxime) the copy above is needed because of a side effect into
080: // checkExceptionHandlers; consider protecting there instead of here;
081: // NullReferenceTest#test0510
082: }
083: manageSyntheticAccessIfNecessary(currentScope, flowInfo);
084: return flowInfo;
085: }
086:
087: /**
088: * @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
089: */
090: public void computeConversion(Scope scope,
091: TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
092: if (runtimeTimeType == null || compileTimeType == null)
093: return;
094: // set the generic cast after the fact, once the type expectation is fully known (no need for strict cast)
095: if (this .binding != null && this .binding.isValidBinding()) {
096: MethodBinding originalBinding = this .binding.original();
097: TypeBinding originalType = originalBinding.returnType;
098: // extra cast needed if method return type is type variable
099: if (originalBinding != this .binding
100: && originalType != this .binding.returnType
101: && runtimeTimeType.id != TypeIds.T_JavaLangObject
102: && (originalType.tagBits & TagBits.HasTypeVariable) != 0) {
103: TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType
104: .isBaseType()) ? compileTimeType // unboxing: checkcast before conversion
105: : runtimeTimeType;
106: this .valueCast = originalType.genericCast(targetType);
107: } else if (this .actualReceiverType.isArrayType()
108: && runtimeTimeType.id != TypeIds.T_JavaLangObject
109: && this .binding.parameters == Binding.NO_PARAMETERS
110: && scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5
111: && CharOperation.equals(this .binding.selector,
112: TypeConstants.CLONE)) {
113: // from 1.5 compliant mode on, array#clone() resolves to array type, but codegen to #clone()Object - thus require extra inserted cast
114: this .valueCast = runtimeTimeType;
115: }
116: }
117: super
118: .computeConversion(scope, runtimeTimeType,
119: compileTimeType);
120: }
121:
122: /**
123: * MessageSend code generation
124: *
125: * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
126: * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
127: * @param valueRequired boolean
128: */
129: public void generateCode(BlockScope currentScope,
130: CodeStream codeStream, boolean valueRequired) {
131:
132: int pc = codeStream.position;
133:
134: // generate receiver/enclosing instance access
135: boolean isStatic = this .codegenBinding.isStatic();
136: if (isStatic) {
137: this .receiver.generateCode(currentScope, codeStream, false);
138: codeStream.recordPositionsFrom(pc, this .sourceStart);
139: } else if ((this .bits & ASTNode.DepthMASK) != 0
140: && this .receiver.isImplicitThis()) { // outer access ?
141: // outer method can be reached through emulation if implicit access
142: ReferenceBinding targetType = currentScope
143: .enclosingSourceType()
144: .enclosingTypeAt(
145: (this .bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
146: Object[] path = currentScope
147: .getEmulationPath(targetType,
148: true /*only exact match*/, false/*consider enclosing arg*/);
149: codeStream.generateOuterAccess(path, this , targetType,
150: currentScope);
151: } else {
152: this .receiver.generateCode(currentScope, codeStream, true);
153: if (this .receiverGenericCast != null)
154: codeStream.checkcast(this .receiverGenericCast);
155: codeStream.recordPositionsFrom(pc, this .sourceStart);
156:
157: }
158: // generate arguments
159: generateArguments(this .binding, this .arguments, currentScope,
160: codeStream);
161: // actual message invocation
162: if (this .syntheticAccessor == null) {
163: if (isStatic) {
164: codeStream.invokestatic(this .codegenBinding);
165: } else {
166: if ((this .receiver.isSuper())
167: || this .codegenBinding.isPrivate()) {
168: codeStream.invokespecial(this .codegenBinding);
169: } else {
170: if (this .codegenBinding.declaringClass
171: .isInterface()) { // interface or annotation type
172: codeStream.invokeinterface(this .codegenBinding);
173: } else {
174: codeStream.invokevirtual(this .codegenBinding);
175: }
176: }
177: }
178: } else {
179: codeStream.invokestatic(this .syntheticAccessor);
180: }
181: // required cast must occur even if no value is required
182: if (this .valueCast != null)
183: codeStream.checkcast(this .valueCast);
184: if (valueRequired) {
185: // implicit conversion if necessary
186: codeStream
187: .generateImplicitConversion(this .implicitConversion);
188: } else {
189: boolean isUnboxing = (this .implicitConversion & TypeIds.UNBOXING) != 0;
190: // conversion only generated if unboxing
191: if (isUnboxing)
192: codeStream
193: .generateImplicitConversion(this .implicitConversion);
194: switch (isUnboxing ? postConversionType(currentScope).id
195: : this .codegenBinding.returnType.id) {
196: case T_long:
197: case T_double:
198: codeStream.pop2();
199: break;
200: case T_void:
201: break;
202: default:
203: codeStream.pop();
204: }
205: }
206: codeStream.recordPositionsFrom(pc,
207: (int) (this .nameSourcePosition >>> 32)); // highlight selector
208: }
209:
210: /**
211: * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
212: */
213: public TypeBinding[] genericTypeArguments() {
214: return this .genericTypeArguments;
215: }
216:
217: public boolean isSuperAccess() {
218: return this .receiver.isSuper();
219: }
220:
221: public boolean isTypeAccess() {
222: return this .receiver != null && this .receiver.isTypeReference();
223: }
224:
225: public void manageSyntheticAccessIfNecessary(
226: BlockScope currentScope, FlowInfo flowInfo) {
227:
228: if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0)
229: return;
230:
231: // if method from parameterized type got found, use the original method at codegen time
232: this .codegenBinding = this .binding.original();
233: if (this .binding.isPrivate()) {
234:
235: // depth is set for both implicit and explicit access (see MethodBinding#canBeSeenBy)
236: if (currentScope.enclosingSourceType() != this .codegenBinding.declaringClass) {
237:
238: this .syntheticAccessor = ((SourceTypeBinding) this .codegenBinding.declaringClass)
239: .addSyntheticMethod(this .codegenBinding,
240: isSuperAccess());
241: currentScope.problemReporter()
242: .needToEmulateMethodAccess(this .codegenBinding,
243: this );
244: return;
245: }
246:
247: } else if (this .receiver instanceof QualifiedSuperReference) { // qualified super
248:
249: // qualified super need emulation always
250: SourceTypeBinding destinationType = (SourceTypeBinding) (((QualifiedSuperReference) this .receiver).currentCompatibleType);
251: this .syntheticAccessor = destinationType
252: .addSyntheticMethod(this .codegenBinding,
253: isSuperAccess());
254: currentScope.problemReporter().needToEmulateMethodAccess(
255: this .codegenBinding, this );
256: return;
257:
258: } else if (this .binding.isProtected()) {
259:
260: SourceTypeBinding enclosingSourceType;
261: if (((this .bits & ASTNode.DepthMASK) != 0)
262: && this .codegenBinding.declaringClass.getPackage() != (enclosingSourceType = currentScope
263: .enclosingSourceType()).getPackage()) {
264:
265: SourceTypeBinding currentCompatibleType = (SourceTypeBinding) enclosingSourceType
266: .enclosingTypeAt((this .bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
267: this .syntheticAccessor = currentCompatibleType
268: .addSyntheticMethod(this .codegenBinding,
269: isSuperAccess());
270: currentScope.problemReporter()
271: .needToEmulateMethodAccess(this .codegenBinding,
272: this );
273: return;
274: }
275: }
276:
277: // if the binding declaring class is not visible, need special action
278: // for runtime compatibility on 1.2 VMs : change the declaring class of the binding
279: // NOTE: from target 1.2 on, method's declaring class is touched if any different from receiver type
280: // and not from Object or implicit static method call.
281: if (this .binding.declaringClass != this .actualReceiverType
282: && this .receiverGenericCast == null
283: && !this .actualReceiverType.isArrayType()) {
284: CompilerOptions options = currentScope.compilerOptions();
285: if ((options.targetJDK >= ClassFileConstants.JDK1_2
286: && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(this .receiver
287: .isImplicitThis() && this .codegenBinding
288: .isStatic())) && this .binding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object methods
289: || !this .binding.declaringClass
290: .canBeSeenBy(currentScope)) {
291:
292: this .codegenBinding = currentScope
293: .enclosingSourceType()
294: .getUpdatedMethodBinding(
295: this .codegenBinding,
296: (ReferenceBinding) this .actualReceiverType
297: .erasure());
298: }
299: // Post 1.4.0 target, array clone() invocations are qualified with array type
300: // This is handled in array type #clone method binding resolution (see Scope and UpdatedMethodBinding)
301: }
302: }
303:
304: public int nullStatus(FlowInfo flowInfo) {
305: return FlowInfo.UNKNOWN;
306: }
307:
308: /**
309: * @see org.eclipse.jdt.internal.compiler.ast.Expression#postConversionType(Scope)
310: */
311: public TypeBinding postConversionType(Scope scope) {
312: TypeBinding convertedType = this .resolvedType;
313: if (this .valueCast != null)
314: convertedType = this .valueCast;
315: int runtimeType = (this .implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4;
316: switch (runtimeType) {
317: case T_boolean:
318: convertedType = TypeBinding.BOOLEAN;
319: break;
320: case T_byte:
321: convertedType = TypeBinding.BYTE;
322: break;
323: case T_short:
324: convertedType = TypeBinding.SHORT;
325: break;
326: case T_char:
327: convertedType = TypeBinding.CHAR;
328: break;
329: case T_int:
330: convertedType = TypeBinding.INT;
331: break;
332: case T_float:
333: convertedType = TypeBinding.FLOAT;
334: break;
335: case T_long:
336: convertedType = TypeBinding.LONG;
337: break;
338: case T_double:
339: convertedType = TypeBinding.DOUBLE;
340: break;
341: default:
342: }
343: if ((this .implicitConversion & TypeIds.BOXING) != 0) {
344: convertedType = scope.environment().computeBoxingType(
345: convertedType);
346: }
347: return convertedType;
348: }
349:
350: public StringBuffer printExpression(int indent, StringBuffer output) {
351:
352: if (!this .receiver.isImplicitThis())
353: this .receiver.printExpression(0, output).append('.');
354: if (this .typeArguments != null) {
355: output.append('<');
356: int max = this .typeArguments.length - 1;
357: for (int j = 0; j < max; j++) {
358: this .typeArguments[j].print(0, output);
359: output.append(", ");//$NON-NLS-1$
360: }
361: this .typeArguments[max].print(0, output);
362: output.append('>');
363: }
364: output.append(this .selector).append('(');
365: if (this .arguments != null) {
366: for (int i = 0; i < this .arguments.length; i++) {
367: if (i > 0)
368: output.append(", "); //$NON-NLS-1$
369: this .arguments[i].printExpression(0, output);
370: }
371: }
372: return output.append(')');
373: }
374:
375: public TypeBinding resolveType(BlockScope scope) {
376: // Answer the signature return type
377: // Base type promotion
378:
379: this .constant = Constant.NotAConstant;
380: boolean receiverCast = false, argsContainCast = false;
381: if (this .receiver instanceof CastExpression) {
382: this .receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
383: receiverCast = true;
384: }
385: this .actualReceiverType = this .receiver.resolveType(scope);
386: boolean receiverIsType = this .receiver instanceof NameReference
387: && (((NameReference) this .receiver).bits & Binding.TYPE) != 0;
388: if (receiverCast && this .actualReceiverType != null) {
389: // due to change of declaring class with receiver type, only identity cast should be notified
390: if (((CastExpression) this .receiver).expression.resolvedType == this .actualReceiverType) {
391: scope.problemReporter().unnecessaryCast(
392: (CastExpression) this .receiver);
393: }
394: }
395: // resolve type arguments (for generic constructor call)
396: if (this .typeArguments != null) {
397: int length = this .typeArguments.length;
398: boolean argHasError = false; // typeChecks all arguments
399: this .genericTypeArguments = new TypeBinding[length];
400: for (int i = 0; i < length; i++) {
401: TypeReference typeReference = this .typeArguments[i];
402: if ((this .genericTypeArguments[i] = typeReference
403: .resolveType(scope, true /* check bounds*/)) == null) {
404: argHasError = true;
405: }
406: if (argHasError && typeReference instanceof Wildcard) {
407: scope.problemReporter().illegalUsageOfWildcard(
408: typeReference);
409: }
410: }
411: if (argHasError) {
412: return null;
413: }
414: }
415: // will check for null after args are resolved
416: TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
417: if (this .arguments != null) {
418: boolean argHasError = false; // typeChecks all arguments
419: int length = this .arguments.length;
420: argumentTypes = new TypeBinding[length];
421: for (int i = 0; i < length; i++) {
422: Expression argument = this .arguments[i];
423: if (argument instanceof CastExpression) {
424: argument.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
425: argsContainCast = true;
426: }
427: if ((argumentTypes[i] = argument.resolveType(scope)) == null) {
428: argHasError = true;
429: }
430: }
431: if (argHasError) {
432: if (this .actualReceiverType instanceof ReferenceBinding) {
433: // record a best guess, for clients who need hint about possible method match
434: TypeBinding[] pseudoArgs = new TypeBinding[length];
435: for (int i = length; --i >= 0;)
436: pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL
437: : argumentTypes[i]; // replace args with errors with null type
438: this .binding = this .receiver.isImplicitThis() ? scope
439: .getImplicitMethod(this .selector,
440: pseudoArgs, this )
441: : scope
442: .findMethod(
443: (ReferenceBinding) this .actualReceiverType,
444: this .selector, pseudoArgs,
445: this );
446: if (this .binding != null
447: && !this .binding.isValidBinding()) {
448: MethodBinding closestMatch = ((ProblemMethodBinding) this .binding).closestMatch;
449: // record the closest match, for clients who may still need hint about possible method match
450: if (closestMatch != null) {
451: if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method
452: // shouldn't return generic method outside its context, rather convert it to raw method (175409)
453: closestMatch = scope
454: .environment()
455: .createParameterizedGenericMethod(
456: closestMatch.original(),
457: (RawTypeBinding) null);
458: }
459: this .binding = closestMatch;
460: MethodBinding closestMatchOriginal = closestMatch
461: .original();
462: if ((closestMatchOriginal.isPrivate() || closestMatchOriginal.declaringClass
463: .isLocalType())
464: && !scope
465: .isDefinedInMethod(closestMatchOriginal)) {
466: // ignore cases where method is used from within inside itself (e.g. direct recursions)
467: closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
468: }
469: }
470: }
471: }
472: return null;
473: }
474: }
475: if (this .actualReceiverType == null) {
476: return null;
477: }
478: // base type cannot receive any message
479: if (this .actualReceiverType.isBaseType()) {
480: scope.problemReporter().errorNoMethodFor(this ,
481: this .actualReceiverType, argumentTypes);
482: return null;
483: }
484: this .binding = this .receiver.isImplicitThis() ? scope
485: .getImplicitMethod(this .selector, argumentTypes, this )
486: : scope.getMethod(this .actualReceiverType,
487: this .selector, argumentTypes, this );
488: if (!this .binding.isValidBinding()) {
489: if (this .binding.declaringClass == null) {
490: if (this .actualReceiverType instanceof ReferenceBinding) {
491: this .binding.declaringClass = (ReferenceBinding) this .actualReceiverType;
492: } else {
493: scope.problemReporter().errorNoMethodFor(this ,
494: this .actualReceiverType, argumentTypes);
495: return null;
496: }
497: }
498: scope.problemReporter().invalidMethod(this , this .binding);
499: MethodBinding closestMatch = ((ProblemMethodBinding) this .binding).closestMatch;
500: switch (this .binding.problemId()) {
501: case ProblemReasons.Ambiguous:
502: break; // no resilience on ambiguous
503: case ProblemReasons.NotVisible:
504: case ProblemReasons.NonStaticReferenceInConstructorInvocation:
505: case ProblemReasons.NonStaticReferenceInStaticContext:
506: case ProblemReasons.ReceiverTypeNotVisible:
507: case ProblemReasons.ParameterBoundMismatch:
508: // only steal returnType in cases listed above
509: if (closestMatch != null)
510: this .resolvedType = closestMatch.returnType;
511: default:
512: }
513: // record the closest match, for clients who may still need hint about possible method match
514: if (closestMatch != null) {
515: this .binding = closestMatch;
516: MethodBinding closestMatchOriginal = closestMatch
517: .original();
518: if ((closestMatchOriginal.isPrivate() || closestMatchOriginal.declaringClass
519: .isLocalType())
520: && !scope
521: .isDefinedInMethod(closestMatchOriginal)) {
522: // ignore cases where method is used from within inside itself (e.g. direct recursions)
523: closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
524: }
525: }
526: return this .resolvedType;
527: }
528: final CompilerOptions compilerOptions = scope.compilerOptions();
529: if (!this .binding.isStatic()) {
530: // the "receiver" must not be a type, in other words, a NameReference that the TC has bound to a Type
531: if (receiverIsType) {
532: scope.problemReporter().mustUseAStaticMethod(this ,
533: this .binding);
534: if (this .actualReceiverType.isRawType()
535: && (this .receiver.bits & ASTNode.IgnoreRawTypeCheck) == 0
536: && compilerOptions
537: .getSeverity(CompilerOptions.RawTypeReference) != ProblemSeverities.Ignore) {
538: scope.problemReporter().rawTypeReference(
539: this .receiver, this .actualReceiverType);
540: }
541: } else {
542: this .receiver.computeConversion(scope,
543: this .actualReceiverType,
544: this .actualReceiverType);
545: // compute generic cast if necessary
546: TypeBinding receiverErasure = this .actualReceiverType
547: .erasure();
548: if (receiverErasure instanceof ReferenceBinding) {
549: if (receiverErasure
550: .findSuperTypeWithSameErasure(this .binding.declaringClass) == null) {
551: this .receiverGenericCast = this .binding.declaringClass; // handle indirect inheritance thru variable secondary bound
552: }
553: }
554: }
555: } else {
556: // static message invoked through receiver? legal but unoptimal (optional warning).
557: if (!(this .receiver.isImplicitThis()
558: || this .receiver.isSuper() || receiverIsType)) {
559: scope.problemReporter().nonStaticAccessToStaticMethod(
560: this , this .binding);
561: }
562: if (!this .receiver.isImplicitThis()
563: && this .binding.declaringClass != this .actualReceiverType) {
564: scope.problemReporter().indirectAccessToStaticMethod(
565: this , this .binding);
566: }
567: }
568: checkInvocationArguments(scope, this .receiver,
569: this .actualReceiverType, this .binding, this .arguments,
570: argumentTypes, argsContainCast, this );
571:
572: //-------message send that are known to fail at compile time-----------
573: if (this .binding.isAbstract()) {
574: if (this .receiver.isSuper()) {
575: scope.problemReporter()
576: .cannotDireclyInvokeAbstractMethod(this ,
577: this .binding);
578: }
579: // abstract private methods cannot occur nor abstract static............
580: }
581: if (isMethodUseDeprecated(this .binding, scope, true))
582: scope.problemReporter()
583: .deprecatedMethod(this .binding, this );
584:
585: // from 1.5 compliance on, array#clone() returns the array type (but binding still shows Object)
586: if (this .actualReceiverType.isArrayType()
587: && this .binding.parameters == Binding.NO_PARAMETERS
588: && compilerOptions.complianceLevel >= ClassFileConstants.JDK1_5
589: && CharOperation.equals(this .binding.selector,
590: TypeConstants.CLONE)) {
591: this .resolvedType = this .actualReceiverType;
592: } else {
593: TypeBinding returnType = this .binding.returnType;
594: if (returnType != null)
595: returnType = returnType.capture(scope, this .sourceEnd);
596: this .resolvedType = returnType;
597: }
598: if (this .receiver.isSuper()
599: && compilerOptions
600: .getSeverity(CompilerOptions.OverridingMethodWithoutSuperInvocation) != ProblemSeverities.Ignore) {
601: final ReferenceContext referenceContext = scope
602: .methodScope().referenceContext;
603: if (referenceContext instanceof AbstractMethodDeclaration) {
604: final AbstractMethodDeclaration abstractMethodDeclaration = (AbstractMethodDeclaration) referenceContext;
605: MethodBinding enclosingMethodBinding = abstractMethodDeclaration.binding;
606: if (enclosingMethodBinding.isOverriding()
607: && CharOperation.equals(this .binding.selector,
608: enclosingMethodBinding.selector)
609: && this .binding
610: .areParametersEqual(enclosingMethodBinding)) {
611: abstractMethodDeclaration.bits |= ASTNode.OverridingMethodWithSupercall;
612: }
613: }
614: }
615: return this .resolvedType;
616: }
617:
618: public void setActualReceiverType(ReferenceBinding receiverType) {
619: if (receiverType == null)
620: return; // error scenario only
621: this .actualReceiverType = receiverType;
622: }
623:
624: public void setDepth(int depth) {
625: this .bits &= ~ASTNode.DepthMASK; // flush previous depth if any
626: if (depth > 0) {
627: this .bits |= (depth & 0xFF) << ASTNode.DepthSHIFT; // encoded on 8 bits
628: }
629: }
630:
631: /**
632: * @see org.eclipse.jdt.internal.compiler.ast.Expression#setExpectedType(org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
633: */
634: public void setExpectedType(TypeBinding expectedType) {
635: this .expectedType = expectedType;
636: }
637:
638: public void setFieldIndex(int depth) {
639: // ignore for here
640: }
641:
642: public void traverse(ASTVisitor visitor, BlockScope blockScope) {
643: if (visitor.visit(this , blockScope)) {
644: this .receiver.traverse(visitor, blockScope);
645: if (this .typeArguments != null) {
646: for (int i = 0, typeArgumentsLength = this .typeArguments.length; i < typeArgumentsLength; i++) {
647: this .typeArguments[i].traverse(visitor, blockScope);
648: }
649: }
650: if (this .arguments != null) {
651: int argumentsLength = this .arguments.length;
652: for (int i = 0; i < argumentsLength; i++)
653: this.arguments[i].traverse(visitor, blockScope);
654: }
655: }
656: visitor.endVisit(this, blockScope);
657: }
658: }
|