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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
12 package net.sourceforge.phpdt.core.dom;
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;
27 * Internal implementation of method bindings.
29 class MethodBinding implements IMethodBinding {
31 private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
32 Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED | Modifier.NATIVE |
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;
40 private ITypeBinding declaringClass;
41 private ITypeBinding returnType;
43 private ITypeBinding[] typeParameters;
44 private ITypeBinding[] typeArguments;
45 private IAnnotationBinding[] annotations;
46 private IAnnotationBinding[][] parameterAnnotations;
48 MethodBinding(BindingResolver resolver, net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding binding) {
49 this.resolver = resolver;
50 this.binding = binding;
53 public boolean isAnnotationMember() {
54 return getDeclaringClass().isAnnotation();
58 * @see IMethodBinding#isConstructor()
60 public boolean isConstructor() {
61 return this.binding.isConstructor();
65 * @see IMethodBinding#isDefaultConstructor()
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()) {
75 return (this.binding.modifiers & ExtraCompilerModifiers.AccIsDefaultConstructor) != 0;
77 if (declaringClassBinding.isBinaryBinding()) {
80 return (this.binding.modifiers & ExtraCompilerModifiers.AccIsDefaultConstructor) != 0;
84 * @see IBinding#getName()
86 public String getName() {
88 if (this.binding.isConstructor()) {
89 name = this.getDeclaringClass().getName();
91 name = new String(this.binding.selector);
97 public IAnnotationBinding[] getAnnotations() {
98 if (this.annotations != null) {
99 return this.annotations;
101 net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations = this.binding.getAnnotations();
102 int length = internalAnnotations == null ? 0 : internalAnnotations.length;
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) {
112 tempAnnotations[convertedAnnotationCount++] = annotationInstance;
114 if (convertedAnnotationCount != length) {
115 if (convertedAnnotationCount == 0) {
116 return this.annotations = AnnotationBinding.NoAnnotations;
118 System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount);
120 return this.annotations = tempAnnotations;
122 return this.annotations = AnnotationBinding.NoAnnotations;
126 * @see IMethodBinding#getDeclaringClass()
128 public ITypeBinding getDeclaringClass() {
129 if (this.declaringClass == null) {
130 this.declaringClass = this.resolver.getTypeBinding(this.binding.declaringClass);
132 return declaringClass;
135 public IAnnotationBinding[] getParameterAnnotations(int index) {
136 if (getParameterTypes() == NO_TYPE_BINDINGS) {
137 return AnnotationBinding.NoAnnotations;
139 if (this.parameterAnnotations != null) {
140 return this.parameterAnnotations[index];
142 net.sourceforge.phpdt.internal.compiler.lookup.AnnotationBinding[][] bindingAnnotations = this.binding.getParameterAnnotations();
143 if (bindingAnnotations == null) return AnnotationBinding.NoAnnotations;
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;
157 domAnnotations[i][j] = domAnnotation;
160 this.parameterAnnotations = domAnnotations;
162 return this.parameterAnnotations[index];
166 * @see IMethodBinding#getParameterTypes()
168 public ITypeBinding[] getParameterTypes() {
169 if (this.parameterTypes != null) {
170 return parameterTypes;
172 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding[] parameters = this.binding.parameters;
173 int length = parameters == null ? 0 : parameters.length;
175 return this.parameterTypes = NO_TYPE_BINDINGS;
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;
185 paramTypes[i] = typeBinding;
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;
195 return this.parameterTypes = paramTypes;
200 * @see IMethodBinding#getReturnType()
202 public ITypeBinding getReturnType() {
203 if (this.returnType == null) {
204 this.returnType = this.resolver.getTypeBinding(this.binding.returnType);
206 return this.returnType;
209 public Object getDefaultValue() {
210 if (isAnnotationMember())
211 return MemberValuePairBinding.buildDOMValue(this.binding.getDefaultValue(), this.resolver);
216 * @see IMethodBinding#getExceptionTypes()
218 public ITypeBinding[] getExceptionTypes() {
219 if (this.exceptionTypes != null) {
220 return exceptionTypes;
222 net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding[] exceptions = this.binding.thrownExceptions;
223 int length = exceptions == null ? 0 : exceptions.length;
225 return this.exceptionTypes = NO_TYPE_BINDINGS;
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;
233 exTypes[i] = typeBinding;
235 return this.exceptionTypes = exTypes;
238 public IJavaElement getJavaElement() {
239 JavaElement element = getUnresolvedJavaElement();
242 return element.resolved(this.binding);
245 private JavaElement getUnresolvedJavaElement() {
246 if (!(this.resolver instanceof DefaultBindingResolver)) return null;
248 DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
249 return Util.getUnresolvedJavaElement(
251 defaultBindingResolver.workingCopyOwner,
252 defaultBindingResolver.getBindingsToNodesMap());
256 * @see IBinding#getKind()
258 public int getKind() {
259 return IBinding.METHOD;
263 * @see IBinding#getModifiers()
265 public int getModifiers() {
266 return this.binding.getAccessFlags() & VALID_MODIFIERS;
270 * @see IBinding#isDeprecated()
272 public boolean isDeprecated() {
273 return this.binding.isDeprecated();
277 * @see IBinding#isRecovered()
279 public boolean isRecovered() {
284 * @see IBinding#isSynthetic()
286 public boolean isSynthetic() {
287 return this.binding.isSynthetic();
291 * @see org.eclipse.jdt.core.dom.IMethodBinding#isVarargs()
294 public boolean isVarargs() {
295 return this.binding.isVarargs();
299 * @see IBinding#getKey()
301 public String getKey() {
302 if (this.key == null) {
303 this.key = new String(this.binding.computeUniqueKey());
309 * @see IBinding#isEqualTo(IBinding)
312 public boolean isEqualTo(IBinding other) {
314 // identical binding - equal (key or no key)
318 // other binding missing
321 if (!(other instanceof MethodBinding)) {
324 net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding otherBinding = ((MethodBinding) other).binding;
325 return BindingComparator.isEqual(this.binding, otherBinding);
329 * @see org.eclipse.jdt.core.dom.IMethodBinding#getTypeParameters()
331 public ITypeBinding[] getTypeParameters() {
332 if (this.typeParameters != null) {
333 return this.typeParameters;
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;
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;
346 tParameters[i] = typeBinding;
348 return this.typeParameters = tParameters;
352 * @see org.eclipse.jdt.core.dom.IMethodBinding#isGenericMethod()
355 public boolean isGenericMethod() {
356 // equivalent to return getTypeParameters().length > 0;
357 if (this.typeParameters != null) {
358 return this.typeParameters.length > 0;
360 TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
361 return (typeVariableBindings != null && typeVariableBindings.length > 0);
365 * @see org.eclipse.jdt.core.dom.IMethodBinding#getTypeArguments()
367 public ITypeBinding[] getTypeArguments() {
368 if (this.typeArguments != null) {
369 return this.typeArguments;
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;
383 tArguments[i] = typeBinding;
385 return this.typeArguments = tArguments;
388 return this.typeArguments = NO_TYPE_BINDINGS;
392 * @see org.eclipse.jdt.core.dom.IMethodBinding#isParameterizedMethod()
394 public boolean isParameterizedMethod() {
395 return (this.binding instanceof ParameterizedGenericMethodBinding)
396 && !((ParameterizedGenericMethodBinding) this.binding).isRaw;
400 * @see org.eclipse.jdt.core.dom.IMethodBinding#isRawMethod()
402 public boolean isRawMethod() {
403 return (this.binding instanceof ParameterizedGenericMethodBinding)
404 && ((ParameterizedGenericMethodBinding) this.binding).isRaw;
407 public boolean isSubsignature(IMethodBinding otherMethod) {
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
420 * @see org.eclipse.jdt.core.dom.IMethodBinding#getMethodDeclaration()
422 public IMethodBinding getMethodDeclaration() {
423 return this.resolver.getMethodBinding(this.binding.original());
427 * @see IMethodBinding#overrides(IMethodBinding)
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);
436 * For debugging purpose only.
437 * @see java.lang.Object#toString()
439 public String toString() {
440 return this.binding.toString();