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.Node;
     20 import com.github.javaparser.ast.body.FieldDeclaration;
     21 import com.github.javaparser.ast.body.Parameter;
     22 import com.github.javaparser.ast.body.VariableDeclarator;
     23 import com.github.javaparser.ast.expr.LambdaExpr;
     24 import com.github.javaparser.ast.expr.MethodCallExpr;
     25 import com.github.javaparser.ast.expr.VariableDeclarationExpr;
     26 import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration;
     27 import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
     28 import com.github.javaparser.resolution.types.ResolvedArrayType;
     29 import com.github.javaparser.resolution.types.ResolvedPrimitiveType;
     30 import com.github.javaparser.resolution.types.ResolvedType;
     31 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
     32 import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory;
     33 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
     34 
     35 import static com.github.javaparser.symbolsolver.javaparser.Navigator.requireParentNode;
     36 
     37 /**
     38  * @author Federico Tomassetti
     39  */
     40 public class JavaParserSymbolDeclaration implements ResolvedValueDeclaration {
     41 
     42     private String name;
     43     private Node wrappedNode;
     44     private boolean field;
     45     private boolean parameter;
     46     private boolean variable;
     47     private TypeSolver typeSolver;
     48 
     49     private JavaParserSymbolDeclaration(Node wrappedNode, String name, TypeSolver typeSolver, boolean field, boolean parameter, boolean variable) {
     50         this.name = name;
     51         this.wrappedNode = wrappedNode;
     52         this.field = field;
     53         this.variable = variable;
     54         this.parameter = parameter;
     55         this.typeSolver = typeSolver;
     56     }
     57 
     58     public static JavaParserFieldDeclaration field(VariableDeclarator wrappedNode, TypeSolver typeSolver) {
     59         return new JavaParserFieldDeclaration(wrappedNode, typeSolver);
     60     }
     61 
     62     public static JavaParserParameterDeclaration parameter(Parameter parameter, TypeSolver typeSolver) {
     63         return new JavaParserParameterDeclaration(parameter, typeSolver);
     64     }
     65 
     66     public static JavaParserSymbolDeclaration localVar(VariableDeclarator variableDeclarator, TypeSolver typeSolver) {
     67         return new JavaParserSymbolDeclaration(variableDeclarator, variableDeclarator.getName().getId(), typeSolver, false, false, true);
     68     }
     69 
     70     public static int getParamPos(Parameter parameter) {
     71         int pos = 0;
     72         for (Node node : requireParentNode(parameter).getChildNodes()) {
     73             if (node == parameter) {
     74                 return pos;
     75             } else if (node instanceof Parameter) {
     76                 pos++;
     77             }
     78         }
     79         return pos;
     80     }
     81 
     82     public static int getParamPos(Node node) {
     83         if (requireParentNode(node) instanceof MethodCallExpr) {
     84             MethodCallExpr call = (MethodCallExpr) requireParentNode(node);
     85             for (int i = 0; i < call.getArguments().size(); i++) {
     86                 if (call.getArguments().get(i) == node) return i;
     87             }
     88             throw new IllegalStateException();
     89         }
     90         throw new IllegalArgumentException();
     91     }
     92 
     93     @Override
     94     public String toString() {
     95         return "JavaParserSymbolDeclaration{" +
     96                 "name='" + name + '\'' +
     97                 ", wrappedNode=" + wrappedNode +
     98                 '}';
     99     }
    100 
    101     @Override
    102     public String getName() {
    103         return name;
    104     }
    105 
    106     @Override
    107     public boolean isField() {
    108         return field;
    109     }
    110 
    111     @Override
    112     public boolean isParameter() {
    113         return parameter;
    114     }
    115 
    116     @Override
    117     public boolean isType() {
    118         return false;
    119     }
    120 
    121     @Override
    122     public ResolvedType getType() {
    123         if (wrappedNode instanceof Parameter) {
    124             Parameter parameter = (Parameter) wrappedNode;
    125             if (requireParentNode(wrappedNode) instanceof LambdaExpr) {
    126                 int pos = getParamPos(parameter);
    127                 ResolvedType lambdaType = JavaParserFacade.get(typeSolver).getType(requireParentNode(wrappedNode));
    128 
    129                 // TODO understand from the context to which method this corresponds
    130                 //MethodDeclaration methodDeclaration = JavaParserFacade.get(typeSolver).getMethodCalled
    131                 //MethodDeclaration methodCalled = JavaParserFacade.get(typeSolver).solve()
    132                 throw new UnsupportedOperationException(wrappedNode.getClass().getCanonicalName());
    133             } else {
    134                 final ResolvedType rawType;
    135                 if (parameter.getType() instanceof com.github.javaparser.ast.type.PrimitiveType) {
    136                     rawType = ResolvedPrimitiveType.byName(((com.github.javaparser.ast.type.PrimitiveType) parameter.getType()).getType().name());
    137                 } else {
    138                     rawType = JavaParserFacade.get(typeSolver).convertToUsage(parameter.getType(), wrappedNode);
    139                 }
    140                 if (parameter.isVarArgs()) {
    141                     return new ResolvedArrayType(rawType);
    142                 }
    143                 return rawType;
    144             }
    145         } else if (wrappedNode instanceof VariableDeclarator) {
    146             VariableDeclarator variableDeclarator = (VariableDeclarator) wrappedNode;
    147             if (requireParentNode(wrappedNode) instanceof VariableDeclarationExpr) {
    148                 return JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), JavaParserFactory.getContext(wrappedNode, typeSolver));
    149             } else if (requireParentNode(wrappedNode) instanceof FieldDeclaration) {
    150                 return JavaParserFacade.get(typeSolver).convert(variableDeclarator.getType(), JavaParserFactory.getContext(wrappedNode, typeSolver));
    151             }
    152         }
    153         throw new UnsupportedOperationException(wrappedNode.getClass().getCanonicalName());
    154     }
    155 
    156     @Override
    157     public ResolvedTypeDeclaration asType() {
    158         throw new UnsupportedOperationException(this.getClass().getCanonicalName() + ": wrapping " + this.getWrappedNode().getClass().getCanonicalName());
    159     }
    160 
    161     /**
    162      * Returns the JavaParser node associated with this JavaParserSymbolDeclaration.
    163      *
    164      * @return A visitable JavaParser node wrapped by this object.
    165      */
    166     public Node getWrappedNode() {
    167         return wrappedNode;
    168     }
    169 
    170 
    171 }
    172