Home | History | Annotate | Download | only in declarations
      1 /*
      2  * Copyright 2016 Federico Tomassetti
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.github.javaparser.symbolsolver.javaparsermodel.declarations;
     18 
     19 import com.github.javaparser.ast.AccessSpecifier;
     20 import com.github.javaparser.ast.Node;
     21 import com.github.javaparser.ast.body.BodyDeclaration;
     22 import com.github.javaparser.ast.body.EnumConstantDeclaration;
     23 import com.github.javaparser.ast.type.ClassOrInterfaceType;
     24 import com.github.javaparser.resolution.MethodUsage;
     25 import com.github.javaparser.resolution.UnsolvedSymbolException;
     26 import com.github.javaparser.resolution.declarations.*;
     27 import com.github.javaparser.resolution.types.ResolvedArrayType;
     28 import com.github.javaparser.resolution.types.ResolvedReferenceType;
     29 import com.github.javaparser.resolution.types.ResolvedType;
     30 import com.github.javaparser.resolution.types.parametrization.ResolvedTypeParametersMap;
     31 import com.github.javaparser.symbolsolver.core.resolution.Context;
     32 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
     33 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
     34 import com.github.javaparser.symbolsolver.logic.AbstractTypeDeclaration;
     35 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
     36 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
     37 import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl;
     38 import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionFactory;
     39 import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
     40 
     41 import java.io.Serializable;
     42 import java.util.*;
     43 import java.util.stream.Collectors;
     44 
     45 /**
     46  * @author Federico Tomassetti
     47  */
     48 public class JavaParserEnumDeclaration extends AbstractTypeDeclaration implements ResolvedEnumDeclaration {
     49 
     50     private TypeSolver typeSolver;
     51     private com.github.javaparser.ast.body.EnumDeclaration wrappedNode;
     52     private JavaParserTypeAdapter<com.github.javaparser.ast.body.EnumDeclaration> javaParserTypeAdapter;
     53 
     54     public JavaParserEnumDeclaration(com.github.javaparser.ast.body.EnumDeclaration wrappedNode, TypeSolver typeSolver) {
     55         this.wrappedNode = wrappedNode;
     56         this.typeSolver = typeSolver;
     57         this.javaParserTypeAdapter = new JavaParserTypeAdapter<>(wrappedNode, typeSolver);
     58     }
     59 
     60     @Override
     61     public String toString() {
     62         return "JavaParserEnumDeclaration{" +
     63                 "wrappedNode=" + wrappedNode +
     64                 '}';
     65     }
     66 
     67     @Override
     68     public Set<ResolvedMethodDeclaration> getDeclaredMethods() {
     69         Set<ResolvedMethodDeclaration> methods = new HashSet<>();
     70         for (BodyDeclaration<?> member : wrappedNode.getMembers()) {
     71             if (member instanceof com.github.javaparser.ast.body.MethodDeclaration) {
     72                 methods.add(new JavaParserMethodDeclaration((com.github.javaparser.ast.body.MethodDeclaration) member, typeSolver));
     73             }
     74         }
     75         return methods;
     76     }
     77 
     78     public Context getContext() {
     79         return JavaParserFactory.getContext(wrappedNode, typeSolver);
     80     }
     81 
     82     @Override
     83     public String getName() {
     84         return wrappedNode.getName().getId();
     85     }
     86 
     87     @Override
     88     public boolean isField() {
     89         return false;
     90     }
     91 
     92     @Override
     93     public boolean isParameter() {
     94         return false;
     95     }
     96 
     97     @Override
     98     public boolean isType() {
     99         return true;
    100     }
    101 
    102     @Override
    103     public boolean hasDirectlyAnnotation(String canonicalName) {
    104         throw new UnsupportedOperationException();
    105     }
    106 
    107     @Override
    108     public boolean canBeAssignedTo(ResolvedReferenceTypeDeclaration other) {
    109         String otherName = other.getQualifiedName();
    110         // Enums cannot be extended
    111         if (otherName.equals(this.getQualifiedName())) {
    112             return true;
    113         }
    114         if (otherName.equals(Enum.class.getCanonicalName())) {
    115             return true;
    116         }
    117         // Enum implements Comparable and Serializable
    118         if (otherName.equals(Comparable.class.getCanonicalName())) {
    119             return true;
    120         }
    121         if (otherName.equals(Serializable.class.getCanonicalName())) {
    122             return true;
    123         }
    124         if (otherName.equals(Object.class.getCanonicalName())) {
    125             return true;
    126         }
    127         return false;
    128     }
    129 
    130     @Override
    131     public boolean isClass() {
    132         return false;
    133     }
    134 
    135     @Override
    136     public boolean isInterface() {
    137         return false;
    138     }
    139 
    140     @Override
    141     public String getPackageName() {
    142         return javaParserTypeAdapter.getPackageName();
    143     }
    144 
    145     @Override
    146     public String getClassName() {
    147         return javaParserTypeAdapter.getClassName();
    148     }
    149 
    150     @Override
    151     public String getQualifiedName() {
    152         return javaParserTypeAdapter.getQualifiedName();
    153     }
    154 
    155     @Override
    156     public boolean isAssignableBy(ResolvedReferenceTypeDeclaration other) {
    157         return javaParserTypeAdapter.isAssignableBy(other);
    158     }
    159 
    160     @Override
    161     public boolean isAssignableBy(ResolvedType type) {
    162         return javaParserTypeAdapter.isAssignableBy(type);
    163     }
    164 
    165     @Override
    166     public boolean isTypeParameter() {
    167         return false;
    168     }
    169 
    170     @Override
    171     public boolean equals(Object o) {
    172         if (this == o) return true;
    173         if (o == null || getClass() != o.getClass()) return false;
    174 
    175         JavaParserEnumDeclaration that = (JavaParserEnumDeclaration) o;
    176 
    177         if (!wrappedNode.equals(that.wrappedNode)) return false;
    178 
    179         return true;
    180     }
    181 
    182     @Override
    183     public int hashCode() {
    184         return wrappedNode.hashCode();
    185     }
    186 
    187     @Deprecated
    188     public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> parameterTypes,
    189                                                     TypeSolver typeSolver, Context invokationContext, List<ResolvedType> typeParameterValues) {
    190         if (name.equals("values") && parameterTypes.isEmpty()) {
    191             return Optional.of(new ValuesMethod(this, typeSolver).getUsage(null));
    192         }
    193         // TODO add methods inherited from Enum
    194         return getContext().solveMethodAsUsage(name, parameterTypes, typeSolver);
    195     }
    196 
    197     @Override
    198     public List<ResolvedFieldDeclaration> getAllFields() {
    199         List<ResolvedFieldDeclaration> fields = javaParserTypeAdapter.getFieldsForDeclaredVariables();
    200 
    201         if (this.wrappedNode.getEntries() != null) {
    202             for (EnumConstantDeclaration member : this.wrappedNode.getEntries()) {
    203                 fields.add(new JavaParserFieldDeclaration(member, typeSolver));
    204             }
    205         }
    206 
    207         return fields;
    208     }
    209 
    210     @Override
    211     public List<ResolvedReferenceType> getAncestors() {
    212         List<ResolvedReferenceType> ancestors = new ArrayList<>();
    213         ResolvedReferenceType enumClass = ReflectionFactory.typeUsageFor(Enum.class, typeSolver).asReferenceType();
    214         ResolvedTypeParameterDeclaration eTypeParameter = enumClass.getTypeDeclaration().getTypeParameters().get(0);
    215         enumClass = enumClass.deriveTypeParameters(new ResolvedTypeParametersMap.Builder().setValue(eTypeParameter, new ReferenceTypeImpl(this, typeSolver)).build());
    216         ancestors.add(enumClass);
    217         if (wrappedNode.getImplementedTypes() != null) {
    218             for (ClassOrInterfaceType implementedType : wrappedNode.getImplementedTypes()) {
    219                 SymbolReference<ResolvedTypeDeclaration> implementedDeclRef = new SymbolSolver(typeSolver).solveTypeInType(this, implementedType.getName().getId());
    220                 if (!implementedDeclRef.isSolved()) {
    221                     throw new UnsolvedSymbolException(implementedType.getName().getId());
    222                 }
    223                 ancestors.add(new ReferenceTypeImpl((ResolvedReferenceTypeDeclaration) implementedDeclRef.getCorrespondingDeclaration(), typeSolver));
    224             }
    225         }
    226         return ancestors;
    227     }
    228 
    229     @Override
    230     public List<ResolvedTypeParameterDeclaration> getTypeParameters() {
    231         return Collections.emptyList();
    232     }
    233 
    234     /**
    235      * Returns the JavaParser node associated with this JavaParserEnumDeclaration.
    236      *
    237      * @return A visitable JavaParser node wrapped by this object.
    238      */
    239     public com.github.javaparser.ast.body.EnumDeclaration getWrappedNode() {
    240         return wrappedNode;
    241     }
    242 
    243     @Override
    244     public List<ResolvedEnumConstantDeclaration> getEnumConstants() {
    245         return wrappedNode.getEntries().stream()
    246                 .map(entry -> new JavaParserEnumConstantDeclaration(entry, typeSolver))
    247                 .collect(Collectors.toList());
    248     }
    249 
    250     // Needed by ContextHelper
    251     public static class ValuesMethod implements ResolvedMethodDeclaration {
    252 
    253         private JavaParserEnumDeclaration enumDeclaration;
    254         private TypeSolver typeSolver;
    255 
    256         public ValuesMethod(JavaParserEnumDeclaration enumDeclaration, TypeSolver typeSolver) {
    257             this.enumDeclaration = enumDeclaration;
    258             this.typeSolver = typeSolver;
    259         }
    260 
    261         @Override
    262         public ResolvedReferenceTypeDeclaration declaringType() {
    263             return enumDeclaration;
    264         }
    265 
    266         @Override
    267         public ResolvedType getReturnType() {
    268             return new ResolvedArrayType(new ReferenceTypeImpl(enumDeclaration, typeSolver));
    269         }
    270 
    271         @Override
    272         public int getNumberOfParams() {
    273             return 0;
    274         }
    275 
    276         @Override
    277         public ResolvedParameterDeclaration getParam(int i) {
    278             throw new UnsupportedOperationException();
    279         }
    280 
    281         public MethodUsage getUsage(Node node) {
    282             throw new UnsupportedOperationException();
    283         }
    284 
    285         public MethodUsage resolveTypeVariables(Context context, List<ResolvedType> parameterTypes) {
    286             return new MethodUsage(this);
    287         }
    288 
    289         @Override
    290         public boolean isAbstract() {
    291             throw new UnsupportedOperationException();
    292         }
    293 
    294         @Override
    295         public boolean isDefaultMethod() {
    296             return false;
    297         }
    298 
    299         @Override
    300         public boolean isStatic() {
    301             return false;
    302         }
    303 
    304         @Override
    305         public String getName() {
    306             return "values";
    307         }
    308 
    309         @Override
    310         public List<ResolvedTypeParameterDeclaration> getTypeParameters() {
    311             return Collections.emptyList();
    312         }
    313 
    314         @Override
    315         public AccessSpecifier accessSpecifier() {
    316             return Helper.toAccessLevel(enumDeclaration.getWrappedNode().getModifiers());
    317         }
    318 
    319         @Override
    320         public int getNumberOfSpecifiedExceptions() {
    321             return 0;
    322         }
    323 
    324         @Override
    325         public ResolvedType getSpecifiedException(int index) {
    326             throw new UnsupportedOperationException("The values method of an enum does not throw any exception");
    327         }
    328     }
    329 
    330     @Override
    331     public AccessSpecifier accessSpecifier() {
    332         throw new UnsupportedOperationException();
    333     }
    334 
    335     @Override
    336     public Set<ResolvedReferenceTypeDeclaration> internalTypes() {
    337         Set<ResolvedReferenceTypeDeclaration> res = new HashSet<>();
    338         for (BodyDeclaration<?> member : this.wrappedNode.getMembers()) {
    339             if (member instanceof com.github.javaparser.ast.body.TypeDeclaration) {
    340                 res.add(JavaParserFacade.get(typeSolver).getTypeDeclaration((com.github.javaparser.ast.body.TypeDeclaration)member));
    341             }
    342         }
    343         return res;
    344     }
    345 
    346     @Override
    347     public Optional<ResolvedReferenceTypeDeclaration> containerType() {
    348         return javaParserTypeAdapter.containerType();
    349     }
    350 }
    351