]> source.dussan.org Git - aspectj.git/blob
10e93ae00261699914ea9250e89c0b6bae5edb9b
[aspectj.git] /
1 /* *******************************************************************
2  * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
3  * All rights reserved. 
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 
8  *  
9  * Contributors: 
10  *     PARC     initial implementation 
11  * ******************************************************************/
12
13 package org.aspectj.ajdt.internal.compiler.lookup;
14
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;
28
29 /**
30  * A special method binding representing an ITD that pretends to be a member in some target type for matching purposes.
31  */
32 public class InterTypeMethodBinding extends MethodBinding {
33
34         /** The target type upon which the ITD is declared */
35         private ReferenceBinding targetType;
36
37         /**
38          * This is the 'pretend' method that should be the target of any attempt to call the ITD'd method.
39          */
40         private MethodBinding syntheticMethod;
41
42         public MethodBinding postDispatchMethod;
43
44         public AbstractMethodDeclaration sourceMethod;
45
46         public InterTypeMethodBinding(EclipseFactory world, ResolvedTypeMunger munger, UnresolvedType withinType,
47                         AbstractMethodDeclaration sourceMethod) {
48                 super();
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);
60
61                 // Ok, we need to set the typevariable declaring elements
62                 // 1st set:
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;
66                 }
67                 for (int i = 0; i < typeVariables.length; i++) {
68                         if (typeVariables[i].declaringElement == null)
69                                 throw new RuntimeException("Declaring element not set");
70
71                 }
72                 // typeVariables[0].declaringElement=this;
73                 // if (tVar.getDeclaringElement() instanceof Member) {
74                 // declaringElement = makeMethodBinding((ResolvedMember)tVar.getDeclaringElement());
75                 // } else {
76                 // declaringElement = makeTypeBinding((UnresolvedType)tVar.getDeclaringElement());
77                 // }
78                 if (signature.getKind() == Member.METHOD) {
79                         syntheticMethod = world.makeMethodBinding(AjcMemberMaker.interMethodDispatcher(signature, withinType));
80                         postDispatchMethod = world.makeMethodBinding(AjcMemberMaker.interMethodBody(signature, withinType));
81                 } else {
82                         syntheticMethod = world.makeMethodBinding(AjcMemberMaker.interConstructor(world.getWorld().resolve(
83                                         signature.getDeclaringType()), signature, withinType));
84                         postDispatchMethod = syntheticMethod;
85                 }
86
87         }
88
89         // XXX this is identical to InterTypeFieldBinding
90         @Override
91         public boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) {
92                 scope.compilationUnitScope().recordTypeReference(declaringClass);
93
94                 if (isPublic())
95                         return true;
96
97                 SourceTypeBinding invocationType = scope.invocationType();
98                 // System.out.println("receiver: " + receiverType + ", " + invocationType);
99
100                 if (invocationType == declaringClass)
101                         return true;
102
103                 if (invocationType.privilegedHandler != null) {
104                         // it is a privileged aspect
105                         return true;
106                 }
107                 
108                 if (isProtected()) {
109                         throw new RuntimeException("unimplemented");
110                 }
111
112                 // XXX make sure this walks correctly
113                 if (isPrivate()) {
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) {
120                                                 return true;
121                                         }
122                                         enclosingType = enclosingType.enclosingType();
123                                 }
124                         }
125
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;
129
130                         if (invocationType != declaringClass) {
131                                 ReferenceBinding outerInvocationType = invocationType;
132                                 ReferenceBinding temp = outerInvocationType.enclosingType();
133                                 while (temp != null) {
134                                         outerInvocationType = temp;
135                                         temp = temp.enclosingType();
136                                 }
137
138                                 ReferenceBinding outerDeclaringClass = declaringClass;
139                                 temp = outerDeclaringClass.enclosingType();
140                                 while (temp != null) {
141                                         outerDeclaringClass = temp;
142                                         temp = temp.enclosingType();
143                                 }
144
145                                 // System.err.println("outer dec: " +
146                                 if (outerInvocationType != outerDeclaringClass)
147                                         return false;
148                         }
149                         return true;
150                 }
151
152                 // isDefault()
153                 if (invocationType.fPackage == declaringClass.fPackage)
154                         return true;
155                 return false;
156         }
157
158         @Override
159         public boolean isFinal() {
160                 if (sourceMethod == null || !(sourceMethod instanceof InterTypeMethodDeclaration))
161                         return super.isFinal();
162                 return ((InterTypeMethodDeclaration) sourceMethod).isFinal();
163         }
164
165         @Override
166         public MethodBinding getAccessMethod(boolean staticReference) {
167                 if (staticReference)
168                         return postDispatchMethod;
169                 else
170                         return syntheticMethod;
171         }
172
173         @Override
174         public boolean alwaysNeedsAccessMethod() {
175                 return true;
176         }
177
178         @Override
179         public AbstractMethodDeclaration sourceMethod() {
180                 return sourceMethod;
181         }
182
183         public ReferenceBinding getTargetType() {
184                 return targetType;
185         }
186
187         // override method in MethodBinding to ensure correct behaviour in some of JDTs generics checks.
188         @Override
189         public ReferenceBinding getOwningClass() {
190                 return targetType;
191         }
192
193         @Override
194         public String toString() {
195                 return "InterTypeMethodBinding(" + super.toString() + ", " + getTargetType() + ")";
196         }
197 }