KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > apt > model > ExecutableElementImpl


1 /*******************************************************************************
2  * Copyright (c) 2005, 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.compiler.apt.model;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Collections JavaDoc;
15 import java.util.List JavaDoc;
16 import java.util.Set JavaDoc;
17
18 import javax.lang.model.element.AnnotationValue;
19 import javax.lang.model.element.Element;
20 import javax.lang.model.element.ElementKind;
21 import javax.lang.model.element.ElementVisitor;
22 import javax.lang.model.element.ExecutableElement;
23 import javax.lang.model.element.Modifier;
24 import javax.lang.model.element.Name;
25 import javax.lang.model.element.PackageElement;
26 import javax.lang.model.element.TypeElement;
27 import javax.lang.model.element.TypeParameterElement;
28 import javax.lang.model.element.VariableElement;
29 import javax.lang.model.type.TypeMirror;
30
31 import org.eclipse.jdt.core.compiler.CharOperation;
32 import org.eclipse.jdt.internal.compiler.apt.dispatch.BaseProcessingEnvImpl;
33 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
34 import org.eclipse.jdt.internal.compiler.ast.Argument;
35 import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
36 import org.eclipse.jdt.internal.compiler.lookup.AnnotationHolder;
37 import org.eclipse.jdt.internal.compiler.lookup.BinaryLocalVariableBinding;
38 import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
39 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
40 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
41 import org.eclipse.jdt.internal.compiler.lookup.MethodVerifier;
42 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
43 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
44 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
45 import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
46
47 public class ExecutableElementImpl extends ElementImpl implements
48         ExecutableElement {
49     
50     private Name _name = null;
51     
52     /* package */ ExecutableElementImpl(BaseProcessingEnvImpl env, MethodBinding binding) {
53         super(env, binding);
54     }
55
56     @Override JavaDoc
57     public <R, P> R accept(ElementVisitor<R, P> v, P p)
58     {
59         return v.visitExecutable(this, p);
60     }
61
62     @Override JavaDoc
63     protected AnnotationBinding[] getAnnotationBindings()
64     {
65         return ((MethodBinding)_binding).getAnnotations();
66     }
67
68     @Override JavaDoc
69     public AnnotationValue getDefaultValue() {
70         MethodBinding binding = (MethodBinding)_binding;
71         Object JavaDoc defaultValue = binding.getDefaultValue();
72         if (defaultValue != null) return new AnnotationValueImpl(_env, defaultValue, binding.returnType);
73         return null;
74     }
75     
76     @Override JavaDoc
77     public List JavaDoc<? extends Element> getEnclosedElements() {
78         return Collections.emptyList();
79     }
80
81     @Override JavaDoc
82     public Element getEnclosingElement() {
83         MethodBinding binding = (MethodBinding)_binding;
84         if (null == binding.declaringClass) {
85             return null;
86         }
87         return _env.getFactory().newElement(binding.declaringClass);
88     }
89
90     @Override JavaDoc
91     public String JavaDoc getFileName() {
92         ReferenceBinding dc = ((MethodBinding)_binding).declaringClass;
93         char[] name = dc.getFileName();
94         if (name == null)
95             return null;
96         return new String JavaDoc(name);
97     }
98
99     @Override JavaDoc
100     public ElementKind getKind() {
101         MethodBinding binding = (MethodBinding)_binding;
102         if (binding.isConstructor()) {
103             return ElementKind.CONSTRUCTOR;
104         }
105         else if (CharOperation.equals(binding.selector, TypeConstants.CLINIT)) {
106             return ElementKind.STATIC_INIT;
107         }
108         else if (CharOperation.equals(binding.selector, TypeConstants.INIT)) {
109             return ElementKind.INSTANCE_INIT;
110         }
111         else {
112             return ElementKind.METHOD;
113         }
114     }
115
116     @Override JavaDoc
117     public Set JavaDoc<Modifier> getModifiers() {
118         MethodBinding binding = (MethodBinding)_binding;
119         return Factory.getModifiers(binding.modifiers, getKind());
120     }
121
122     @Override JavaDoc
123     PackageElement getPackage()
124     {
125         MethodBinding binding = (MethodBinding)_binding;
126         if (null == binding.declaringClass) {
127             return null;
128         }
129         return _env.getFactory().newPackageElement(binding.declaringClass.fPackage);
130     }
131
132     @Override JavaDoc
133     public List JavaDoc<? extends VariableElement> getParameters() {
134         MethodBinding binding = (MethodBinding)_binding;
135         int length = binding.parameters == null ? 0 : binding.parameters.length;
136         if (0 != length) {
137             AbstractMethodDeclaration methodDeclaration = binding.sourceMethod();
138             List JavaDoc<VariableElement> params = new ArrayList JavaDoc<VariableElement>(length);
139             if (methodDeclaration != null) {
140                 for (Argument argument : methodDeclaration.arguments) {
141                     VariableElement param = new VariableElementImpl(_env, argument.binding);
142                     params.add(param);
143                 }
144             } else {
145                 // binary method
146
boolean isEnumConstructor = binding.isConstructor()
147                         && binding.declaringClass.isEnum()
148                         && binding.declaringClass.isBinaryBinding()
149                         && ((binding.modifiers & ExtraCompilerModifiers.AccGenericSignature) == 0);
150                 AnnotationBinding[][] parameterAnnotationBindings = null;
151                 AnnotationHolder annotationHolder = binding.declaringClass.retrieveAnnotationHolder(binding, false);
152                 if (annotationHolder != null) {
153                     parameterAnnotationBindings = annotationHolder.getParameterAnnotations();
154                 }
155                 // we need to filter the synthetic arguments
156
if (isEnumConstructor) {
157                     if (length == 2) {
158                         // the two arguments are only the two synthetic arguments
159
return Collections.emptyList();
160                     }
161                     for (int i = 2; i < length; i++) {
162                         TypeBinding typeBinding = binding.parameters[i];
163                         StringBuilder JavaDoc builder = new StringBuilder JavaDoc("arg");//$NON-NLS-1$
164
builder.append(i - 2);
165                         VariableElement param = new VariableElementImpl(_env,
166                                 new BinaryLocalVariableBinding(
167                                         String.valueOf(builder).toCharArray(),
168                                         typeBinding,
169                                         0,
170                                         null));
171                         params.add(param);
172                     }
173                 } else {
174                     int i = 0;
175                     for (TypeBinding typeBinding : binding.parameters) {
176                         StringBuilder JavaDoc builder = new StringBuilder JavaDoc("arg");//$NON-NLS-1$
177
builder.append(i);
178                         VariableElement param = new VariableElementImpl(_env,
179                                 new BinaryLocalVariableBinding(
180                                         String.valueOf(builder).toCharArray(),
181                                         typeBinding,
182                                         0,
183                                         parameterAnnotationBindings != null ? parameterAnnotationBindings[i] : null));
184                         params.add(param);
185                         i++;
186                     }
187                 }
188             }
189             return Collections.unmodifiableList(params);
190         }
191         return Collections.emptyList();
192     }
193
194     @Override JavaDoc
195     public TypeMirror getReturnType() {
196         MethodBinding binding = (MethodBinding)_binding;
197         if (binding.returnType == null) {
198             return null;
199         }
200         else return _env.getFactory().newTypeMirror(binding.returnType);
201     }
202
203     @Override JavaDoc
204     public Name getSimpleName() {
205         MethodBinding binding = (MethodBinding)_binding;
206         if (_name == null) {
207             _name = new NameImpl(binding.selector);
208         }
209         return _name;
210     }
211     
212     @Override JavaDoc
213     public List JavaDoc<? extends TypeMirror> getThrownTypes() {
214         MethodBinding binding = (MethodBinding)_binding;
215         if (binding.thrownExceptions.length == 0) {
216             return Collections.emptyList();
217         }
218         List JavaDoc<TypeMirror> list = new ArrayList JavaDoc<TypeMirror>(binding.thrownExceptions.length);
219         for (ReferenceBinding exception : binding.thrownExceptions) {
220             list.add(_env.getFactory().newTypeMirror(exception));
221         }
222         return list;
223     }
224
225     @Override JavaDoc
226     public List JavaDoc<? extends TypeParameterElement> getTypeParameters() {
227         MethodBinding binding = (MethodBinding)_binding;
228         TypeVariableBinding[] variables = binding.typeVariables();
229         if (variables.length == 0) {
230             return Collections.emptyList();
231         }
232         List JavaDoc<TypeParameterElement> params = new ArrayList JavaDoc<TypeParameterElement>(variables.length);
233         for (TypeVariableBinding variable : variables) {
234             params.add(_env.getFactory().newTypeParameterElement(variable, this));
235         }
236         return Collections.unmodifiableList(params);
237     }
238
239     @Override JavaDoc
240     public boolean hides(Element hidden)
241     {
242         if (!(hidden instanceof ExecutableElementImpl)) {
243             return false;
244         }
245         MethodBinding hiderBinding = (MethodBinding)_binding;
246         MethodBinding hiddenBinding = (MethodBinding)((ExecutableElementImpl)hidden)._binding;
247         if (hiderBinding == hiddenBinding) {
248             return false;
249         }
250         if (hiddenBinding.isPrivate()) {
251             return false;
252         }
253         // See JLS 8.4.8: hiding only applies to static methods
254
if (!hiderBinding.isStatic() || !hiddenBinding.isStatic()) {
255             return false;
256         }
257         // check names
258
if (!CharOperation.equals(hiddenBinding.selector, hiderBinding.selector)) {
259             return false;
260         }
261         // check parameters
262
if (!_env.getLookupEnvironment().methodVerifier().doesMethodOverride(hiderBinding, hiddenBinding)) {
263             return false;
264         }
265         return null != hiderBinding.declaringClass.findSuperTypeWithSameErasure(hiddenBinding.declaringClass);
266     }
267
268     @Override JavaDoc
269     public boolean isVarArgs() {
270         return ((MethodBinding) _binding).isVarargs();
271     }
272
273     /**
274      * Return true if this method overrides {@code overridden} in the context of {@code type}. For
275      * instance, consider
276      * <pre>
277      * interface A { void f(); }
278      * class B { void f() {} }
279      * class C extends B implements I { }
280      * </pre>
281      * In the context of B, B.f() does not override A.f(); they are unrelated. But in the context of
282      * C, B.f() does override A.f(). That is, the copy of B.f() that C inherits overrides A.f().
283      * This is equivalent to considering two questions: first, does C inherit B.f(); if so, does
284      * the inherited C.f() override A.f(). If B.f() were private, for instance, then in the context
285      * of C it would still not override A.f().
286      *
287      * @see javax.lang.model.util.Elements#overrides(ExecutableElement, ExecutableElement, TypeElement)
288      * @jls3 8.4.8 Inheritance, Overriding, and Hiding
289      * @jls3 9.4.1 Inheritance and Overriding
290      */

291     public boolean overrides(ExecutableElement overridden, TypeElement type)
292     {
293         MethodBinding overriddenBinding = (MethodBinding)((ExecutableElementImpl) overridden)._binding;
294         ReferenceBinding overriderContext = (ReferenceBinding)((TypeElementImpl)type)._binding;
295         if ((MethodBinding)_binding == overriddenBinding)
296             return false;
297         if (overriddenBinding.isPrivate()) {
298             return false;
299         }
300         char[] selector = ((MethodBinding)_binding).selector;
301         if (!CharOperation.equals(selector, overriddenBinding.selector))
302             return false;
303         
304         // Construct a binding to the equivalent of this (the overrider) as it would be inherited by 'type'.
305
// Can only do this if 'type' is descended from the overrider.
306
// Second clause of the AND is required to match a peculiar javac behavior.
307
if (null == overriderContext.findSuperTypeWithSameErasure(((MethodBinding)_binding).declaringClass) &&
308                 null == ((MethodBinding)_binding).declaringClass.findSuperTypeWithSameErasure(overriderContext)) {
309             return false;
310         }
311         MethodBinding overriderBinding = new MethodBinding((MethodBinding)_binding, overriderContext);
312         if (overriderBinding.isPrivate()) {
313             // a private method can never override another method. The other method would either be
314
// private itself, in which case it would not be visible; or this would be a restriction
315
// of access, which is a compile-time error.
316
return false;
317         }
318         
319         TypeBinding match = overriderBinding.declaringClass.findSuperTypeWithSameErasure(overriddenBinding.declaringClass);
320         if (!(match instanceof ReferenceBinding)) return false;
321
322         org.eclipse.jdt.internal.compiler.lookup.MethodBinding[] superMethods = ((ReferenceBinding)match).getMethods(selector);
323         for (int i = 0, length = superMethods.length; i < length; i++) {
324             if (superMethods[i].original() == overriddenBinding) {
325                 LookupEnvironment lookupEnvironment = _env.getLookupEnvironment();
326                 if (lookupEnvironment == null) return false;
327                 MethodVerifier methodVerifier = lookupEnvironment.methodVerifier();
328                 org.eclipse.jdt.internal.compiler.lookup.MethodBinding superMethod = superMethods[i];
329                 return !superMethod.isPrivate()
330                     && !(superMethod.isDefault() && (superMethod.declaringClass.getPackage()) != overriderBinding.declaringClass.getPackage())
331                     && methodVerifier.doesMethodOverride(overriderBinding, superMethod);
332             }
333         }
334         return false;
335     }
336
337 }
338
Popular Tags