1 /* *******************************************************************
2 * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
4 * This program and the accompanying materials are made available
5 * under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * PARC initial implementation
11 * ******************************************************************/
13 package org.aspectj.ajdt.internal.compiler.lookup;
15 import org.aspectj.ajdt.internal.compiler.ast.InterTypeMethodDeclaration;
16 import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
17 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
18 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
19 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
20 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Scope;
21 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
22 import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
23 import org.aspectj.weaver.AjcMemberMaker;
24 import org.aspectj.weaver.Member;
25 import org.aspectj.weaver.ResolvedMember;
26 import org.aspectj.weaver.ResolvedTypeMunger;
27 import org.aspectj.weaver.UnresolvedType;
30 * A special method binding representing an ITD that pretends to be a member in some target type for matching purposes.
32 public class InterTypeMethodBinding extends MethodBinding {
34 /** The target type upon which the ITD is declared */
35 private ReferenceBinding targetType;
38 * This is the 'pretend' method that should be the target of any attempt to call the ITD'd method.
40 private MethodBinding syntheticMethod;
42 public MethodBinding postDispatchMethod;
44 public AbstractMethodDeclaration sourceMethod;
46 public InterTypeMethodBinding(EclipseFactory world, ResolvedTypeMunger munger, UnresolvedType withinType,
47 AbstractMethodDeclaration sourceMethod) {
49 ResolvedMember signature = munger.getSignature();
50 MethodBinding mb = world.makeMethodBinding(signature, munger.getTypeVariableAliases());
51 this.modifiers = mb.modifiers;
52 this.selector = mb.selector;
53 this.returnType = mb.returnType;
54 this.parameters = mb.parameters;
55 this.thrownExceptions = mb.thrownExceptions;
56 this.typeVariables = mb.typeVariables;
57 this.sourceMethod = sourceMethod;
58 this.targetType = (ReferenceBinding) world.makeTypeBinding(signature.getDeclaringType());
59 this.declaringClass = (ReferenceBinding) world.makeTypeBinding(withinType);
61 // Ok, we need to set the typevariable declaring elements
63 // If the typevariable is one declared on the source method, then we know we are the declaring element
64 for (int i = 0; i < typeVariables.length; i++) {
65 typeVariables[i].declaringElement = this;
67 for (int i = 0; i < typeVariables.length; i++) {
68 if (typeVariables[i].declaringElement == null)
69 throw new RuntimeException("Declaring element not set");
72 // typeVariables[0].declaringElement=this;
73 // if (tVar.getDeclaringElement() instanceof Member) {
74 // declaringElement = makeMethodBinding((ResolvedMember)tVar.getDeclaringElement());
76 // declaringElement = makeTypeBinding((UnresolvedType)tVar.getDeclaringElement());
78 if (signature.getKind() == Member.METHOD) {
79 syntheticMethod = world.makeMethodBinding(AjcMemberMaker.interMethodDispatcher(signature, withinType));
80 postDispatchMethod = world.makeMethodBinding(AjcMemberMaker.interMethodBody(signature, withinType));
82 syntheticMethod = world.makeMethodBinding(AjcMemberMaker.interConstructor(world.getWorld().resolve(
83 signature.getDeclaringType()), signature, withinType));
84 postDispatchMethod = syntheticMethod;
89 // XXX this is identical to InterTypeFieldBinding
91 public boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) {
92 scope.compilationUnitScope().recordTypeReference(declaringClass);
97 SourceTypeBinding invocationType = scope.invocationType();
98 // System.out.println("receiver: " + receiverType + ", " + invocationType);
100 if (invocationType == declaringClass)
103 if (invocationType.privilegedHandler != null) {
104 // it is a privileged aspect
109 throw new RuntimeException("unimplemented");
112 // XXX make sure this walks correctly
114 // Possibly the call is made from an inner type within the privileged aspect
115 // TODO should check the first outer aspect we come across and stop at that point?
116 if (invocationType.isNestedType()) {
117 TypeBinding enclosingType = invocationType.enclosingType();
118 while (enclosingType != null) {
119 if ((enclosingType instanceof SourceTypeBinding) && ((SourceTypeBinding)enclosingType).privilegedHandler != null) {
122 enclosingType = enclosingType.enclosingType();
126 // answer true if the receiverType is the declaringClass
127 // AND the invocationType and the declaringClass have a common enclosingType
128 // if (receiverType != declaringClass) return false;
130 if (invocationType != declaringClass) {
131 ReferenceBinding outerInvocationType = invocationType;
132 ReferenceBinding temp = outerInvocationType.enclosingType();
133 while (temp != null) {
134 outerInvocationType = temp;
135 temp = temp.enclosingType();
138 ReferenceBinding outerDeclaringClass = declaringClass;
139 temp = outerDeclaringClass.enclosingType();
140 while (temp != null) {
141 outerDeclaringClass = temp;
142 temp = temp.enclosingType();
145 // System.err.println("outer dec: " +
146 if (outerInvocationType != outerDeclaringClass)
153 if (invocationType.fPackage == declaringClass.fPackage)
159 public boolean isFinal() {
160 if (sourceMethod == null || !(sourceMethod instanceof InterTypeMethodDeclaration))
161 return super.isFinal();
162 return ((InterTypeMethodDeclaration) sourceMethod).isFinal();
166 public MethodBinding getAccessMethod(boolean staticReference) {
168 return postDispatchMethod;
170 return syntheticMethod;
174 public boolean alwaysNeedsAccessMethod() {
179 public AbstractMethodDeclaration sourceMethod() {
183 public ReferenceBinding getTargetType() {
187 // override method in MethodBinding to ensure correct behaviour in some of JDTs generics checks.
189 public ReferenceBinding getOwningClass() {
194 public String toString() {
195 return "InterTypeMethodBinding(" + super.toString() + ", " + getTargetType() + ")";