diff options
Diffstat (limited to 'javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java')
-rw-r--r-- | javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java new file mode 100644 index 000000000..b39521067 --- /dev/null +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedReferenceTypeDeclaration.java @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2007-2010 JĂșlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2016 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.resolution.declarations; + +import com.github.javaparser.ast.AccessSpecifier; +import com.github.javaparser.resolution.MethodUsage; +import com.github.javaparser.resolution.UnsolvedSymbolException; +import com.github.javaparser.resolution.types.ResolvedReferenceType; +import com.github.javaparser.resolution.types.ResolvedType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author Federico Tomassetti + */ +public interface ResolvedReferenceTypeDeclaration extends ResolvedTypeDeclaration, + ResolvedTypeParametrizable { + + @Override + default ResolvedReferenceTypeDeclaration asReferenceType() { + return this; + } + + /// + /// Ancestors + /// + + /** + * The list of all the direct ancestors of the current declaration. + * Note that the ancestor can be parametrized types with values specified. For example: + * <p> + * class A implements Comparable<String> {} + * <p> + * In this case the ancestor is Comparable<String> + */ + List<ResolvedReferenceType> getAncestors(); + + /** + * The list of all the ancestors of the current declaration, direct and indirect. + * This list does not contains duplicates with the exacting same type parameters. + */ + default List<ResolvedReferenceType> getAllAncestors() { + List<ResolvedReferenceType> ancestors = new ArrayList<>(); + // We want to avoid infinite recursion in case of Object having Object as ancestor + if (!(Object.class.getCanonicalName().equals(getQualifiedName()))) { + for (ResolvedReferenceType ancestor : getAncestors()) { + ancestors.add(ancestor); + for (ResolvedReferenceType inheritedAncestor : ancestor.getAllAncestors()) { + if (!ancestors.contains(inheritedAncestor)) { + ancestors.add(inheritedAncestor); + } + } + } + } + return ancestors; + } + + /// + /// Fields + /// + + /** + * Note that the type of the field should be expressed using the type variables of this particular type. + * Consider for example: + * <p> + * class Foo<E> { E field; } + * <p> + * class Bar extends Foo<String> { } + * <p> + * When calling getField("field") on Foo I should get a FieldDeclaration with type E, while calling it on + * Bar I should get a FieldDeclaration with type String. + */ + default ResolvedFieldDeclaration getField(String name) { + Optional<ResolvedFieldDeclaration> field = this.getAllFields().stream().filter(f -> f.getName().equals(name)).findFirst(); + if (field.isPresent()) { + return field.get(); + } else { + throw new UnsolvedSymbolException("Field not found: " + name); + } + } + + /** + * Consider only field or inherited field which is not private. + */ + default ResolvedFieldDeclaration getVisibleField(String name) { + Optional<ResolvedFieldDeclaration> field = getVisibleFields().stream().filter(f -> f.getName().equals(name)).findFirst(); + if (field.isPresent()) { + return field.get(); + } else { + throw new IllegalArgumentException(); + } + } + + /** + * Has this type a field with the given name? + */ + default boolean hasField(String name) { + return this.getAllFields().stream().filter(f -> f.getName().equals(name)).findFirst().isPresent(); + } + + /** + * Either a declared field or inherited field which is not private. + */ + default boolean hasVisibleField(String name) { + return getVisibleFields().stream().filter(f -> f.getName().equals(name)).findFirst().isPresent(); + } + + /** + * Return a list of all fields, either declared in this declaration or inherited. + */ + List<ResolvedFieldDeclaration> getAllFields(); + + /** + * Return a list of all fields declared and the inherited ones which are not private. + */ + default List<ResolvedFieldDeclaration> getVisibleFields() { + return getAllFields().stream() + .filter(f -> f.declaringType().equals(this) || f.accessSpecifier() != AccessSpecifier.PRIVATE) + .collect(Collectors.toList()); + } + + /** + * Return a list of all the non static fields, either declared or inherited. + */ + default List<ResolvedFieldDeclaration> getAllNonStaticFields() { + return getAllFields().stream().filter(it -> !it.isStatic()).collect(Collectors.toList()); + } + + /** + * Return a list of all the static fields, either declared or inherited. + */ + default List<ResolvedFieldDeclaration> getAllStaticFields() { + return getAllFields().stream().filter(it -> it.isStatic()).collect(Collectors.toList()); + } + + /** + * Return a list of all the fields declared in this type. + */ + default List<ResolvedFieldDeclaration> getDeclaredFields() { + return getAllFields().stream().filter(it -> it.declaringType().getQualifiedName().equals(getQualifiedName())).collect(Collectors.toList()); + } + + /// + /// Methods + /// + + /** + * Return a list of all the methods declared in this type declaration. + */ + Set<ResolvedMethodDeclaration> getDeclaredMethods(); + + /** + * Return a list of all the methods declared of this type declaration, either declared or inherited. + * Note that it should not include overridden methods. + */ + Set<MethodUsage> getAllMethods(); + + /// + /// Assignability + /// + + /** + * Can we assign instances of the given type to variables having the type defined + * by this declaration? + */ + boolean isAssignableBy(ResolvedType type); + + /** + * Can we assign instances of the type defined by this declaration to variables having the type defined + * by the given type? + */ + default boolean canBeAssignedTo(ResolvedReferenceTypeDeclaration other) { + return other.isAssignableBy(this); + } + + /** + * Can we assign instances of the given type to variables having the type defined + * by this declaration? + */ + boolean isAssignableBy(ResolvedReferenceTypeDeclaration other); + + /// + /// Annotations + /// + + /** + * Has the type at least one annotation declared having the specified qualified name? + */ + boolean hasDirectlyAnnotation(String qualifiedName); + + /** + * Has the type at least one annotation declared or inherited having the specified qualified name? + */ + default boolean hasAnnotation(String qualifiedName) { + if (hasDirectlyAnnotation(qualifiedName)) { + return true; + } + return getAllAncestors().stream().anyMatch(it -> it.asReferenceType().getTypeDeclaration().hasDirectlyAnnotation(qualifiedName)); + } + + /** + * This means that the type has a functional method. Conceptually, a functional interface has exactly one abstract method. + * Typically these classes has the FunctionInterface annotation but this is not mandatory. + */ + boolean isFunctionalInterface(); + + /// + /// Type parameters + /// + + @Override + default Optional<ResolvedTypeParameterDeclaration> findTypeParameter(String name) { + for (ResolvedTypeParameterDeclaration tp : this.getTypeParameters()) { + if (tp.getName().equals(name)) { + return Optional.of(tp); + } + } + if (this.containerType().isPresent()) { + return this.containerType().get().findTypeParameter(name); + } + return Optional.empty(); + } +} |