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<String> {} 56 * <p> 57 * In this case the ancestor is Comparable<String> 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