Home | History | Annotate | Download | only in contexts
      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.contexts;
     18 
     19 import com.github.javaparser.ast.expr.Expression;
     20 import com.github.javaparser.ast.expr.FieldAccessExpr;
     21 import com.github.javaparser.ast.expr.ThisExpr;
     22 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration;
     23 import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration;
     24 import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
     25 import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
     26 import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration;
     27 import com.github.javaparser.resolution.types.ResolvedPrimitiveType;
     28 import com.github.javaparser.resolution.types.ResolvedType;
     29 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
     30 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
     31 import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
     32 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
     33 import com.github.javaparser.symbolsolver.model.resolution.Value;
     34 import com.github.javaparser.symbolsolver.resolution.SymbolSolver;
     35 
     36 import java.util.Collection;
     37 import java.util.List;
     38 import java.util.Optional;
     39 
     40 import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode;
     41 import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
     42 
     43 /**
     44  * @author Federico Tomassetti
     45  */
     46 public class FieldAccessContext extends AbstractJavaParserContext<FieldAccessExpr> {
     47 
     48     private static final String ARRAY_LENGTH_FIELD_NAME = "length";
     49 
     50     public FieldAccessContext(FieldAccessExpr wrappedNode, TypeSolver typeSolver) {
     51         super(wrappedNode, typeSolver);
     52     }
     53 
     54     @Override
     55     public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name, TypeSolver typeSolver) {
     56         if (wrappedNode.getName().toString().equals(name)) {
     57             if (wrappedNode.getScope() instanceof ThisExpr) {
     58                 ResolvedType typeOfThis = JavaParserFacade.get(typeSolver).getTypeOfThisIn(wrappedNode);
     59                 return new SymbolSolver(typeSolver).solveSymbolInType(typeOfThis.asReferenceType().getTypeDeclaration(), name);
     60             }
     61         }
     62         return JavaParserFactory.getContext(requireParentNode(wrappedNode), typeSolver).solveSymbol(name, typeSolver);
     63     }
     64 
     65     @Override
     66     public SymbolReference<ResolvedTypeDeclaration> solveType(String name, TypeSolver typeSolver) {
     67         return JavaParserFactory.getContext(requireParentNode(wrappedNode), typeSolver).solveType(name, typeSolver);
     68     }
     69 
     70     @Override
     71     public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> parameterTypes, boolean staticOnly, TypeSolver typeSolver) {
     72         return JavaParserFactory.getContext(requireParentNode(wrappedNode), typeSolver).solveMethod(name, parameterTypes, false, typeSolver);
     73     }
     74 
     75     @Override
     76     public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
     77         Expression scope = wrappedNode.getScope();
     78         if (wrappedNode.getName().toString().equals(name)) {
     79             ResolvedType typeOfScope = JavaParserFacade.get(typeSolver).getType(scope);
     80             if (typeOfScope.isArray() && name.equals(ARRAY_LENGTH_FIELD_NAME)) {
     81                 return Optional.of(new Value(ResolvedPrimitiveType.INT, ARRAY_LENGTH_FIELD_NAME));
     82             }
     83             if (typeOfScope.isReferenceType()) {
     84                 Optional<ResolvedType> typeUsage = typeOfScope.asReferenceType().getFieldType(name);
     85                 return typeUsage.map(resolvedType -> new Value(resolvedType, name));
     86             } else {
     87                 return Optional.empty();
     88             }
     89         } else {
     90             return getParent().solveSymbolAsValue(name, typeSolver);
     91         }
     92     }
     93 
     94     public SymbolReference<ResolvedFieldDeclaration> solveField(String name, TypeSolver typeSolver) {
     95         Collection<ResolvedReferenceTypeDeclaration> rrtds = findTypeDeclarations(Optional.of(wrappedNode.getScope()), typeSolver);
     96         for (ResolvedReferenceTypeDeclaration rrtd : rrtds) {
     97             try {
     98                 return SymbolReference.solved(rrtd.getField(wrappedNode.getName().getId()));
     99             } catch (Throwable t) {
    100             }
    101         }
    102         return SymbolReference.unsolved(ResolvedFieldDeclaration.class);
    103     }
    104 }
    105