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.declarations.common; 18 19 import com.github.javaparser.resolution.MethodUsage; 20 import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; 21 import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; 22 import com.github.javaparser.resolution.types.ResolvedType; 23 import com.github.javaparser.resolution.types.ResolvedTypeVariable; 24 import com.github.javaparser.symbolsolver.core.resolution.Context; 25 import com.github.javaparser.symbolsolver.logic.InferenceContext; 26 import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; 27 import com.github.javaparser.symbolsolver.reflectionmodel.MyObjectProvider; 28 29 import java.util.ArrayList; 30 import java.util.List; 31 import java.util.Optional; 32 33 /** 34 * @author Federico Tomassetti 35 */ 36 public class MethodDeclarationCommonLogic { 37 38 private ResolvedMethodDeclaration methodDeclaration; 39 private TypeSolver typeSolver; 40 41 public MethodDeclarationCommonLogic(ResolvedMethodDeclaration methodDeclaration, TypeSolver typeSolver) { 42 this.methodDeclaration = methodDeclaration; 43 this.typeSolver = typeSolver; 44 } 45 46 public MethodUsage resolveTypeVariables(Context context, List<ResolvedType> parameterTypes) { 47 ResolvedType returnType = replaceTypeParams(methodDeclaration.getReturnType(), typeSolver, context); 48 List<ResolvedType> params = new ArrayList<>(); 49 for (int i = 0; i < methodDeclaration.getNumberOfParams(); i++) { 50 ResolvedType replaced = replaceTypeParams(methodDeclaration.getParam(i).getType(), typeSolver, context); 51 params.add(replaced); 52 } 53 54 // We now look at the type parameter for the method which we can derive from the parameter types 55 // and then we replace them in the return type 56 // Map<TypeParameterDeclaration, Type> determinedTypeParameters = new HashMap<>(); 57 InferenceContext inferenceContext = new InferenceContext(MyObjectProvider.INSTANCE); 58 for (int i = 0; i < methodDeclaration.getNumberOfParams() - (methodDeclaration.hasVariadicParameter() ? 1 : 0); i++) { 59 ResolvedType formalParamType = methodDeclaration.getParam(i).getType(); 60 ResolvedType actualParamType = parameterTypes.get(i); 61 inferenceContext.addPair(formalParamType, actualParamType); 62 } 63 64 returnType = inferenceContext.resolve(inferenceContext.addSingle(returnType)); 65 66 return new MethodUsage(methodDeclaration, params, returnType); 67 } 68 69 private ResolvedType replaceTypeParams(ResolvedType type, TypeSolver typeSolver, Context context) { 70 if (type.isTypeVariable()) { 71 ResolvedTypeParameterDeclaration typeParameter = type.asTypeParameter(); 72 if (typeParameter.declaredOnType()) { 73 Optional<ResolvedType> typeParam = typeParamByName(typeParameter.getName(), typeSolver, context); 74 if (typeParam.isPresent()) { 75 type = typeParam.get(); 76 } 77 } 78 } 79 80 if (type.isReferenceType()) { 81 type.asReferenceType().transformTypeParameters(tp -> replaceTypeParams(tp, typeSolver, context)); 82 } 83 84 return type; 85 } 86 87 protected Optional<ResolvedType> typeParamByName(String name, TypeSolver typeSolver, Context context) { 88 return methodDeclaration.getTypeParameters().stream().filter(tp -> tp.getName().equals(name)).map(tp -> toType(tp)).findFirst(); 89 } 90 91 protected ResolvedType toType(ResolvedTypeParameterDeclaration typeParameterDeclaration) { 92 return new ResolvedTypeVariable(typeParameterDeclaration); 93 } 94 } 95