JavaParser Source Viewer

Home|JavaParser/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java
1/*
2 * Copyright (C) 2007-2010 JĂșlio Vilmar Gesser.
3 * Copyright (C) 2011, 2013-2020 The JavaParser Team.
4 *
5 * This file is part of JavaParser.
6 *
7 * JavaParser can be used either under the terms of
8 * a) the GNU Lesser General Public License as published by
9 *     the Free Software Foundation, either version 3 of the License, or
10 *     (at your option) any later version.
11 * b) the terms of the Apache License
12 *
13 * You should have received a copy of both licenses in LICENCE.LGPL and
14 * LICENCE.APACHE. Please refer to those files for details.
15 *
16 * JavaParser is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU Lesser General Public License for more details.
20 */
21
22package com.github.javaparser.resolution.declarations;
23
24import java.util.ArrayList;
25import java.util.List;
26import java.util.Optional;
27import java.util.Set;
28import java.util.stream.Collectors;
29
30import com.github.javaparser.ast.AccessSpecifier;
31import com.github.javaparser.resolution.MethodUsage;
32import com.github.javaparser.resolution.UnsolvedSymbolException;
33import com.github.javaparser.resolution.types.ResolvedReferenceType;
34import com.github.javaparser.resolution.types.ResolvedType;
35
36/**
37 * @author Federico Tomassetti
38 */
39public interface ResolvedReferenceTypeDeclaration extends ResolvedTypeDeclaration,
40                                                                  ResolvedTypeParametrizable {
41
42    @Override
43    default ResolvedReferenceTypeDeclaration asReferenceType() {
44        return this;
45    }
46
47    ///
48    /// Ancestors
49    ///
50
51    /**
52     * Resolves the types of all direct ancestors (i.e., the directly extended class and the directly implemented
53     * interfaces) and returns the list of ancestors as a list of resolved reference types.
54     * <p>
55     * In case any ancestor cannot be resolved, an {@code UnsolvedSymbolException} is thrown. In order to obtain a list
56     * of only the resolvable direct ancestors, use {@link #getAncestors(boolean)} and pass the value {@code true}.
57     * <p>
58     * Note that an ancestor can be parametrized types with values specified. For example:
59     * <p>
60     * class A implements Comparable&lt;String&gt; {}
61     * <p>
62     * In this case the ancestor is Comparable&lt;String&gt;
63     *
64     * @return The list of resolved ancestors.
65     * @throws UnsolvedSymbolException if some ancestor could not be resolved.
66     */
67    default List<ResolvedReferenceTypegetAncestors() {
68        return getAncestors(false);
69    }
70
71    /**
72     * Resolves the types of all direct ancestors (i.e., the directly extended class and the directly implemented
73     * interfaces) and returns the list of ancestors as a list of resolved reference types.
74     * <p>
75     * If {@code acceptIncompleteList} is {@code false}, then an {@code UnsolvedSymbolException} is thrown if any
76     * ancestor cannot be resolved. Otherwise, a list of only the resolvable direct ancestors is returned.
77     *
78     * @param acceptIncompleteList When set to {@code false}, this method throws an {@link UnsolvedSymbolException} if
79     *                             one or more ancestor could not be resolved. When set to {@code true}, this method
80     *                             does not throw an {@link UnsolvedSymbolException}, but the list of returned ancestors
81     *                             may be incomplete in case one or more ancestor could not be resolved.
82     * @return The list of resolved ancestors.
83     * @throws UnsolvedSymbolException if some ancestor could not be resolved and {@code acceptIncompleteList} is set to
84     *                                 {@code false}.
85     */
86    List<ResolvedReferenceTypegetAncestors(boolean acceptIncompleteList);
87
88    /**
89     * The list of all the ancestors of the current declaration, direct and indirect.
90     * This list does not contains duplicates with the exact same type parameters.
91     */
92    default List<ResolvedReferenceTypegetAllAncestors() {
93        List<ResolvedReferenceTypeancestors = new ArrayList<>();
94        // We want to avoid infinite recursion in case of Object having Object as ancestor
95        if (!isJavaLangObject()) {
96            for (ResolvedReferenceType ancestor : getAncestors()) {
97                ancestors.add(ancestor);
98                for (ResolvedReferenceType inheritedAncestor : ancestor.getAllAncestors()) {
99                    if (!ancestors.contains(inheritedAncestor)) {
100                        ancestors.add(inheritedAncestor);
101                    }
102                }
103            }
104        }
105        return ancestors;
106    }
107
108    ///
109    /// Fields
110    ///
111
112    /**
113     * Note that the type of the field should be expressed using the type variables of this particular type.
114     * Consider for example:
115     * <p>
116     * class Foo<E> { E field; }
117     * <p>
118     * class Bar extends Foo<String> { }
119     * <p>
120     * When calling getField("field") on Foo I should get a FieldDeclaration with type E, while calling it on
121     * Bar I should get a FieldDeclaration with type String.
122     */
123    default ResolvedFieldDeclaration getField(String name) {
124        Optional<ResolvedFieldDeclarationfield = this.getAllFields().stream()
125                .filter(f -> f.getName().equals(name))
126                .findFirst();
127        if (field.isPresent()) {
128            return field.get();
129        } else {
130            throw new UnsolvedSymbolException("Field not found: " + name);
131        }
132    }
133
134    /**
135     * Consider only field or inherited field which is not private.
136     */
137    default ResolvedFieldDeclaration getVisibleField(String name) {
138        Optional<ResolvedFieldDeclarationfield = getVisibleFields().stream().filter(f -> f.getName().equals(name)).findFirst();
139        if (field.isPresent()) {
140            return field.get();
141        } else {
142            throw new IllegalArgumentException();
143        }
144    }
145
146    /**
147     * Has this type a field with the given name?
148     */
149    default boolean hasField(String name) {
150        return this.getAllFields().stream().anyMatch(f -> f.getName().equals(name));
151    }
152
153    /**
154     * Either a declared field or inherited field which is not private.
155     */
156    default boolean hasVisibleField(String name) {
157        return getVisibleFields().stream().anyMatch(f -> f.getName().equals(name));
158    }
159
160    /**
161     * Return a list of all fields, either declared in this declaration or inherited.
162     */
163    List<ResolvedFieldDeclarationgetAllFields();
164
165    /**
166     * Return a list of all fields declared and the inherited ones which are not private.
167     */
168    default List<ResolvedFieldDeclarationgetVisibleFields() {
169        return getAllFields().stream()
170                       .filter(f -> f.declaringType().equals(this) || f.accessSpecifier() != AccessSpecifier.PRIVATE)
171                       .collect(Collectors.toList());
172    }
173
174    /**
175     * Return a list of all the non static fields, either declared or inherited.
176     */
177    default List<ResolvedFieldDeclarationgetAllNonStaticFields() {
178        return getAllFields().stream().filter(it -> !it.isStatic()).collect(Collectors.toList());
179    }
180
181    /**
182     * Return a list of all the static fields, either declared or inherited.
183     */
184    default List<ResolvedFieldDeclarationgetAllStaticFields() {
185        return getAllFields().stream().filter(it -> it.isStatic()).collect(Collectors.toList());
186    }
187
188    /**
189     * Return a list of all the fields declared in this type.
190     */
191    default List<ResolvedFieldDeclarationgetDeclaredFields() {
192        return getAllFields().stream().filter(it -> it.declaringType().getQualifiedName()
193                                                            .equals(getQualifiedName())).collect(Collectors.toList());
194    }
195
196    ///
197    /// Methods
198    ///
199
200    /**
201     * Return a list of all the methods declared in this type declaration.
202     */
203    Set<ResolvedMethodDeclarationgetDeclaredMethods();
204
205    /**
206     * Return a list of all the methods declared of this type declaration, either declared or inherited.
207     * Note that it should not include overridden methods.
208     */
209    Set<MethodUsagegetAllMethods();
210
211    ///
212    /// Assignability
213    ///
214
215    /**
216     * Can we assign instances of the given type to variables having the type defined
217     * by this declaration?
218     */
219    boolean isAssignableBy(ResolvedType type);
220
221    /**
222     * Can we assign instances of the type defined by this declaration to variables having the type defined
223     * by the given type?
224     */
225    default boolean canBeAssignedTo(ResolvedReferenceTypeDeclaration other) {
226        return other.isAssignableBy(this);
227    }
228
229    /**
230     * Can we assign instances of the given type to variables having the type defined
231     * by this declaration?
232     */
233    boolean isAssignableBy(ResolvedReferenceTypeDeclaration other);
234
235    ///
236    /// Annotations
237    ///
238
239    /**
240     * Has the type at least one annotation declared having the specified qualified name?
241     */
242    boolean hasDirectlyAnnotation(String qualifiedName);
243
244    /**
245     * Has the type at least one annotation declared or inherited having the specified qualified name?
246     */
247    default boolean hasAnnotation(String qualifiedName) {
248        if (hasDirectlyAnnotation(qualifiedName)) {
249            return true;
250        }
251        return getAllAncestors().stream()
252                .filter(it -> it.asReferenceType().getTypeDeclaration().isPresent())
253                .anyMatch(it -> it.asReferenceType().getTypeDeclaration().get().hasDirectlyAnnotation(qualifiedName));
254    }
255
256    /**
257     * This means that the type has a functional method. Conceptually, a functional interface has exactly one abstract method.
258     * Typically these classes has the FunctionInterface annotation but this is not mandatory.
259     */
260    boolean isFunctionalInterface();
261
262    ///
263    /// Type parameters
264    ///
265
266    @Override
267    default Optional<ResolvedTypeParameterDeclarationfindTypeParameter(String name) {
268        for (ResolvedTypeParameterDeclaration tp : this.getTypeParameters()) {
269            if (tp.getName().equals(name)) {
270                return Optional.of(tp);
271            }
272        }
273        if (this.containerType().isPresent()) {
274            return this.containerType().get().findTypeParameter(name);
275        }
276        return Optional.empty();
277    }
278
279    List<ResolvedConstructorDeclarationgetConstructors();
280
281
282    /**
283     * We don't make this _ex_plicit in the data representation because that would affect codegen
284     * and make everything generate like {@code <T extends Object>} instead of {@code <T>}
285     *
286     * @return true, if this represents {@code java.lang.Object}
287     * @see ResolvedReferenceType#isJavaLangObject()
288     * @see <a href="https://github.com/javaparser/javaparser/issues/2044">https://github.com/javaparser/javaparser/issues/2044</a>
289     */
290    default boolean isJavaLangObject() {
291        return this.isClass()
292                && !isAnonymousClass()
293                && hasName() // Consider anonymous classes
294                && getQualifiedName().equals(java.lang.Object.class.getCanonicalName());
295    }
296
297    /**
298     * @return true, if this represents {@code java.lang.Enum}
299     * @see ResolvedReferenceType#isJavaLangEnum()
300     */
301    default boolean isJavaLangEnum() {
302        return this.isEnum()
303                && getQualifiedName().equals(java.lang.Enum.class.getCanonicalName());
304    }
305
306}
307
MembersX
ResolvedReferenceTypeDeclaration:getDeclaredFields
ResolvedReferenceTypeDeclaration:getAllAncestors:Block:ancestors
ResolvedReferenceTypeDeclaration:getVisibleField:Block:field
ResolvedReferenceTypeDeclaration:getConstructors
ResolvedReferenceTypeDeclaration:getVisibleField
ResolvedReferenceTypeDeclaration:getField
ResolvedReferenceTypeDeclaration:getAllStaticFields
ResolvedReferenceTypeDeclaration:findTypeParameter
ResolvedReferenceTypeDeclaration:getDeclaredMethods
ResolvedReferenceTypeDeclaration:getAncestors
ResolvedReferenceTypeDeclaration:isAssignableBy
ResolvedReferenceTypeDeclaration:hasDirectlyAnnotation
ResolvedReferenceTypeDeclaration:hasAnnotation
ResolvedReferenceTypeDeclaration:canBeAssignedTo
ResolvedReferenceTypeDeclaration:getAllAncestors
ResolvedReferenceTypeDeclaration:hasVisibleField
ResolvedReferenceTypeDeclaration:getAllNonStaticFields
ResolvedReferenceTypeDeclaration:hasField
ResolvedReferenceTypeDeclaration:asReferenceType
ResolvedReferenceTypeDeclaration:getField:Block:field
ResolvedReferenceTypeDeclaration:isFunctionalInterface
ResolvedReferenceTypeDeclaration:getVisibleFields
ResolvedReferenceTypeDeclaration:isJavaLangObject
ResolvedReferenceTypeDeclaration:isJavaLangEnum
ResolvedReferenceTypeDeclaration:getAllFields
ResolvedReferenceTypeDeclaration:getAllMethods
Members
X