EclipseJDT Source Viewer

Home|eclipse_jdt/src/org/eclipse/jdt/core/dom/VariableBinding.java
1/*******************************************************************************
2 * Copyright (c) 2000, 2021 IBM Corporation and others.
3 *
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
8 *
9 * SPDX-License-Identifier: EPL-2.0
10 *
11 * Contributors:
12 *     IBM Corporation - initial API and implementation
13 *     Stephan Herrmann - Contribution for
14 *                                Bug 429813 - [1.8][dom ast] IMethodBinding#getJavaElement() should return IMethod for lambda
15 *                                Bug 466308 - [hovering] Javadoc header for parameter is wrong with annotation-based null analysis
16 *******************************************************************************/
17
18package org.eclipse.jdt.core.dom;
19
20import org.eclipse.jdt.core.IJavaElement;
21import org.eclipse.jdt.core.JavaCore;
22import org.eclipse.jdt.core.util.IModifierConstants;
23import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
24import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
25import org.eclipse.jdt.internal.compiler.impl.Constant;
26import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
27import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
28import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
29import org.eclipse.jdt.internal.compiler.lookup.RecordComponentBinding;
30import org.eclipse.jdt.internal.compiler.lookup.TagBits;
31import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
32import org.eclipse.jdt.internal.core.JavaElement;
33import org.eclipse.jdt.internal.core.LocalVariable;
34import org.eclipse.jdt.internal.core.util.Util;
35
36/**
37 * Internal implementation of variable bindings.
38 */
39class VariableBinding implements IVariableBinding {
40
41    private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
42        Modifier.STATIC | Modifier.FINAL | Modifier.TRANSIENT | Modifier.VOLATILE;
43
44    private org.eclipse.jdt.internal.compiler.lookup.VariableBinding binding;
45    private ITypeBinding declaringClass;
46    private String key;
47    private String name;
48    private BindingResolver resolver;
49    private ITypeBinding type;
50    private IAnnotationBinding[] annotations;
51
52    VariableBinding(BindingResolver resolverorg.eclipse.jdt.internal.compiler.lookup.VariableBinding binding) {
53        this.resolver = resolver;
54        this.binding = binding;
55    }
56
57    @Override
58    public IAnnotationBinding[] getAnnotations() {
59        if (this.annotations != null) {
60            return this.annotations;
61        }
62        org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations = this.binding.getAnnotations();
63        int length = internalAnnotations == null ? 0 : internalAnnotations.length;
64        if (length != 0) {
65            IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length];
66            int convertedAnnotationCount = 0;
67            for (int i = 0i < lengthi++) {
68                org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
69                final IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
70                if (annotationInstance == null) {
71                    continue;
72                }
73                tempAnnotations[convertedAnnotationCount++] = annotationInstance;
74            }
75            if (convertedAnnotationCount != length) {
76                if (convertedAnnotationCount == 0) {
77                    return this.annotations = AnnotationBinding.NoAnnotations;
78                }
79                System.arraycopy(tempAnnotations0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0convertedAnnotationCount);
80            }
81            return this.annotations = tempAnnotations;
82        }
83        return this.annotations = AnnotationBinding.NoAnnotations;
84    }
85
86    @Override
87    public Object getConstantValue() {
88        Constant c = this.binding.constant();
89        if (c == null || c == Constant.NotAConstant) return null;
90        switch (c.typeID()) {
91            case TypeIds.T_boolean:
92                return Boolean.valueOf(c.booleanValue());
93            case TypeIds.T_byte:
94                return Byte.valueOf(c.byteValue());
95            case TypeIds.T_char:
96                return Character.valueOf(c.charValue());
97            case TypeIds.T_double:
98                return Double.valueOf(c.doubleValue());
99            case TypeIds.T_float:
100                return Float.valueOf(c.floatValue());
101            case TypeIds.T_int:
102                return Integer.valueOf(c.intValue());
103            case TypeIds.T_long:
104                return Long.valueOf(c.longValue());
105            case TypeIds.T_short:
106                return Short.valueOf(c.shortValue());
107            case TypeIds.T_JavaLangString:
108                return c.stringValue();
109        }
110        return null;
111    }
112
113    @Override
114    public ITypeBinding getDeclaringClass() {
115        if (isField()) {
116            if (this.declaringClass == null) {
117                FieldBinding fieldBinding = (FieldBinding) this.binding;
118                this.declaringClass = this.resolver.getTypeBinding(fieldBinding.declaringClass);
119            }
120            return this.declaringClass;
121        } else {
122            return null;
123        }
124    }
125
126    @Override
127    public IMethodBinding getDeclaringMethod() {
128        if (!isField()) {
129            ASTNode node = this.resolver.findDeclaringNode(this);
130            while (true) {
131                if (node == null) {
132                    if (this.binding instanceof LocalVariableBinding) {
133                        LocalVariableBinding localVariableBinding = (LocalVariableBinding) this.binding;
134                        org.eclipse.jdt.internal.compiler.lookup.MethodBinding enclosingMethod = localVariableBinding.getEnclosingMethod();
135                        if (enclosingMethod != null)
136                            return this.resolver.getMethodBinding(enclosingMethod);
137                    }
138                    return null;
139                }
140                switch(node.getNodeType()) {
141                    case ASTNode.INITIALIZER :
142                        return null;
143                    case ASTNode.METHOD_DECLARATION :
144                        MethodDeclaration methodDeclaration = (MethodDeclarationnode;
145                        return methodDeclaration.resolveBinding();
146                    case ASTNode.LAMBDA_EXPRESSION :
147                        LambdaExpression lambdaExpression = (LambdaExpressionnode;
148                        return lambdaExpression.resolveMethodBinding();
149                    default:
150                        node = node.getParent();
151                }
152            }
153        }
154        return null;
155    }
156
157    @Override
158    public IJavaElement getJavaElement() {
159        JavaElement element = getUnresolvedJavaElement();
160        if (element == null)
161            return null;
162        return element.resolved(this.binding);
163    }
164
165    @Override
166    public String getKey() {
167        if (this.key == null) {
168            this.key = new String(this.binding.computeUniqueKey());
169        }
170        return this.key;
171    }
172
173    @Override
174    public int getKind() {
175        return IBinding.VARIABLE;
176    }
177
178    @Override
179    public int getModifiers() {
180        if (isField()) {
181            return ((FieldBinding) this.binding).getAccessFlags() & VALID_MODIFIERS;
182        }
183        if (this.binding.isFinal()) {
184            return IModifierConstants.ACC_FINAL;
185        }
186        return Modifier.NONE;
187    }
188
189    @Override
190    public String getName() {
191        if (this.name == null) {
192            this.name = new String(this.binding.name);
193        }
194        return this.name;
195    }
196
197    @Override
198    public ITypeBinding getType() {
199        if (this.type == null) {
200            this.type = this.resolver.getTypeBinding(this.binding.type);
201        }
202        return this.type;
203    }
204
205    private JavaElement getUnresolvedJavaElement() {
206        if (JavaCore.getPlugin() == null) {
207            return null;
208        }
209        if (isField()) {
210            if (this.resolver instanceof DefaultBindingResolver) {
211                DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
212                if (!defaultBindingResolver.fromJavaProject) return null;
213                return Util.getUnresolvedJavaElement(
214                        (FieldBinding) this.binding,
215                        defaultBindingResolver.workingCopyOwner,
216                        defaultBindingResolver.getBindingsToNodesMap());
217            }
218            return null;
219        }else if (isRecordComponent()) {
220            if (this.resolver instanceof DefaultBindingResolver) {
221                DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
222                if (!defaultBindingResolver.fromJavaProject) return null;
223                return Util.getUnresolvedJavaElement(
224                        (RecordComponentBinding) this.binding,
225                        defaultBindingResolver.workingCopyOwner,
226                        defaultBindingResolver.getBindingsToNodesMap());
227            }
228            return null;
229        }
230        // local variable
231        if (!(this.resolver instanceof DefaultBindingResolver)) return null;
232        DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
233        if (!defaultBindingResolver.fromJavaProject) return null;
234        VariableDeclaration localVar = (VariableDeclarationdefaultBindingResolver.bindingsToAstNodes.get(this);
235        if (localVar == null) return null;
236        SimpleName localName = localVar.getName();
237        int nameStart = localName.getStartPosition();
238        int nameLength = localName.getLength();
239        int sourceStart;
240        int sourceLength;
241        int modifiers = 0;
242        if (localVar instanceof SingleVariableDeclaration) {
243            sourceStart = localVar.getStartPosition();
244            sourceLength = localVar.getLength();
245            final SingleVariableDeclaration singleVariableDeclaration = (SingleVariableDeclarationlocalVar;
246            modifiers = singleVariableDeclaration.getModifiers();
247        } else {
248            ASTNode node = localVar.getParent();
249            sourceStart = node.getStartPosition();
250            sourceLength = node.getLength();
251            VariableDeclarationFragment fragment = (VariableDeclarationFragmentlocalVar;
252            final ASTNode parent = fragment.getParent();
253            switch (parent.getNodeType()) {
254                case ASTNode.VARIABLE_DECLARATION_EXPRESSION :
255                    VariableDeclarationExpression expression = (VariableDeclarationExpressionparent;
256                    modifiers = expression.getModifiers();
257                    break;
258                case ASTNode.VARIABLE_DECLARATION_STATEMENT :
259                    VariableDeclarationStatement statement = (VariableDeclarationStatementparent;
260                    modifiers = statement.getModifiers();
261                    break;
262                case ASTNode.FIELD_DECLARATION :
263                    FieldDeclaration fieldDeclaration = (FieldDeclarationparent;
264                    modifiers = fieldDeclaration.getModifiers();
265                    break;
266            }
267        }
268        int sourceEnd = sourceStart+sourceLength-1;
269        char[] typeSig = this.binding.type.genericTypeSignature();
270        JavaElement parent = null;
271        IMethodBinding declaringMethod = getDeclaringMethod();
272        if (this.binding instanceof RecordComponentBinding) {
273            return null// TODO : SEE Bug 562736/ BUG 562637
274        }
275        final LocalVariableBinding localVariableBinding = (LocalVariableBinding) this.binding;
276        if (declaringMethod == null) {
277            ReferenceContext referenceContext = localVariableBinding.declaringScope.referenceContext();
278            if (referenceContext instanceof TypeDeclaration){
279                // Local variable is declared inside an initializer
280                TypeDeclaration typeDeclaration = (TypeDeclarationreferenceContext;
281                JavaElement typeHandle = null;
282                typeHandle = Util.getUnresolvedJavaElement(
283                    typeDeclaration.binding,
284                    defaultBindingResolver.workingCopyOwner,
285                    defaultBindingResolver.getBindingsToNodesMap());
286                parent = Util.getUnresolvedJavaElement(sourceStartsourceEndtypeHandle);
287            } else {
288                return null;
289            }
290        } else {
291            parent = (JavaElementdeclaringMethod.getJavaElement();
292        }
293        if (parent == null) return null;
294        return new LocalVariable(
295                parent,
296                localName.getIdentifier(),
297                sourceStart,
298                sourceEnd,
299                nameStart,
300                nameStart+nameLength-1,
301                new String(typeSig),
302                localVariableBinding.declaration.annotations,
303                modifiers,
304                (localVariableBinding.tagBits & TagBits.IsArgument) != 0);
305    }
306
307    @Override
308    public IVariableBinding getVariableDeclaration() {
309        if (isField()) {
310            FieldBinding fieldBinding = (FieldBinding) this.binding;
311            return this.resolver.getVariableBinding(fieldBinding.original());
312        }
313        return this;
314    }
315
316    @Override
317    public int getVariableId() {
318        return this.binding.id;
319    }
320
321    @Override
322    public boolean isParameter() {
323        return (this.binding.tagBits & TagBits.IsArgument) != 0;
324    }
325
326    @Override
327    public boolean isDeprecated() {
328        if (isField()) {
329            return ((FieldBinding) this.binding).isDeprecated();
330        }
331        return false;
332    }
333
334    @Override
335    public boolean isEnumConstant() {
336        return (this.binding.modifiers & ClassFileConstants.AccEnum) != 0;
337    }
338
339    @Override
340    public boolean isEqualTo(IBinding other) {
341        if (other == this) {
342            // identical binding - equal (key or no key)
343            return true;
344        }
345        if (other == null) {
346            // other binding missing
347            return false;
348        }
349        if (!(other instanceof VariableBinding)) {
350            return false;
351        }
352        org.eclipse.jdt.internal.compiler.lookup.VariableBinding otherBinding = ((VariableBindingother).binding;
353        if (this.binding instanceof FieldBinding) {
354            if (otherBinding instanceof FieldBinding) {
355                return BindingComparator.isEqual((FieldBinding) this.binding, (FieldBindingotherBinding);
356            } else {
357                return false;
358            }
359        } else {
360            if (BindingComparator.isEqual(this.bindingotherBinding)) {
361                IMethodBinding declaringMethod = getDeclaringMethod();
362                IMethodBinding otherDeclaringMethod = ((VariableBindingother).getDeclaringMethod();
363                if (declaringMethod == null) {
364                    if (otherDeclaringMethod != null) {
365                        return false;
366                    }
367                    return true;
368                }
369                return declaringMethod.isEqualTo(otherDeclaringMethod);
370            }
371            return false;
372        }
373    }
374
375    @Override
376    public boolean isField() {
377        return this.binding instanceof FieldBinding;
378    }
379
380    @Override
381    public boolean isSynthetic() {
382        if (isField()) {
383            return ((FieldBinding) this.binding).isSynthetic();
384        }
385        return false;
386    }
387
388    @Override
389    public boolean isRecovered() {
390        return false;
391    }
392
393    @Override
394    public boolean isEffectivelyFinal() {
395        return (!this.binding.isFinal() && this.binding.isEffectivelyFinal());
396    }
397
398    @Override
399    public boolean isRecordComponent() {
400        return this.binding instanceof RecordComponentBinding;
401    }
402
403    /*
404     * For debugging purpose only.
405     * @see java.lang.Object#toString()
406     */
407    @Override
408    public String toString() {
409        return this.binding.toString();
410    }
411
412}
413
MembersX
VariableBinding:resolver
VariableBinding:VALID_MODIFIERS
VariableBinding:getModifiers
VariableBinding:getUnresolvedJavaElement:Block:Block:parent
VariableBinding:getUnresolvedJavaElement:Block:parent
VariableBinding:getUnresolvedJavaElement:Block:Block:node
VariableBinding:getUnresolvedJavaElement:Block:Block:referenceContext
VariableBinding:isRecovered
VariableBinding:getDeclaringMethod:Block:Block:Block:Block:Block:localVariableBinding
VariableBinding:getUnresolvedJavaElement:Block:sourceEnd
VariableBinding:toString
VariableBinding:getVariableDeclaration:Block:Block:fieldBinding
VariableBinding:getUnresolvedJavaElement:Block:localName
VariableBinding:getUnresolvedJavaElement:Block:Block:fragment
VariableBinding:getUnresolvedJavaElement:Block:Block:Block:defaultBindingResolver
VariableBinding:isParameter
VariableBinding:getAnnotations:Block:Block:Block:annotationInstance
VariableBinding:getConstantValue
VariableBinding:binding
VariableBinding:getUnresolvedJavaElement
VariableBinding:isRecordComponent
VariableBinding:getJavaElement:Block:element
VariableBinding:getUnresolvedJavaElement:Block:localVar
VariableBinding:getAnnotations
VariableBinding:getName
VariableBinding:name
VariableBinding:getAnnotations:Block:Block:tempAnnotations
VariableBinding:isEqualTo:Block:Block:Block:declaringMethod
VariableBinding:isEqualTo:Block:Block:Block:otherDeclaringMethod
VariableBinding:getKey
VariableBinding:getUnresolvedJavaElement:Block:Block:statement
VariableBinding:getVariableDeclaration
VariableBinding:getUnresolvedJavaElement:Block:Block:expression
VariableBinding:getDeclaringMethod
VariableBinding:getUnresolvedJavaElement:Block:Block:Block:typeHandle
VariableBinding:getUnresolvedJavaElement:Block:declaringMethod
VariableBinding:getAnnotations:Block:internalAnnotations
VariableBinding:getDeclaringMethod:Block:Block:Block:lambdaExpression
VariableBinding:getUnresolvedJavaElement:Block:modifiers
VariableBinding:getUnresolvedJavaElement:Block:Block:Block:typeDeclaration
VariableBinding:VariableBinding
VariableBinding:getDeclaringClass:Block:Block:Block:fieldBinding
VariableBinding:getUnresolvedJavaElement:Block:localVariableBinding
VariableBinding:key
VariableBinding:getAnnotations:Block:Block:Block:internalAnnotation
VariableBinding:declaringClass
VariableBinding:isSynthetic
VariableBinding:getVariableId
VariableBinding:getDeclaringClass
VariableBinding:isEnumConstant
VariableBinding:getDeclaringMethod:Block:Block:node
VariableBinding:getUnresolvedJavaElement:Block:nameStart
VariableBinding:isDeprecated
VariableBinding:getConstantValue:Block:c
VariableBinding:getKind
VariableBinding:getUnresolvedJavaElement:Block:Block:singleVariableDeclaration
VariableBinding:getUnresolvedJavaElement:Block:sourceLength
VariableBinding:isEqualTo
VariableBinding:isEqualTo:Block:otherBinding
VariableBinding:getJavaElement
VariableBinding:isField
VariableBinding:type
VariableBinding:annotations
VariableBinding:getAnnotations:Block:Block:convertedAnnotationCount
VariableBinding:getUnresolvedJavaElement:Block:typeSig
VariableBinding:getType
VariableBinding:getAnnotations:Block:length
VariableBinding:getUnresolvedJavaElement:Block:nameLength
VariableBinding:getUnresolvedJavaElement:Block:Block:fieldDeclaration
VariableBinding:isEffectivelyFinal
VariableBinding:getDeclaringMethod:Block:Block:Block:methodDeclaration
VariableBinding:getDeclaringMethod:Block:Block:Block:Block:Block:enclosingMethod
VariableBinding:getUnresolvedJavaElement:Block:defaultBindingResolver
VariableBinding:getUnresolvedJavaElement:Block:sourceStart
Members
X