KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > lookup > SyntheticAccessMethodBinding


1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.compiler.lookup;
12
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
15 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
16
17 public class SyntheticAccessMethodBinding extends MethodBinding {
18
19     public FieldBinding targetReadField; // read access to a field
20
public FieldBinding targetWriteField; // write access to a field
21
public MethodBinding targetMethod; // method or constructor
22

23     public int accessType;
24
25     public final static int FieldReadAccess = 1; // field read
26
public final static int FieldWriteAccess = 2; // field write
27
public final static int MethodAccess = 3; // normal method
28
public final static int ConstructorAccess = 4; // constructor
29
public final static int SuperMethodAccess = 5; // super method
30

31     final static char[] AccessMethodPrefix = { 'a', 'c', 'c', 'e', 's', 's', '$' };
32
33     public int sourceStart = 0; // start position of the matching declaration
34
public int index; // used for sorting access methods in the class file
35

36     public SyntheticAccessMethodBinding(FieldBinding targetField, boolean isReadAccess, ReferenceBinding declaringClass) {
37
38         this.modifiers = AccDefault | AccStatic | AccSynthetic;
39         SourceTypeBinding declaringSourceType = (SourceTypeBinding) declaringClass;
40         SyntheticAccessMethodBinding[] knownAccessMethods = declaringSourceType.syntheticAccessMethods();
41         int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
42         this.index = methodId;
43         this.selector = CharOperation.concat(AccessMethodPrefix, String.valueOf(methodId).toCharArray());
44         if (isReadAccess) {
45             this.returnType = targetField.type;
46             if (targetField.isStatic()) {
47                 this.parameters = NoParameters;
48             } else {
49                 this.parameters = new TypeBinding[1];
50                 this.parameters[0] = declaringSourceType;
51             }
52             this.targetReadField = targetField;
53             this.accessType = FieldReadAccess;
54         } else {
55             this.returnType = VoidBinding;
56             if (targetField.isStatic()) {
57                 this.parameters = new TypeBinding[1];
58                 this.parameters[0] = targetField.type;
59             } else {
60                 this.parameters = new TypeBinding[2];
61                 this.parameters[0] = declaringSourceType;
62                 this.parameters[1] = targetField.type;
63             }
64             this.targetWriteField = targetField;
65             this.accessType = FieldWriteAccess;
66         }
67         this.thrownExceptions = NoExceptions;
68         this.declaringClass = declaringSourceType;
69     
70         // check for method collision
71
boolean needRename;
72         do {
73             check : {
74                 needRename = false;
75                 // check for collision with known methods
76
MethodBinding[] methods = declaringSourceType.methods;
77                 for (int i = 0, length = methods.length; i < length; i++) {
78                     if (CharOperation.equals(this.selector, methods[i].selector) && this.areParametersEqual(methods[i])) {
79                         needRename = true;
80                         break check;
81                     }
82                 }
83                 // check for collision with synthetic accessors
84
if (knownAccessMethods != null) {
85                     for (int i = 0, length = knownAccessMethods.length; i < length; i++) {
86                         if (knownAccessMethods[i] == null) continue;
87                         if (CharOperation.equals(this.selector, knownAccessMethods[i].selector) && this.areParametersEqual(methods[i])) {
88                             needRename = true;
89                             break check;
90                         }
91                     }
92                 }
93             }
94             if (needRename) { // retry with a selector postfixed by a growing methodId
95
this.setSelector(CharOperation.concat(AccessMethodPrefix, String.valueOf(++methodId).toCharArray()));
96             }
97         } while (needRename);
98     
99         // retrieve sourceStart position for the target field for line number attributes
100
FieldDeclaration[] fieldDecls = declaringSourceType.scope.referenceContext.fields;
101         if (fieldDecls != null) {
102             for (int i = 0, max = fieldDecls.length; i < max; i++) {
103                 if (fieldDecls[i].binding == targetField) {
104                     this.sourceStart = fieldDecls[i].sourceStart;
105                     return;
106                 }
107             }
108         }
109     
110     /* did not find the target field declaration - it is a synthetic one
111         public class A {
112             public class B {
113                 public class C {
114                     void foo() {
115                         System.out.println("A.this = " + A.this);
116                     }
117                 }
118             }
119             public static void main(String args[]) {
120                 new A().new B().new C().foo();
121             }
122         }
123     */

124         // We now at this point - per construction - it is for sure an enclosing instance, we are going to
125
// show the target field type declaration location.
126
this.sourceStart = declaringSourceType.scope.referenceContext.sourceStart; // use the target declaring class name position instead
127
}
128
129     public SyntheticAccessMethodBinding(MethodBinding targetMethod, boolean isSuperAccess, ReferenceBinding receiverType) {
130     
131         if (targetMethod.isConstructor()) {
132             this.initializeConstructorAccessor(targetMethod);
133         } else {
134             this.initializeMethodAccessor(targetMethod, isSuperAccess, receiverType);
135         }
136     }
137
138     /**
139      * An constructor accessor is a constructor with an extra argument (declaringClass), in case of
140      * collision with an existing constructor, then add again an extra argument (declaringClass again).
141      */

142      public void initializeConstructorAccessor(MethodBinding accessedConstructor) {
143     
144         this.targetMethod = accessedConstructor;
145         this.modifiers = AccDefault | AccSynthetic;
146         SourceTypeBinding sourceType = (SourceTypeBinding) accessedConstructor.declaringClass;
147         SyntheticAccessMethodBinding[] knownAccessMethods =
148             sourceType.syntheticAccessMethods();
149         this.index = knownAccessMethods == null ? 0 : knownAccessMethods.length;
150     
151         this.selector = accessedConstructor.selector;
152         this.returnType = accessedConstructor.returnType;
153         this.accessType = ConstructorAccess;
154         this.parameters = new TypeBinding[accessedConstructor.parameters.length + 1];
155         System.arraycopy(
156             accessedConstructor.parameters,
157             0,
158             this.parameters,
159             0,
160             accessedConstructor.parameters.length);
161         parameters[accessedConstructor.parameters.length] =
162             accessedConstructor.declaringClass;
163         this.thrownExceptions = accessedConstructor.thrownExceptions;
164         this.declaringClass = sourceType;
165     
166         // check for method collision
167
boolean needRename;
168         do {
169             check : {
170                 needRename = false;
171                 // check for collision with known methods
172
MethodBinding[] methods = sourceType.methods;
173                 for (int i = 0, length = methods.length; i < length; i++) {
174                     if (CharOperation.equals(this.selector, methods[i].selector)
175                         && this.areParametersEqual(methods[i])) {
176                         needRename = true;
177                         break check;
178                     }
179                 }
180                 // check for collision with synthetic accessors
181
if (knownAccessMethods != null) {
182                     for (int i = 0, length = knownAccessMethods.length; i < length; i++) {
183                         if (knownAccessMethods[i] == null)
184                             continue;
185                         if (CharOperation.equals(this.selector, knownAccessMethods[i].selector)
186                             && this.areParametersEqual(knownAccessMethods[i])) {
187                             needRename = true;
188                             break check;
189                         }
190                     }
191                 }
192             }
193             if (needRename) { // retry with a new extra argument
194
int length = this.parameters.length;
195                 System.arraycopy(
196                     this.parameters,
197                     0,
198                     this.parameters = new TypeBinding[length + 1],
199                     0,
200                     length);
201                 this.parameters[length] = this.declaringClass;
202             }
203         } while (needRename);
204     
205         // retrieve sourceStart position for the target method for line number attributes
206
AbstractMethodDeclaration[] methodDecls =
207             sourceType.scope.referenceContext.methods;
208         if (methodDecls != null) {
209             for (int i = 0, length = methodDecls.length; i < length; i++) {
210                 if (methodDecls[i].binding == accessedConstructor) {
211                     this.sourceStart = methodDecls[i].sourceStart;
212                     return;
213                 }
214             }
215         }
216     }
217
218     /**
219      * An method accessor is a method with an access$N selector, where N is incremented in case of collisions.
220      */

221     public void initializeMethodAccessor(MethodBinding accessedMethod, boolean isSuperAccess, ReferenceBinding receiverType) {
222         
223         this.targetMethod = accessedMethod;
224         this.modifiers = AccDefault | AccStatic | AccSynthetic;
225         SourceTypeBinding declaringSourceType = (SourceTypeBinding) receiverType;
226         SyntheticAccessMethodBinding[] knownAccessMethods = declaringSourceType.syntheticAccessMethods();
227         int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
228         this.index = methodId;
229     
230         this.selector = CharOperation.concat(AccessMethodPrefix, String.valueOf(methodId).toCharArray());
231         this.returnType = accessedMethod.returnType;
232         this.accessType = isSuperAccess ? SuperMethodAccess : MethodAccess;
233         
234         if (accessedMethod.isStatic()) {
235             this.parameters = accessedMethod.parameters;
236         } else {
237             this.parameters = new TypeBinding[accessedMethod.parameters.length + 1];
238             this.parameters[0] = declaringSourceType;
239             System.arraycopy(accessedMethod.parameters, 0, this.parameters, 1, accessedMethod.parameters.length);
240         }
241         this.thrownExceptions = accessedMethod.thrownExceptions;
242         this.declaringClass = declaringSourceType;
243     
244         // check for method collision
245
boolean needRename;
246         do {
247             check : {
248                 needRename = false;
249                 // check for collision with known methods
250
MethodBinding[] methods = declaringSourceType.methods;
251                 for (int i = 0, length = methods.length; i < length; i++) {
252                     if (CharOperation.equals(this.selector, methods[i].selector) && this.areParametersEqual(methods[i])) {
253                         needRename = true;
254                         break check;
255                     }
256                 }
257                 // check for collision with synthetic accessors
258
if (knownAccessMethods != null) {
259                     for (int i = 0, length = knownAccessMethods.length; i < length; i++) {
260                         if (knownAccessMethods[i] == null) continue;
261                         if (CharOperation.equals(this.selector, knownAccessMethods[i].selector) && this.areParametersEqual(knownAccessMethods[i])) {
262                             needRename = true;
263                             break check;
264                         }
265                     }
266                 }
267             }
268             if (needRename) { // retry with a selector & a growing methodId
269
this.setSelector(CharOperation.concat(AccessMethodPrefix, String.valueOf(++methodId).toCharArray()));
270             }
271         } while (needRename);
272     
273         // retrieve sourceStart position for the target method for line number attributes
274
AbstractMethodDeclaration[] methodDecls = declaringSourceType.scope.referenceContext.methods;
275         if (methodDecls != null) {
276             for (int i = 0, length = methodDecls.length; i < length; i++) {
277                 if (methodDecls[i].binding == accessedMethod) {
278                     this.sourceStart = methodDecls[i].sourceStart;
279                     return;
280                 }
281             }
282         }
283     }
284
285     protected boolean isConstructorRelated() {
286         return accessType == ConstructorAccess;
287     }
288 }
289
Popular Tags