KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > eval > CodeSnippetScope


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

11 package org.eclipse.jdt.internal.eval;
12
13 import org.eclipse.jdt.core.compiler.CharOperation;
14 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
15 import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
16 import org.eclipse.jdt.internal.compiler.lookup.Binding;
17 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
18 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
19 import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
20 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
21 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
22 import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding;
23 import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
24 import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
25 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
26 import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
27 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
28 import org.eclipse.jdt.internal.compiler.lookup.Scope;
29 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
30 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
31 import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
32
33 /**
34  * This scope is used for code snippet lookup to emulate private, protected and default access.
35  * These accesses inside inner classes are not managed yet.
36  */

37 public class CodeSnippetScope extends BlockScope {
38 /**
39  * CodeSnippetScope constructor comment.
40  * @param kind int
41  * @param parent org.eclipse.jdt.internal.compiler.lookup.Scope
42  */

43 protected CodeSnippetScope(int kind, Scope parent) {
44     super(kind, parent);
45 }
46 /**
47  * CodeSnippetScope constructor comment.
48  * @param parent org.eclipse.jdt.internal.compiler.lookup.BlockScope
49  */

50 public CodeSnippetScope(BlockScope parent) {
51     super(parent);
52 }
53 /**
54  * CodeSnippetScope constructor comment.
55  * @param parent org.eclipse.jdt.internal.compiler.lookup.BlockScope
56  * @param variableCount int
57  */

58 public CodeSnippetScope(BlockScope parent, int variableCount) {
59     super(parent, variableCount);
60 }
61 /* Answer true if the receiver is visible to the type provided by the scope.
62 * InvocationSite implements isSuperAccess() to provide additional information
63 * if the receiver is protected.
64 *
65 * NOTE: Cannot invoke this method with a compilation unit scope.
66 */

67
68 public final boolean canBeSeenByForCodeSnippet(FieldBinding fieldBinding, TypeBinding receiverType, InvocationSite invocationSite, Scope scope) {
69     if (fieldBinding.isPublic()) return true;
70
71     ReferenceBinding invocationType = (ReferenceBinding) receiverType;
72     if (invocationType == fieldBinding.declaringClass) return true;
73
74     if (fieldBinding.isProtected()) {
75         // answer true if the invocationType is the declaringClass or they are in the same package
76
// OR the invocationType is a subclass of the declaringClass
77
// AND the receiverType is the invocationType or its subclass
78
// OR the field is a static field accessed directly through a type
79
if (invocationType == fieldBinding.declaringClass) return true;
80         if (invocationType.fPackage == fieldBinding.declaringClass.fPackage) return true;
81         if (fieldBinding.declaringClass.isSuperclassOf(invocationType)) {
82             if (invocationSite.isSuperAccess()) return true;
83             // receiverType can be an array binding in one case... see if you can change it
84
if (receiverType instanceof ArrayBinding)
85                 return false;
86             if (invocationType.isSuperclassOf((ReferenceBinding) receiverType))
87                 return true;
88             if (fieldBinding.isStatic())
89                 return true; // see 1FMEPDL - return invocationSite.isTypeAccess();
90
}
91         return false;
92     }
93
94     if (fieldBinding.isPrivate()) {
95         // answer true if the receiverType is the declaringClass
96
// AND the invocationType and the declaringClass have a common enclosingType
97
if (receiverType != fieldBinding.declaringClass) return false;
98
99         if (invocationType != fieldBinding.declaringClass) {
100             ReferenceBinding outerInvocationType = invocationType;
101             ReferenceBinding temp = outerInvocationType.enclosingType();
102             while (temp != null) {
103                 outerInvocationType = temp;
104                 temp = temp.enclosingType();
105             }
106
107             ReferenceBinding outerDeclaringClass = fieldBinding.declaringClass;
108             temp = outerDeclaringClass.enclosingType();
109             while (temp != null) {
110                 outerDeclaringClass = temp;
111                 temp = temp.enclosingType();
112             }
113             if (outerInvocationType != outerDeclaringClass) return false;
114         }
115         return true;
116     }
117
118     // isDefault()
119
if (invocationType.fPackage != fieldBinding.declaringClass.fPackage) return false;
120
121     // receiverType can be an array binding in one case... see if you can change it
122
if (receiverType instanceof ArrayBinding)
123         return false;
124     ReferenceBinding type = (ReferenceBinding) receiverType;
125     PackageBinding declaringPackage = fieldBinding.declaringClass.fPackage;
126     do {
127         if (fieldBinding.declaringClass == type) return true;
128         if (declaringPackage != type.fPackage) return false;
129     } while ((type = type.superclass()) != null);
130     return false;
131 }
132 /* Answer true if the receiver is visible to the type provided by the scope.
133 * InvocationSite implements isSuperAccess() to provide additional information
134 * if the receiver is protected.
135 *
136 * NOTE: Cannot invoke this method with a compilation unit scope.
137 */

138 public final boolean canBeSeenByForCodeSnippet(MethodBinding methodBinding, TypeBinding receiverType, InvocationSite invocationSite, Scope scope) {
139     if (methodBinding.isPublic()) return true;
140
141     ReferenceBinding invocationType = (ReferenceBinding) receiverType;
142     if (invocationType == methodBinding.declaringClass && invocationType == receiverType) return true;
143
144     if (methodBinding.isProtected()) {
145         // answer true if the invocationType is the declaringClass or they are in the same package
146
// OR the invocationType is a subclass of the declaringClass
147
// AND the receiverType is the invocationType or its subclass
148
// OR the method is a static method accessed directly through a type
149
if (invocationType == methodBinding.declaringClass) return true;
150         if (invocationType.fPackage == methodBinding.declaringClass.fPackage) return true;
151         if (methodBinding.declaringClass.isSuperclassOf(invocationType)) {
152             if (invocationSite.isSuperAccess()) return true;
153             // receiverType can be an array binding in one case... see if you can change it
154
if (receiverType instanceof ArrayBinding)
155                 return false;
156             if (invocationType.isSuperclassOf((ReferenceBinding) receiverType))
157                 return true;
158             if (methodBinding.isStatic())
159                 return true; // see 1FMEPDL - return invocationSite.isTypeAccess();
160
}
161         return false;
162     }
163
164     if (methodBinding.isPrivate()) {
165         // answer true if the receiverType is the declaringClass
166
// AND the invocationType and the declaringClass have a common enclosingType
167
if (receiverType != methodBinding.declaringClass) return false;
168
169         if (invocationType != methodBinding.declaringClass) {
170             ReferenceBinding outerInvocationType = invocationType;
171             ReferenceBinding temp = outerInvocationType.enclosingType();
172             while (temp != null) {
173                 outerInvocationType = temp;
174                 temp = temp.enclosingType();
175             }
176
177             ReferenceBinding outerDeclaringClass = methodBinding.declaringClass;
178             temp = outerDeclaringClass.enclosingType();
179             while (temp != null) {
180                 outerDeclaringClass = temp;
181                 temp = temp.enclosingType();
182             }
183             if (outerInvocationType != outerDeclaringClass) return false;
184         }
185         return true;
186     }
187
188     // isDefault()
189
if (invocationType.fPackage != methodBinding.declaringClass.fPackage) return false;
190
191     // receiverType can be an array binding in one case... see if you can change it
192
if (receiverType instanceof ArrayBinding)
193         return false;
194     ReferenceBinding type = (ReferenceBinding) receiverType;
195     PackageBinding declaringPackage = methodBinding.declaringClass.fPackage;
196     do {
197         if (methodBinding.declaringClass == type) return true;
198         if (declaringPackage != type.fPackage) return false;
199     } while ((type = type.superclass()) != null);
200     return false;
201 }
202 /* Answer true if the receiver is visible to the type provided by the scope.
203 * InvocationSite implements isSuperAccess() to provide additional information
204 * if the receiver is protected.
205 *
206 * NOTE: Cannot invoke this method with a compilation unit scope.
207 */

208
209 public final boolean canBeSeenByForCodeSnippet(ReferenceBinding referenceBinding, ReferenceBinding receiverType) {
210     if (referenceBinding.isPublic()) return true;
211
212     if (receiverType == referenceBinding) return true;
213
214     if (referenceBinding.isProtected()) {
215         // answer true if the receiver (or its enclosing type) is the superclass
216
// of the receiverType or in the same package
217
return receiverType.fPackage == referenceBinding.fPackage
218                 || referenceBinding.isSuperclassOf(receiverType)
219                 || referenceBinding.enclosingType().isSuperclassOf(receiverType); // protected types always have an enclosing one
220
}
221
222     if (referenceBinding.isPrivate()) {
223         // answer true if the receiver and the receiverType have a common enclosingType
224
// already know they are not the identical type
225
ReferenceBinding outerInvocationType = receiverType;
226         ReferenceBinding temp = outerInvocationType.enclosingType();
227         while (temp != null) {
228             outerInvocationType = temp;
229             temp = temp.enclosingType();
230         }
231
232         ReferenceBinding outerDeclaringClass = referenceBinding;
233         temp = outerDeclaringClass.enclosingType();
234         while (temp != null) {
235             outerDeclaringClass = temp;
236             temp = temp.enclosingType();
237         }
238         return outerInvocationType == outerDeclaringClass;
239     }
240
241     // isDefault()
242
return receiverType.fPackage == referenceBinding.fPackage;
243 }
244 // Internal use only
245
public MethodBinding findExactMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
246     MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes, null);
247     if (exactMethod != null){
248         if (receiverType.isInterface() || canBeSeenByForCodeSnippet(exactMethod, receiverType, invocationSite, this))
249             return exactMethod;
250     }
251     return null;
252 }
253 // Internal use only
254

255 /* Answer the field binding that corresponds to fieldName.
256     Start the lookup at the receiverType.
257     InvocationSite implements
258         isSuperAccess(); this is used to determine if the discovered field is visible.
259     Only fields defined by the receiverType or its supertypes are answered;
260     a field of an enclosing type will not be found using this API.
261
262     If no visible field is discovered, null is answered.
263 */

264
265 public FieldBinding findFieldForCodeSnippet(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
266     if (receiverType.isBaseType())
267         return null;
268     if (receiverType.isArrayType()) {
269         TypeBinding leafType = receiverType.leafComponentType();
270         if (leafType instanceof ReferenceBinding)
271         if (!((ReferenceBinding)leafType).canBeSeenBy(this)) {
272             return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ProblemReasons.ReceiverTypeNotVisible);
273         }
274         if (CharOperation.equals(fieldName, LENGTH))
275             return ArrayBinding.ArrayLength;
276         return null;
277     }
278
279     ReferenceBinding currentType = (ReferenceBinding) receiverType;
280     if (!currentType.canBeSeenBy(this))
281         return new ProblemFieldBinding(currentType, fieldName, ProblemReasons.ReceiverTypeNotVisible);
282
283     FieldBinding field = currentType.getField(fieldName, true /*resolve*/);
284     if (field != null) {
285         if (canBeSeenByForCodeSnippet(field, currentType, invocationSite, this))
286             return field;
287         else
288             return new ProblemFieldBinding(field /* closest match*/, field.declaringClass, fieldName, ProblemReasons.NotVisible);
289     }
290
291     // collect all superinterfaces of receiverType until the field is found in a supertype
292
ReferenceBinding[][] interfacesToVisit = null;
293     int lastPosition = -1;
294     FieldBinding visibleField = null;
295     boolean keepLooking = true;
296     boolean notVisible = false; // we could hold onto the not visible field for extra error reporting
297
while (keepLooking) {
298         ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
299         if (itsInterfaces != Binding.NO_SUPERINTERFACES) {
300             if (interfacesToVisit == null)
301                 interfacesToVisit = new ReferenceBinding[5][];
302             if (++lastPosition == interfacesToVisit.length)
303                 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
304             interfacesToVisit[lastPosition] = itsInterfaces;
305         }
306         if ((currentType = currentType.superclass()) == null)
307             break;
308
309         if ((field = currentType.getField(fieldName, true /*resolve*/)) != null) {
310             keepLooking = false;
311             if (canBeSeenByForCodeSnippet(field, receiverType, invocationSite, this)) {
312                 if (visibleField == null)
313                     visibleField = field;
314                 else
315                     return new ProblemFieldBinding(visibleField, visibleField.declaringClass, fieldName, ProblemReasons.Ambiguous);
316             } else {
317                 notVisible = true;
318             }
319         }
320     }
321
322     // walk all visible interfaces to find ambiguous references
323
if (interfacesToVisit != null) {
324         ProblemFieldBinding ambiguous = null;
325         org.eclipse.jdt.internal.compiler.util.SimpleSet interfacesSeen = new org.eclipse.jdt.internal.compiler.util.SimpleSet(lastPosition * 2);
326         done : for (int i = 0; i <= lastPosition; i++) {
327             ReferenceBinding[] interfaces = interfacesToVisit[i];
328             for (int j = 0, length = interfaces.length; j < length; j++) {
329                 ReferenceBinding anInterface = interfaces[j];
330                 if (interfacesSeen.addIfNotIncluded(anInterface) == anInterface) {
331                     // if interface as not already been visited
332
if ((field = anInterface.getField(fieldName, true /*resolve*/)) != null) {
333                         if (visibleField == null) {
334                             visibleField = field;
335                         } else {
336                             ambiguous = new ProblemFieldBinding(visibleField, visibleField.declaringClass, fieldName, ProblemReasons.Ambiguous);
337                             break done;
338                         }
339                     } else {
340                         ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
341                         if (itsInterfaces != Binding.NO_SUPERINTERFACES) {
342                             if (++lastPosition == interfacesToVisit.length)
343                                 System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
344                             interfacesToVisit[lastPosition] = itsInterfaces;
345                         }
346                     }
347                 }
348             }
349         }
350         if (ambiguous != null) return ambiguous;
351     }
352
353     if (visibleField != null)
354         return visibleField;
355     if (notVisible)
356         return new ProblemFieldBinding(currentType, fieldName, ProblemReasons.NotVisible);
357     return null;
358 }
359 // Internal use only
360
public MethodBinding findMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
361     MethodBinding methodBinding = super.findMethod(receiverType, selector, argumentTypes, invocationSite);
362     if (methodBinding != null && methodBinding.isValidBinding())
363         if (!canBeSeenByForCodeSnippet(methodBinding, receiverType, invocationSite, this))
364             return new ProblemMethodBinding(methodBinding, selector, argumentTypes, ProblemReasons.NotVisible);
365     return methodBinding;
366 }
367
368 // Internal use only
369
public MethodBinding findMethodForArray(ArrayBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
370     ReferenceBinding object = getJavaLangObject();
371     MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes, null);
372     if (methodBinding != null) {
373         // handle the method clone() specially... cannot be protected or throw exceptions
374
if (argumentTypes == Binding.NO_PARAMETERS && CharOperation.equals(selector, CLONE))
375             return new MethodBinding((methodBinding.modifiers & ~ClassFileConstants.AccProtected) | ClassFileConstants.AccPublic, CLONE, methodBinding.returnType, argumentTypes, null, object);
376         if (canBeSeenByForCodeSnippet(methodBinding, receiverType, invocationSite, this))
377             return methodBinding;
378     }
379
380     // answers closest approximation, may not check argumentTypes or visibility
381
methodBinding = findMethod(object, selector, argumentTypes, invocationSite);
382     if (methodBinding == null)
383         return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound);
384     if (methodBinding.isValidBinding()) {
385         MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
386         if (compatibleMethod == null)
387             return new ProblemMethodBinding(methodBinding, selector, argumentTypes, ProblemReasons.NotFound);
388         methodBinding = compatibleMethod;
389         if (!canBeSeenByForCodeSnippet(methodBinding, receiverType, invocationSite, this))
390             return new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, ProblemReasons.NotVisible);
391     }
392     return methodBinding;
393 }
394 /* API
395     flag is a mask of the following values VARIABLE (= FIELD or LOCAL), TYPE.
396     Only bindings corresponding to the mask will be answered.
397
398     if the VARIABLE mask is set then
399         If the first name provided is a field (or local) then the field (or local) is answered
400         Otherwise, package names and type names are consumed until a field is found.
401         In this case, the field is answered.
402
403     if the TYPE mask is set,
404         package names and type names are consumed until the end of the input.
405         Only if all of the input is consumed is the type answered
406
407     All other conditions are errors, and a problem binding is returned.
408     
409     NOTE: If a problem binding is returned, senders should extract the compound name
410     from the binding & not assume the problem applies to the entire compoundName.
411
412     The VARIABLE mask has precedence over the TYPE mask.
413
414     InvocationSite implements
415         isSuperAccess(); this is used to determine if the discovered field is visible.
416         setFieldIndex(int); this is used to record the number of names that were consumed.
417
418     For example, getBinding({"foo","y","q", VARIABLE, site) will answer
419     the binding for the field or local named "foo" (or an error binding if none exists).
420     In addition, setFieldIndex(1) will be sent to the invocation site.
421     If a type named "foo" exists, it will not be detected (and an error binding will be answered)
422
423     IMPORTANT NOTE: This method is written under the assumption that compoundName is longer than length 1.
424 */

425
426 public Binding getBinding(char[][] compoundName, int mask, InvocationSite invocationSite, ReferenceBinding receiverType) {
427     Binding binding = getBinding(compoundName[0], mask | Binding.TYPE | Binding.PACKAGE, invocationSite, true /*resolve*/);
428     invocationSite.setFieldIndex(1);
429     if (!binding.isValidBinding() || binding instanceof VariableBinding)
430         return binding;
431
432     int length = compoundName.length;
433     int currentIndex = 1;
434     foundType: if (binding instanceof PackageBinding) {
435         PackageBinding packageBinding = (PackageBinding) binding;
436
437         while (currentIndex < length) {
438             binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
439             invocationSite.setFieldIndex(currentIndex);
440             if (binding == null) {
441                 if (currentIndex == length) // must be a type if its the last name, otherwise we have no idea if its a package or type
442
return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), null, ProblemReasons.NotFound);
443                 else
444                     return new ProblemBinding(CharOperation.subarray(compoundName, 0, currentIndex), ProblemReasons.NotFound);
445             }
446             if (binding instanceof ReferenceBinding) {
447                 if (!binding.isValidBinding())
448                     return new ProblemReferenceBinding(
449                                     CharOperation.subarray(compoundName, 0, currentIndex),
450                                     ((ReferenceBinding)binding).closestMatch(),
451                                     binding.problemId());
452                 if (!this.canBeSeenByForCodeSnippet((ReferenceBinding) binding, receiverType))
453                     return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), (ReferenceBinding) binding, ProblemReasons.NotVisible);
454                 break foundType;
455             }
456             packageBinding = (PackageBinding) binding;
457         }
458
459         // It is illegal to request a PACKAGE from this method.
460
return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), null, ProblemReasons.NotFound);
461     }
462
463     // know binding is now a ReferenceBinding
464
while (currentIndex < length) {
465         ReferenceBinding typeBinding = (ReferenceBinding) binding;
466         char[] nextName = compoundName[currentIndex++];
467         invocationSite.setFieldIndex(currentIndex);
468         if ((binding = findFieldForCodeSnippet(typeBinding, nextName, invocationSite)) != null) {
469             if (!binding.isValidBinding()) {
470                 return new ProblemFieldBinding(
471                         (FieldBinding)binding,
472                         ((FieldBinding)binding).declaringClass,
473                         CharOperation.concatWith(CharOperation.subarray(compoundName, 0, currentIndex), '.'),
474                         binding.problemId());
475             }
476             break; // binding is now a field
477
}
478         if ((binding = findMemberType(nextName, typeBinding)) == null)
479             return new ProblemBinding(CharOperation.subarray(compoundName, 0, currentIndex), typeBinding, ProblemReasons.NotFound);
480          if (!binding.isValidBinding())
481             return new ProblemReferenceBinding(
482                                 CharOperation.subarray(compoundName, 0, currentIndex),
483                                 ((ReferenceBinding)binding).closestMatch(),
484                                 binding.problemId());
485     }
486
487     if ((mask & Binding.FIELD) != 0 && (binding instanceof FieldBinding)) { // was looking for a field and found a field
488
FieldBinding field = (FieldBinding) binding;
489         if (!field.isStatic()) {
490             return new ProblemFieldBinding(
491                     field,
492                     field.declaringClass,
493                     CharOperation.concatWith(CharOperation.subarray(compoundName, 0, currentIndex), '.'),
494                     ProblemReasons.NonStaticReferenceInStaticContext);
495         }
496         return binding;
497     }
498     if ((mask & Binding.TYPE) != 0 && (binding instanceof ReferenceBinding)) { // was looking for a type and found a type
499
return binding;
500     }
501
502     // handle the case when a field or type was asked for but we resolved the compoundName to a type or field
503
return new ProblemBinding(CharOperation.subarray(compoundName, 0, currentIndex), ProblemReasons.NotFound);
504 }
505 /* API
506
507     Answer the constructor binding that corresponds to receiverType, argumentTypes.
508
509     InvocationSite implements
510         isSuperAccess(); this is used to determine if the discovered constructor is visible.
511
512     If no visible constructor is discovered, an error binding is answered.
513 */

514
515 public MethodBinding getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
516     MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes);
517     if (methodBinding != null) {
518         if (canBeSeenByForCodeSnippet(methodBinding, receiverType, invocationSite, this)) {
519             return methodBinding;
520         }
521     }
522     MethodBinding[] methods = receiverType.getMethods(TypeConstants.INIT);
523     if (methods == Binding.NO_METHODS) {
524         return new ProblemMethodBinding(TypeConstants.INIT, argumentTypes, ProblemReasons.NotFound);
525     }
526     MethodBinding[] compatible = new MethodBinding[methods.length];
527     int compatibleIndex = 0;
528     for (int i = 0, length = methods.length; i < length; i++) {
529         MethodBinding compatibleMethod = computeCompatibleMethod(methods[i], argumentTypes, invocationSite);
530         if (compatibleMethod != null)
531             compatible[compatibleIndex++] = compatibleMethod;
532     }
533     if (compatibleIndex == 0)
534         return new ProblemMethodBinding(TypeConstants.INIT, argumentTypes, ProblemReasons.NotFound); // need a more descriptive error... cannot convert from X to Y
535

536     MethodBinding[] visible = new MethodBinding[compatibleIndex];
537     int visibleIndex = 0;
538     for (int i = 0; i < compatibleIndex; i++) {
539         MethodBinding method = compatible[i];
540         if (canBeSeenByForCodeSnippet(method, receiverType, invocationSite, this)) {
541             visible[visibleIndex++] = method;
542         }
543     }
544     if (visibleIndex == 1) {
545         return visible[0];
546     }
547     if (visibleIndex == 0) {
548         return new ProblemMethodBinding(compatible[0], TypeConstants.INIT, compatible[0].parameters, ProblemReasons.NotVisible);
549     }
550     return mostSpecificClassMethodBinding(visible, visibleIndex, invocationSite);
551 }
552 /* API
553
554     Answer the field binding that corresponds to fieldName.
555     Start the lookup at the receiverType.
556     InvocationSite implements
557         isSuperAccess(); this is used to determine if the discovered field is visible.
558     Only fields defined by the receiverType or its supertypes are answered;
559     a field of an enclosing type will not be found using this API.
560
561     If no visible field is discovered, an error binding is answered.
562 */

563
564 public FieldBinding getFieldForCodeSnippet(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
565     FieldBinding field = findFieldForCodeSnippet(receiverType, fieldName, invocationSite);
566     if (field == null)
567         return new ProblemFieldBinding(receiverType instanceof ReferenceBinding ? (ReferenceBinding) receiverType : null, fieldName, ProblemReasons.NotFound);
568     else
569         return field;
570 }
571 /* API
572
573     Answer the method binding that corresponds to selector, argumentTypes.
574     Start the lookup at the enclosing type of the receiver.
575     InvocationSite implements
576         isSuperAccess(); this is used to determine if the discovered method is visible.
577         setDepth(int); this is used to record the depth of the discovered method
578             relative to the enclosing type of the receiver. (If the method is defined
579             in the enclosing type of the receiver, the depth is 0; in the next enclosing
580             type, the depth is 1; and so on
581
582     If no visible method is discovered, an error binding is answered.
583 */

584
585 public MethodBinding getImplicitMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
586     // retrieve an exact visible match (if possible)
587
MethodBinding methodBinding = findExactMethod(receiverType, selector, argumentTypes, invocationSite);
588     if (methodBinding == null)
589         methodBinding = findMethod(receiverType, selector, argumentTypes, invocationSite);
590     if (methodBinding != null) { // skip it if we did not find anything
591
if (methodBinding.isValidBinding())
592             if (!canBeSeenByForCodeSnippet(methodBinding, receiverType, invocationSite, this))
593                 return new ProblemMethodBinding(methodBinding, selector, argumentTypes, ProblemReasons.NotVisible);
594         return methodBinding;
595     }
596     return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound);
597 }
598 }
599
Popular Tags