• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
3  * Copyright (C) 2011, 2013-2016 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 
22 package com.github.javaparser.resolution.declarations;
23 
24 import com.github.javaparser.ast.AccessSpecifier;
25 import com.github.javaparser.resolution.MethodUsage;
26 import com.github.javaparser.resolution.UnsolvedSymbolException;
27 import com.github.javaparser.resolution.types.ResolvedReferenceType;
28 import com.github.javaparser.resolution.types.ResolvedType;
29 
30 import java.util.ArrayList;
31 import java.util.List;
32 import java.util.Optional;
33 import java.util.Set;
34 import java.util.stream.Collectors;
35 
36 /**
37  * @author Federico Tomassetti
38  */
39 public interface ResolvedReferenceTypeDeclaration extends ResolvedTypeDeclaration,
40         ResolvedTypeParametrizable {
41 
42     @Override
asReferenceType()43     default ResolvedReferenceTypeDeclaration asReferenceType() {
44         return this;
45     }
46 
47     ///
48     /// Ancestors
49     ///
50 
51     /**
52      * The list of all the direct ancestors of the current declaration.
53      * Note that the ancestor can be parametrized types with values specified. For example:
54      * <p>
55      * class A implements Comparable&lt;String&gt; {}
56      * <p>
57      * In this case the ancestor is Comparable&lt;String&gt;
58      */
getAncestors()59     List<ResolvedReferenceType> getAncestors();
60 
61     /**
62      * The list of all the ancestors of the current declaration, direct and indirect.
63      * This list does not contains duplicates with the exacting same type parameters.
64      */
getAllAncestors()65     default List<ResolvedReferenceType> getAllAncestors() {
66         List<ResolvedReferenceType> ancestors = new ArrayList<>();
67         // We want to avoid infinite recursion in case of Object having Object as ancestor
68         if (!(Object.class.getCanonicalName().equals(getQualifiedName()))) {
69             for (ResolvedReferenceType ancestor : getAncestors()) {
70                 ancestors.add(ancestor);
71                 for (ResolvedReferenceType inheritedAncestor : ancestor.getAllAncestors()) {
72                     if (!ancestors.contains(inheritedAncestor)) {
73                         ancestors.add(inheritedAncestor);
74                     }
75                 }
76             }
77         }
78         return ancestors;
79     }
80 
81     ///
82     /// Fields
83     ///
84 
85     /**
86      * Note that the type of the field should be expressed using the type variables of this particular type.
87      * Consider for example:
88      * <p>
89      * class Foo<E> { E field; }
90      * <p>
91      * class Bar extends Foo<String> { }
92      * <p>
93      * When calling getField("field") on Foo I should get a FieldDeclaration with type E, while calling it on
94      * Bar I should get a FieldDeclaration with type String.
95      */
getField(String name)96     default ResolvedFieldDeclaration getField(String name) {
97         Optional<ResolvedFieldDeclaration> field = this.getAllFields().stream().filter(f -> f.getName().equals(name)).findFirst();
98         if (field.isPresent()) {
99             return field.get();
100         } else {
101             throw new UnsolvedSymbolException("Field not found: " + name);
102         }
103     }
104 
105     /**
106      * Consider only field or inherited field which is not private.
107      */
getVisibleField(String name)108     default ResolvedFieldDeclaration getVisibleField(String name) {
109         Optional<ResolvedFieldDeclaration> field = getVisibleFields().stream().filter(f -> f.getName().equals(name)).findFirst();
110         if (field.isPresent()) {
111             return field.get();
112         } else {
113             throw new IllegalArgumentException();
114         }
115     }
116 
117     /**
118      * Has this type a field with the given name?
119      */
hasField(String name)120     default boolean hasField(String name) {
121         return this.getAllFields().stream().filter(f -> f.getName().equals(name)).findFirst().isPresent();
122     }
123 
124     /**
125      * Either a declared field or inherited field which is not private.
126      */
hasVisibleField(String name)127     default boolean hasVisibleField(String name) {
128         return getVisibleFields().stream().filter(f -> f.getName().equals(name)).findFirst().isPresent();
129     }
130 
131     /**
132      * Return a list of all fields, either declared in this declaration or inherited.
133      */
getAllFields()134     List<ResolvedFieldDeclaration> getAllFields();
135 
136     /**
137      * Return a list of all fields declared and the inherited ones which are not private.
138      */
getVisibleFields()139     default List<ResolvedFieldDeclaration> getVisibleFields() {
140         return getAllFields().stream()
141                 .filter(f -> f.declaringType().equals(this) || f.accessSpecifier() != AccessSpecifier.PRIVATE)
142                 .collect(Collectors.toList());
143     }
144 
145     /**
146      * Return a list of all the non static fields, either declared or inherited.
147      */
getAllNonStaticFields()148     default List<ResolvedFieldDeclaration> getAllNonStaticFields() {
149         return getAllFields().stream().filter(it -> !it.isStatic()).collect(Collectors.toList());
150     }
151 
152     /**
153      * Return a list of all the static fields, either declared or inherited.
154      */
getAllStaticFields()155     default List<ResolvedFieldDeclaration> getAllStaticFields() {
156         return getAllFields().stream().filter(it -> it.isStatic()).collect(Collectors.toList());
157     }
158 
159     /**
160      * Return a list of all the fields declared in this type.
161      */
getDeclaredFields()162     default List<ResolvedFieldDeclaration> getDeclaredFields() {
163         return getAllFields().stream().filter(it -> it.declaringType().getQualifiedName().equals(getQualifiedName())).collect(Collectors.toList());
164     }
165 
166     ///
167     /// Methods
168     ///
169 
170     /**
171      * Return a list of all the methods declared in this type declaration.
172      */
getDeclaredMethods()173     Set<ResolvedMethodDeclaration> getDeclaredMethods();
174 
175     /**
176      * Return a list of all the methods declared of this type declaration, either declared or inherited.
177      * Note that it should not include overridden methods.
178      */
getAllMethods()179     Set<MethodUsage> getAllMethods();
180 
181     ///
182     /// Assignability
183     ///
184 
185     /**
186      * Can we assign instances of the given type to variables having the type defined
187      * by this declaration?
188      */
isAssignableBy(ResolvedType type)189     boolean isAssignableBy(ResolvedType type);
190 
191     /**
192      * Can we assign instances of the type defined by this declaration to variables having the type defined
193      * by the given type?
194      */
canBeAssignedTo(ResolvedReferenceTypeDeclaration other)195     default boolean canBeAssignedTo(ResolvedReferenceTypeDeclaration other) {
196         return other.isAssignableBy(this);
197     }
198 
199     /**
200      * Can we assign instances of the given type to variables having the type defined
201      * by this declaration?
202      */
isAssignableBy(ResolvedReferenceTypeDeclaration other)203     boolean isAssignableBy(ResolvedReferenceTypeDeclaration other);
204 
205     ///
206     /// Annotations
207     ///
208 
209     /**
210      * Has the type at least one annotation declared having the specified qualified name?
211      */
hasDirectlyAnnotation(String qualifiedName)212     boolean hasDirectlyAnnotation(String qualifiedName);
213 
214     /**
215      * Has the type at least one annotation declared or inherited having the specified qualified name?
216      */
hasAnnotation(String qualifiedName)217     default boolean hasAnnotation(String qualifiedName) {
218         if (hasDirectlyAnnotation(qualifiedName)) {
219             return true;
220         }
221         return getAllAncestors().stream().anyMatch(it -> it.asReferenceType().getTypeDeclaration().hasDirectlyAnnotation(qualifiedName));
222     }
223 
224     /**
225      * This means that the type has a functional method. Conceptually, a functional interface has exactly one abstract method.
226      * Typically these classes has the FunctionInterface annotation but this is not mandatory.
227      */
isFunctionalInterface()228     boolean isFunctionalInterface();
229 
230     ///
231     /// Type parameters
232     ///
233 
234     @Override
findTypeParameter(String name)235     default Optional<ResolvedTypeParameterDeclaration> findTypeParameter(String name) {
236         for (ResolvedTypeParameterDeclaration tp : this.getTypeParameters()) {
237             if (tp.getName().equals(name)) {
238                 return Optional.of(tp);
239             }
240         }
241         if (this.containerType().isPresent()) {
242             return this.containerType().get().findTypeParameter(name);
243         }
244         return Optional.empty();
245     }
246 }
247