removed unused private methods.
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / MethodBinding.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 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
12 package net.sourceforge.phpdt.core.dom;
13
14 import net.sourceforge.phpdt.core.IJavaElement;
15 import net.sourceforge.phpdt.internal.compiler.lookup.ExtraCompilerModifiers;
16 import net.sourceforge.phpdt.internal.compiler.lookup.LookupEnvironment;
17 import net.sourceforge.phpdt.internal.compiler.lookup.ParameterizedGenericMethodBinding;
18 import net.sourceforge.phpdt.internal.compiler.lookup.RawTypeBinding;
19 import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
21 import net.sourceforge.phpdt.internal.compiler.lookup.TypeVariableBinding;
22 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
23 import net.sourceforge.phpdt.internal.core.JavaElement;
24 import net.sourceforge.phpdt.internal.core.util.Util;
25
26 /**
27  * Internal implementation of method bindings.
28  */
29 class MethodBinding implements IMethodBinding {
30
31         private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
32                 Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED | Modifier.NATIVE |
33                 Modifier.STRICTFP;
34         private static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0];
35         private net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding binding;
36         private BindingResolver resolver;
37         private ITypeBinding[] parameterTypes;
38         private ITypeBinding[] exceptionTypes;
39         private String name;
40         private ITypeBinding declaringClass;
41         private ITypeBinding returnType;
42         private String key;
43         private ITypeBinding[] typeParameters;
44         private ITypeBinding[] typeArguments;
45         private IAnnotationBinding[] annotations;
46         private IAnnotationBinding[][] parameterAnnotations;
47
48         MethodBinding(BindingResolver resolver, net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding binding) {
49                 this.resolver = resolver;
50                 this.binding = binding;
51         }
52
53         public boolean isAnnotationMember() {
54                 return getDeclaringClass().isAnnotation();
55         }
56
57         /**
58          * @see IMethodBinding#isConstructor()
59          */
60         public boolean isConstructor() {
61                 return this.binding.isConstructor();
62         }
63
64         /**
65          * @see IMethodBinding#isDefaultConstructor()
66          * @since 3.0
67          */
68         public boolean isDefaultConstructor() {
69                 final ReferenceBinding declaringClassBinding = this.binding.declaringClass;
70                 if (declaringClassBinding.isRawType()) {
71                         RawTypeBinding rawTypeBinding = (RawTypeBinding) declaringClassBinding;
72                         if (rawTypeBinding.genericType().isBinaryBinding()) {
73                                 return false;
74                         }
75                         return (this.binding.modifiers & ExtraCompilerModifiers.AccIsDefaultConstructor) != 0;
76                 }
77                 if (declaringClassBinding.isBinaryBinding()) {
78                         return false;
79                 }
80                 return (this.binding.modifiers & ExtraCompilerModifiers.AccIsDefaultConstructor) != 0;
81         }
82
83         /**
84          * @see IBinding#getName()
85          */
86         public String getName() {
87                 if (name == null) {
88                         if (this.binding.isConstructor()) {
89                                 name = this.getDeclaringClass().getName();
90                         } else {
91                                 name = new String(this.binding.selector);
92                         }
93                 }
94                 return name;
95         }
96
97         public IAnnotationBinding[] getAnnotations() {
98                 if (this.annotations != null) {
99                         return this.annotations;
100                 }
101                 net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations = this.binding.getAnnotations();
102                 int length = internalAnnotations == null ? 0 : internalAnnotations.length;
103                 if (length != 0) {
104                         IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length];
105                         int convertedAnnotationCount = 0;
106                         for (int i = 0; i < length; i++) {
107                                 net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
108                                 final IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
109                                 if (annotationInstance == null) {
110                                         continue;
111                                 }
112                                 tempAnnotations[convertedAnnotationCount++] = annotationInstance;
113                         }
114                         if (convertedAnnotationCount != length) {
115                                 if (convertedAnnotationCount == 0) {
116                                         return this.annotations = AnnotationBinding.NoAnnotations;
117                                 }
118                                 System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount);
119                         }
120                         return this.annotations = tempAnnotations;
121                 }
122                 return this.annotations = AnnotationBinding.NoAnnotations;
123         }
124
125         /**
126          * @see IMethodBinding#getDeclaringClass()
127          */
128         public ITypeBinding getDeclaringClass() {
129                 if (this.declaringClass == null) {
130                         this.declaringClass = this.resolver.getTypeBinding(this.binding.declaringClass);
131                 }
132                 return declaringClass;
133         }
134
135         public IAnnotationBinding[] getParameterAnnotations(int index) {
136                 if (getParameterTypes() == NO_TYPE_BINDINGS) {
137                         return AnnotationBinding.NoAnnotations;
138                 }
139                 if (this.parameterAnnotations != null) {
140                         return this.parameterAnnotations[index];
141                 }
142                 net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding[][] bindingAnnotations = this.binding.getParameterAnnotations();
143                 if (bindingAnnotations == null) return AnnotationBinding.NoAnnotations;
144
145                 int length = bindingAnnotations.length;
146                 IAnnotationBinding[][] domAnnotations = new IAnnotationBinding[length][];
147                 for (int i = 0; i < length; i++) {
148                         net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding[] paramBindingAnnotations = bindingAnnotations[i];
149                         int pLength = paramBindingAnnotations.length;
150                         domAnnotations[i] = new AnnotationBinding[pLength];
151                         for (int j=0; j<pLength; j++) {
152                                 IAnnotationBinding domAnnotation = this.resolver.getAnnotationInstance(paramBindingAnnotations[j]);
153                                 if (domAnnotation == null) {
154                                         domAnnotations[i] = AnnotationBinding.NoAnnotations;
155                                         break;
156                                 }
157                                 domAnnotations[i][j] = domAnnotation;
158                         }
159                 }
160                 this.parameterAnnotations = domAnnotations;
161                 
162                 return this.parameterAnnotations[index];
163         }
164
165         /**
166          * @see IMethodBinding#getParameterTypes()
167          */
168         public ITypeBinding[] getParameterTypes() {
169                 if (this.parameterTypes != null) {
170                         return parameterTypes;
171                 }
172                 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding[] parameters = this.binding.parameters;
173                 int length = parameters == null ? 0 : parameters.length;
174                 if (length == 0) {
175                         return this.parameterTypes = NO_TYPE_BINDINGS;
176                 } else {
177                         ITypeBinding[] paramTypes = new ITypeBinding[length];
178                         for (int i = 0; i < length; i++) {
179                                 final TypeBinding parameterBinding = parameters[i];
180                                 if (parameterBinding != null) {
181                                         ITypeBinding typeBinding = this.resolver.getTypeBinding(parameterBinding);
182                                         if (typeBinding == null) {
183                                                 return this.parameterTypes = NO_TYPE_BINDINGS;
184                                         }
185                                         paramTypes[i] = typeBinding;
186                                 } else {
187                                         // log error
188                                         StringBuffer message = new StringBuffer("Report method binding where a parameter is null:\n");  //$NON-NLS-1$
189                                         message.append(this.toString());
190                                         Util.log(new IllegalArgumentException(), message.toString());
191                                         // report no binding since one or more parameter has no binding
192                                         return this.parameterTypes = NO_TYPE_BINDINGS;
193                                 }
194                         }
195                         return this.parameterTypes = paramTypes;
196                 }
197         }
198
199         /**
200          * @see IMethodBinding#getReturnType()
201          */
202         public ITypeBinding getReturnType() {
203                 if (this.returnType == null) {
204                         this.returnType = this.resolver.getTypeBinding(this.binding.returnType);
205                 }
206                 return this.returnType;
207         }
208
209         public Object getDefaultValue() {
210                 if (isAnnotationMember())
211                         return MemberValuePairBinding.buildDOMValue(this.binding.getDefaultValue(), this.resolver);
212                 return null;
213         }
214
215         /**
216          * @see IMethodBinding#getExceptionTypes()
217          */
218         public ITypeBinding[] getExceptionTypes() {
219                 if (this.exceptionTypes != null) {
220                         return exceptionTypes;
221                 }
222                 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding[] exceptions = this.binding.thrownExceptions;
223                 int length = exceptions == null ? 0 : exceptions.length;
224                 if (length == 0) {
225                         return this.exceptionTypes = NO_TYPE_BINDINGS;
226                 }
227                 ITypeBinding[] exTypes = new ITypeBinding[length];
228                 for (int i = 0; i < length; i++) {
229                         ITypeBinding typeBinding = this.resolver.getTypeBinding(exceptions[i]);
230                         if (typeBinding == null) {
231                                 return this.exceptionTypes = NO_TYPE_BINDINGS;
232                         }
233                         exTypes[i] = typeBinding;
234                 }
235                 return this.exceptionTypes = exTypes;
236         }
237
238         public IJavaElement getJavaElement() {
239                 JavaElement element = getUnresolvedJavaElement();
240                 if (element == null)
241                         return null;
242                 return element.resolved(this.binding);
243         }
244
245         private JavaElement getUnresolvedJavaElement() {
246                 if (!(this.resolver instanceof DefaultBindingResolver)) return null;
247                 
248                 DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
249                 return Util.getUnresolvedJavaElement(
250                                 this.binding,
251                                 defaultBindingResolver.workingCopyOwner,
252                                 defaultBindingResolver.getBindingsToNodesMap());
253         }
254
255         /**
256          * @see IBinding#getKind()
257          */
258         public int getKind() {
259                 return IBinding.METHOD;
260         }
261
262         /**
263          * @see IBinding#getModifiers()
264          */
265         public int getModifiers() {
266                 return this.binding.getAccessFlags() & VALID_MODIFIERS;
267         }
268
269         /**
270          * @see IBinding#isDeprecated()
271          */
272         public boolean isDeprecated() {
273                 return this.binding.isDeprecated();
274         }
275
276         /**
277          * @see IBinding#isRecovered()
278          */
279         public boolean isRecovered() {
280                 return false;
281         }
282
283         /**
284          * @see IBinding#isSynthetic()
285          */
286         public boolean isSynthetic() {
287                 return this.binding.isSynthetic();
288         }
289
290         /**
291          * @see org.eclipse.jdt.core.dom.IMethodBinding#isVarargs()
292          * @since 3.1
293          */
294         public boolean isVarargs() {
295                 return this.binding.isVarargs();
296         }
297
298         /**
299          * @see IBinding#getKey()
300          */
301         public String getKey() {
302                 if (this.key == null) {
303                         this.key = new String(this.binding.computeUniqueKey());
304                 }
305                 return this.key;
306         }
307
308         /**
309          * @see IBinding#isEqualTo(IBinding)
310          * @since 3.1
311          */
312         public boolean isEqualTo(IBinding other) {
313                 if (other == this) {
314                         // identical binding - equal (key or no key)
315                         return true;
316                 }
317                 if (other == null) {
318                         // other binding missing
319                         return false;
320                 }
321                 if (!(other instanceof MethodBinding)) {
322                         return false;
323                 }
324                 net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding otherBinding = ((MethodBinding) other).binding;
325                 return BindingComparator.isEqual(this.binding, otherBinding);
326         }
327
328         /**
329          * @see org.eclipse.jdt.core.dom.IMethodBinding#getTypeParameters()
330          */
331         public ITypeBinding[] getTypeParameters() {
332                 if (this.typeParameters != null) {
333                         return this.typeParameters;
334                 }
335                 TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
336                 int typeVariableBindingsLength = typeVariableBindings == null ? 0 : typeVariableBindings.length;
337                 if (typeVariableBindingsLength == 0) {
338                         return this.typeParameters = NO_TYPE_BINDINGS;
339                 }
340                 ITypeBinding[] tParameters = new ITypeBinding[typeVariableBindingsLength];
341                 for (int i = 0; i < typeVariableBindingsLength; i++) {
342                         ITypeBinding typeBinding = this.resolver.getTypeBinding(typeVariableBindings[i]);
343                         if (typeBinding == null) {
344                                 return this.typeParameters = NO_TYPE_BINDINGS;
345                         }
346                         tParameters[i] = typeBinding;
347                 }
348                 return this.typeParameters = tParameters;
349         }
350
351         /**
352          * @see org.eclipse.jdt.core.dom.IMethodBinding#isGenericMethod()
353          * @since 3.1
354          */
355         public boolean isGenericMethod() {
356                 // equivalent to return getTypeParameters().length > 0;
357                 if (this.typeParameters != null) {
358                         return this.typeParameters.length > 0;
359                 }
360                 TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
361                 return (typeVariableBindings != null && typeVariableBindings.length > 0);
362         }
363
364         /**
365          * @see org.eclipse.jdt.core.dom.IMethodBinding#getTypeArguments()
366          */
367         public ITypeBinding[] getTypeArguments() {
368                 if (this.typeArguments != null) {
369                         return this.typeArguments;
370                 }
371
372                 if (this.binding instanceof ParameterizedGenericMethodBinding) {
373                         ParameterizedGenericMethodBinding genericMethodBinding = (ParameterizedGenericMethodBinding) this.binding;
374                         net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding[] typeArgumentsBindings = genericMethodBinding.typeArguments;
375                         int typeArgumentsLength = typeArgumentsBindings == null ? 0 : typeArgumentsBindings.length;
376                         if (typeArgumentsLength != 0) {
377                                 ITypeBinding[] tArguments = new ITypeBinding[typeArgumentsLength];
378                                 for (int i = 0; i < typeArgumentsLength; i++) {
379                                         ITypeBinding typeBinding = this.resolver.getTypeBinding(typeArgumentsBindings[i]);
380                                         if (typeBinding == null) {
381                                                 return this.typeArguments = NO_TYPE_BINDINGS;
382                                         }
383                                         tArguments[i] = typeBinding;
384                                 }
385                                 return this.typeArguments = tArguments;
386                         }
387                 }
388                 return this.typeArguments = NO_TYPE_BINDINGS;
389         }
390
391         /**
392          * @see org.eclipse.jdt.core.dom.IMethodBinding#isParameterizedMethod()
393          */
394         public boolean isParameterizedMethod() {
395                 return (this.binding instanceof ParameterizedGenericMethodBinding)
396                         && !((ParameterizedGenericMethodBinding) this.binding).isRaw;
397         }
398
399         /**
400          * @see org.eclipse.jdt.core.dom.IMethodBinding#isRawMethod()
401          */
402         public boolean isRawMethod() {
403                 return (this.binding instanceof ParameterizedGenericMethodBinding)
404                         && ((ParameterizedGenericMethodBinding) this.binding).isRaw;
405         }
406
407         public boolean isSubsignature(IMethodBinding otherMethod) {
408                 try {
409                         LookupEnvironment lookupEnvironment = this.resolver.lookupEnvironment();
410                         return lookupEnvironment != null
411                                 && lookupEnvironment.methodVerifier().isMethodSubsignature(this.binding, ((MethodBinding) otherMethod).binding);
412                 } catch (AbortCompilation e) {
413                         // don't surface internal exception to clients
414                         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
415                         return false;
416                 }
417         }
418
419         /**
420          * @see org.eclipse.jdt.core.dom.IMethodBinding#getMethodDeclaration()
421          */
422         public IMethodBinding getMethodDeclaration() {
423                 return this.resolver.getMethodBinding(this.binding.original());
424         }
425
426         /**
427          * @see IMethodBinding#overrides(IMethodBinding)
428          */
429         public boolean overrides(IMethodBinding otherMethod) {
430                         LookupEnvironment lookupEnvironment = this.resolver.lookupEnvironment();
431                         return lookupEnvironment != null
432                                 && lookupEnvironment.methodVerifier().doesMethodOverride(this.binding, ((MethodBinding) otherMethod).binding);
433         }
434
435         /**
436          * For debugging purpose only.
437          * @see java.lang.Object#toString()
438          */
439         public String toString() {
440                 return this.binding.toString();
441         }
442 }