KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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.compiler.lookup;
12
13 import org.eclipse.jdt.internal.compiler.ast.Wildcard;
14
15 /**
16  * Binding denoting a method after type parameter substitutions got performed.
17  * On parameterized type bindings, all methods got substituted, regardless whether
18  * their signature did involve generics or not, so as to get the proper declaringClass for
19  * these methods.
20  */

21 public class ParameterizedMethodBinding extends MethodBinding {
22
23     protected MethodBinding originalMethod;
24
25     /**
26      * Create method of parameterized type, substituting original parameters/exception/return type with type arguments.
27      */

28     public ParameterizedMethodBinding(final ParameterizedTypeBinding parameterizedDeclaringClass, MethodBinding originalMethod) {
29
30         super(
31                 originalMethod.modifiers,
32                 originalMethod.selector,
33                  originalMethod.returnType,
34                 originalMethod.parameters,
35                 originalMethod.thrownExceptions,
36                 parameterizedDeclaringClass);
37         this.originalMethod = originalMethod;
38         this.tagBits = originalMethod.tagBits;
39         
40         final TypeVariableBinding[] originalVariables = originalMethod.typeVariables;
41         Substitution substitution = null;
42         final int length = originalVariables.length;
43         final boolean isStatic = originalMethod.isStatic();
44         if (length == 0) {
45             this.typeVariables = Binding.NO_TYPE_VARIABLES;
46             if (!isStatic) substitution = parameterizedDeclaringClass;
47         } else {
48             // at least fix up the declaringElement binding + bound substitution if non static
49
final TypeVariableBinding[] substitutedVariables = new TypeVariableBinding[length];
50             for (int i = 0; i < length; i++) { // copy original type variable to relocate
51
TypeVariableBinding originalVariable = originalVariables[i];
52                 substitutedVariables[i] = new TypeVariableBinding(originalVariable.sourceName, this, originalVariable.rank);
53             }
54             this.typeVariables = substitutedVariables;
55             
56             // need to substitute old var refs with new ones (double substitution: declaringClass + new type variables)
57
substitution = new Substitution() {
58                 public LookupEnvironment environment() {
59                     return parameterizedDeclaringClass.environment;
60                 }
61                 public boolean isRawSubstitution() {
62                     return !isStatic && parameterizedDeclaringClass.isRawSubstitution();
63                 }
64                 public TypeBinding substitute(TypeVariableBinding typeVariable) {
65                     // check this variable can be substituted given copied variables
66
if (typeVariable.rank < length && originalVariables[typeVariable.rank] == typeVariable) {
67                         return substitutedVariables[typeVariable.rank];
68                     }
69                     if (!isStatic)
70                         return parameterizedDeclaringClass.substitute(typeVariable);
71                     return typeVariable;
72                 }
73             };
74         
75             // initialize new variable bounds
76
for (int i = 0; i < length; i++) {
77                 TypeVariableBinding originalVariable = originalVariables[i];
78                 TypeVariableBinding substitutedVariable = substitutedVariables[i];
79                 TypeBinding substitutedSuperclass = Scope.substitute(substitution, originalVariable.superclass);
80                 ReferenceBinding[] substitutedInterfaces = Scope.substitute(substitution, originalVariable.superInterfaces);
81                 if (originalVariable.firstBound != null) {
82                     substitutedVariable.firstBound = originalVariable.firstBound == originalVariable.superclass
83                         ? substitutedSuperclass // could be array type or interface
84
: substitutedInterfaces[0];
85                 }
86                 switch (substitutedSuperclass.kind()) {
87                     case Binding.ARRAY_TYPE :
88                         substitutedVariable.superclass = parameterizedDeclaringClass.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null);
89                         substitutedVariable.superInterfaces = substitutedInterfaces;
90                         break;
91                     default:
92                         if (substitutedSuperclass.isInterface()) {
93                             substitutedVariable.superclass = parameterizedDeclaringClass.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null);
94                             int interfaceCount = substitutedInterfaces.length;
95                             System.arraycopy(substitutedInterfaces, 0, substitutedInterfaces = new ReferenceBinding[interfaceCount+1], 1, interfaceCount);
96                             substitutedInterfaces[0] = (ReferenceBinding) substitutedSuperclass;
97                             substitutedVariable.superInterfaces = substitutedInterfaces;
98                         } else {
99                             substitutedVariable.superclass = (ReferenceBinding) substitutedSuperclass; // typeVar was extending other typeVar which got substituted with interface
100
substitutedVariable.superInterfaces = substitutedInterfaces;
101                         }
102                 }
103             }
104         }
105         if (substitution != null) {
106             this.returnType = Scope.substitute(substitution, this.returnType);
107             this.parameters = Scope.substitute(substitution, this.parameters);
108             this.thrownExceptions = Scope.substitute(substitution, this.thrownExceptions);
109         }
110     }
111     
112     /**
113      * Create method of parameterized type, substituting original parameters/exception/return type with type arguments.
114      * This is a CODE ASSIST method ONLY.
115      */

116     public ParameterizedMethodBinding(final ReferenceBinding declaringClass, MethodBinding originalMethod, char[][] alternateParamaterNames, final LookupEnvironment environment) {
117
118         super(
119                 originalMethod.modifiers,
120                 originalMethod.selector,
121                  originalMethod.returnType,
122                 originalMethod.parameters,
123                 originalMethod.thrownExceptions,
124                 declaringClass);
125         this.originalMethod = originalMethod;
126         this.tagBits = originalMethod.tagBits;
127         
128         final TypeVariableBinding[] originalVariables = originalMethod.typeVariables;
129         Substitution substitution = null;
130         final int length = originalVariables.length;
131         if (length == 0) {
132             this.typeVariables = Binding.NO_TYPE_VARIABLES;
133         } else {
134             // at least fix up the declaringElement binding + bound substitution if non static
135
final TypeVariableBinding[] substitutedVariables = new TypeVariableBinding[length];
136             for (int i = 0; i < length; i++) { // copy original type variable to relocate
137
TypeVariableBinding originalVariable = originalVariables[i];
138                 substitutedVariables[i] = new TypeVariableBinding(
139                         alternateParamaterNames == null ?
140                                 originalVariable.sourceName :
141                                 alternateParamaterNames[i],
142                             this,
143                             originalVariable.rank);
144             }
145             this.typeVariables = substitutedVariables;
146             
147             // need to substitute old var refs with new ones (double substitution: declaringClass + new type variables)
148
substitution = new Substitution() {
149                 public LookupEnvironment environment() {
150                     return environment;
151                 }
152                 public boolean isRawSubstitution() {
153                     return false;
154                 }
155                 public TypeBinding substitute(TypeVariableBinding typeVariable) {
156                     // check this variable can be substituted given copied variables
157
if (typeVariable.rank < length && originalVariables[typeVariable.rank] == typeVariable) {
158                         return substitutedVariables[typeVariable.rank];
159                     }
160                     return typeVariable;
161                 }
162             };
163         
164             // initialize new variable bounds
165
for (int i = 0; i < length; i++) {
166                 TypeVariableBinding originalVariable = originalVariables[i];
167                 TypeVariableBinding substitutedVariable = substitutedVariables[i];
168                 TypeBinding substitutedSuperclass = Scope.substitute(substitution, originalVariable.superclass);
169                 ReferenceBinding[] substitutedInterfaces = Scope.substitute(substitution, originalVariable.superInterfaces);
170                 if (originalVariable.firstBound != null) {
171                     substitutedVariable.firstBound = originalVariable.firstBound == originalVariable.superclass
172                         ? substitutedSuperclass // could be array type or interface
173
: substitutedInterfaces[0];
174                 }
175                 switch (substitutedSuperclass.kind()) {
176                     case Binding.ARRAY_TYPE :
177                         substitutedVariable.superclass = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null);
178                         substitutedVariable.superInterfaces = substitutedInterfaces;
179                         break;
180                     default:
181                         if (substitutedSuperclass.isInterface()) {
182                             substitutedVariable.superclass = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null);
183                             int interfaceCount = substitutedInterfaces.length;
184                             System.arraycopy(substitutedInterfaces, 0, substitutedInterfaces = new ReferenceBinding[interfaceCount+1], 1, interfaceCount);
185                             substitutedInterfaces[0] = (ReferenceBinding) substitutedSuperclass;
186                             substitutedVariable.superInterfaces = substitutedInterfaces;
187                         } else {
188                             substitutedVariable.superclass = (ReferenceBinding) substitutedSuperclass; // typeVar was extending other typeVar which got substituted with interface
189
substitutedVariable.superInterfaces = substitutedInterfaces;
190                         }
191                 }
192             }
193         }
194         if (substitution != null) {
195             this.returnType = Scope.substitute(substitution, this.returnType);
196             this.parameters = Scope.substitute(substitution, this.parameters);
197             this.thrownExceptions = Scope.substitute(substitution, this.thrownExceptions);
198         }
199     }
200
201     public ParameterizedMethodBinding() {
202         // no init
203
}
204
205     /**
206      * The type of x.getClass() is substituted from 'Class<? extends Object>' into: 'Class<? extends raw(X)>
207      */

208     public static ParameterizedMethodBinding instantiateGetClass(TypeBinding receiverType, MethodBinding originalMethod, Scope scope) {
209         ParameterizedMethodBinding method = new ParameterizedMethodBinding();
210         method.modifiers = originalMethod.modifiers;
211         method.selector = originalMethod.selector;
212         method.declaringClass = originalMethod.declaringClass;
213         method.typeVariables = Binding.NO_TYPE_VARIABLES;
214         method.originalMethod = originalMethod;
215         method.parameters = originalMethod.parameters;
216         method.thrownExceptions = originalMethod.thrownExceptions;
217         ReferenceBinding genericClassType = scope.getJavaLangClass();
218         LookupEnvironment environment = scope.environment();
219         TypeBinding rawType = environment.convertToRawType(receiverType.erasure());
220         method.returnType = environment.createParameterizedType(
221             genericClassType,
222             new TypeBinding[] { environment.createWildcard(genericClassType, 0, rawType, null /*no extra bound*/, Wildcard.EXTENDS) },
223             null);
224         return method;
225     }
226
227     /**
228      * Returns true if some parameters got substituted.
229      */

230     public boolean hasSubstitutedParameters() {
231         return this.parameters != originalMethod.parameters;
232     }
233
234     /**
235      * Returns true if the return type got substituted.
236      */

237     public boolean hasSubstitutedReturnType() {
238         return this.returnType != originalMethod.returnType;
239     }
240
241     /**
242      * Returns the original method (as opposed to parameterized instances)
243      */

244     public MethodBinding original() {
245         return this.originalMethod.original();
246     }
247 }
248
Popular Tags