1683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti/* 2683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * Copyright 2016 Federico Tomassetti 3683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * 4683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * Licensed under the Apache License, Version 2.0 (the "License"); 5683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * you may not use this file except in compliance with the License. 6683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * You may obtain a copy of the License at 7683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * 8683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * http://www.apache.org/licenses/LICENSE-2.0 9683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * 10683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * Unless required by applicable law or agreed to in writing, software 11683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * distributed under the License is distributed on an "AS IS" BASIS, 12683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * See the License for the specific language governing permissions and 14683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti * limitations under the License. 15683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti */ 16683012de2a3a28358e848f8b145d462eb8b322baFederico Tomassetti 179c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettipackage com.github.javaparser.symbolsolver.resolution; 18d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti 19223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassettiimport com.github.javaparser.resolution.MethodAmbiguityException; 205d8d0cb7947efcf2282f7d056302dd905f348532Federico Tomassettiimport com.github.javaparser.resolution.MethodUsage; 21e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassettiimport com.github.javaparser.resolution.declarations.*; 22e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassettiimport com.github.javaparser.resolution.types.*; 239c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettiimport com.github.javaparser.symbolsolver.core.resolution.Context; 2416720991418fda8f29abd4888fd1a5969f99d259malte_langkabelimport com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserAnonymousClassDeclaration; 259c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettiimport com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration; 269c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettiimport com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserEnumDeclaration; 279c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettiimport com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration; 289c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettiimport com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserMethodDeclaration; 299c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettiimport com.github.javaparser.symbolsolver.javassistmodel.JavassistClassDeclaration; 30c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoideimport com.github.javaparser.symbolsolver.javassistmodel.JavassistEnumDeclaration; 319c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettiimport com.github.javaparser.symbolsolver.javassistmodel.JavassistInterfaceDeclaration; 321e7780e554428a10c73de88ca64e5933b2291593Federico Tomassettiimport com.github.javaparser.symbolsolver.model.resolution.SymbolReference; 339c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettiimport com.github.javaparser.symbolsolver.model.resolution.TypeSolver; 34cb5ffb7fdd56f1b768d25da330fa3b29ecb74eafFederico Tomassettiimport com.github.javaparser.symbolsolver.model.typesystem.*; 359c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettiimport com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration; 36c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoideimport com.github.javaparser.symbolsolver.reflectionmodel.ReflectionEnumDeclaration; 379c53c2cbc607ea694438ade8630be0c155a33162Federico Tomassettiimport com.github.javaparser.symbolsolver.reflectionmodel.ReflectionInterfaceDeclaration; 38630eb94d43670f2080c7273584d49c0b0d4162f1Federico Tomassetti 39cb5ffb7fdd56f1b768d25da330fa3b29ecb74eafFederico Tomassettiimport java.util.*; 40cb5ffb7fdd56f1b768d25da330fa3b29ecb74eafFederico Tomassettiimport java.util.stream.Collectors; 41cb5ffb7fdd56f1b768d25da330fa3b29ecb74eafFederico Tomassetti 42a7803cf050435e3162f7fdde83fb9692a891e92eFederico Tomassetti/** 43a7803cf050435e3162f7fdde83fb9692a891e92eFederico Tomassetti * @author Federico Tomassetti 44a7803cf050435e3162f7fdde83fb9692a891e92eFederico Tomassetti */ 45d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassettipublic class MethodResolutionLogic { 46d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti 47e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti private static List<ResolvedType> groupVariadicParamValues(List<ResolvedType> argumentsTypes, int startVariadic, ResolvedType variadicType) { 48e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti List<ResolvedType> res = new ArrayList<>(argumentsTypes.subList(0, startVariadic)); 49e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti List<ResolvedType> variadicValues = argumentsTypes.subList(startVariadic, argumentsTypes.size()); 50e709c28d4c7d8aa5f4ae1a76c2ca746c244e496fayman abdelghany if (variadicValues.isEmpty()) { 51ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti // TODO if there are no variadic values we should default to the bound of the formal type 52ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti res.add(variadicType); 53ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti } else { 54e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType componentType = findCommonType(variadicValues); 55e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti res.add(new ResolvedArrayType(componentType)); 56ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti } 57ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti return res; 58ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti } 59ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti 60e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti private static ResolvedType findCommonType(List<ResolvedType> variadicValues) { 61e709c28d4c7d8aa5f4ae1a76c2ca746c244e496fayman abdelghany if (variadicValues.isEmpty()) { 62ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti throw new IllegalArgumentException(); 63ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti } 64ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti // TODO implement this decently 65ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti return variadicValues.get(0); 66ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti } 67ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti 68e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti public static boolean isApplicable(ResolvedMethodDeclaration method, String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver) { 6988db8b2a8b93bcc692cb8fd5085ba68b8bcf1968Federico Tomassetti return isApplicable(method, name, argumentsTypes, typeSolver, false); 70c48864ccaea00039c2f6a8390d21cffd3fbde054Federico Tomassetti } 71c48864ccaea00039c2f6a8390d21cffd3fbde054Federico Tomassetti 72e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti private static boolean isApplicable(ResolvedMethodDeclaration method, String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver, boolean withWildcardTolerance) { 73d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti if (!method.getName().equals(name)) { 74d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti return false; 75d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti } 76ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti if (method.hasVariadicParameter()) { 77b32947e8c85bc21fe533173f50d4a0a91036fdafFederico Tomassetti int pos = method.getNumberOfParams() - 1; 78b32947e8c85bc21fe533173f50d4a0a91036fdafFederico Tomassetti if (method.getNumberOfParams() == argumentsTypes.size()) { 79ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti // check if the last value is directly assignable as an array 80e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType expectedType = method.getLastParam().getType(); 81e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType actualType = argumentsTypes.get(pos); 82ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti if (!expectedType.isAssignableBy(actualType)) { 83e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti for (ResolvedTypeParameterDeclaration tp : method.getTypeParameters()) { 84ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti expectedType = replaceTypeParam(expectedType, tp, typeSolver); 85ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti } 86ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti if (!expectedType.isAssignableBy(actualType)) { 87051dbd94c17c4f142d3fe9e8fbd03c29d09ace54Federico Tomassetti if (actualType.isArray() && expectedType.isAssignableBy(actualType.asArrayType().getComponentType())) { 8888db8b2a8b93bcc692cb8fd5085ba68b8bcf1968Federico Tomassetti argumentsTypes.set(pos, actualType.asArrayType().getComponentType()); 89b20f28d6034a54108c056947c631c360fa079138Federico Tomassetti } else { 9088db8b2a8b93bcc692cb8fd5085ba68b8bcf1968Federico Tomassetti argumentsTypes = groupVariadicParamValues(argumentsTypes, pos, method.getLastParam().getType()); 91b20f28d6034a54108c056947c631c360fa079138Federico Tomassetti } 92ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti } 93ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti } // else it is already assignable, nothing to do 94ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti } else { 95c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide if (pos > argumentsTypes.size()) { 96c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide return false; 97c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide } 9888db8b2a8b93bcc692cb8fd5085ba68b8bcf1968Federico Tomassetti argumentsTypes = groupVariadicParamValues(argumentsTypes, pos, method.getLastParam().getType()); 99ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti } 100ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti } 101ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti 102b32947e8c85bc21fe533173f50d4a0a91036fdafFederico Tomassetti if (method.getNumberOfParams() != argumentsTypes.size()) { 103d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti return false; 104d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti } 105e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti Map<String, ResolvedType> matchedParameters = new HashMap<>(); 106c48864ccaea00039c2f6a8390d21cffd3fbde054Federico Tomassetti boolean needForWildCardTolerance = false; 107b32947e8c85bc21fe533173f50d4a0a91036fdafFederico Tomassetti for (int i = 0; i < method.getNumberOfParams(); i++) { 108e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType expectedType = method.getParam(i).getType(); 109e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType actualType = argumentsTypes.get(i); 11069e724f5a168e148ea4479c872cfbf656fce8accFederico Tomassetti if ((expectedType.isTypeVariable() && !(expectedType.isWildcard())) && expectedType.asTypeParameter().declaredOnMethod()) { 1116e654694b8d141fd5503b46f9e77b8763cfa9a81Federico Tomassetti matchedParameters.put(expectedType.asTypeParameter().getName(), actualType); 1126e654694b8d141fd5503b46f9e77b8763cfa9a81Federico Tomassetti continue; 1136e654694b8d141fd5503b46f9e77b8763cfa9a81Federico Tomassetti } 114e3e4b88ee821fdcec76aa3c940cb4b4f466bc2cdFederico Tomassetti boolean isAssignableWithoutSubstitution = expectedType.isAssignableBy(actualType) || 115e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti (method.getParam(i).isVariadic() && new ResolvedArrayType(expectedType).isAssignableBy(actualType)); 1163337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti if (!isAssignableWithoutSubstitution && expectedType.isReferenceType() && actualType.isReferenceType()) { 1173337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti isAssignableWithoutSubstitution = isAssignableMatchTypeParameters( 118051dbd94c17c4f142d3fe9e8fbd03c29d09ace54Federico Tomassetti expectedType.asReferenceType(), 119051dbd94c17c4f142d3fe9e8fbd03c29d09ace54Federico Tomassetti actualType.asReferenceType(), 1203337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti matchedParameters); 1213337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti } 122558fc9b4f808d718b9b266071078752ba68d4203Federico Tomassetti if (!isAssignableWithoutSubstitution) { 123e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti List<ResolvedTypeParameterDeclaration> typeParameters = method.getTypeParameters(); 124e2cc24a4f5a54a058c1d9ba971b7c8aa0a445601malte_langkabel typeParameters.addAll(method.declaringType().getTypeParameters()); 125e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti for (ResolvedTypeParameterDeclaration tp : typeParameters) { 126eec165d9e3ef0ab1d93f69a231964984a3379762Federico Tomassetti expectedType = replaceTypeParam(expectedType, tp, typeSolver); 127558fc9b4f808d718b9b266071078752ba68d4203Federico Tomassetti } 128f821be8dfe72fcd3f4e14f75420617b87ddb8689Federico Tomassetti 1290b419e87200878fe13db395a415efc4d1338cef2Federico Tomassetti if (!expectedType.isAssignableBy(actualType)) { 130c48864ccaea00039c2f6a8390d21cffd3fbde054Federico Tomassetti if (actualType.isWildcard() && withWildcardTolerance && !expectedType.isPrimitive()) { 131c48864ccaea00039c2f6a8390d21cffd3fbde054Federico Tomassetti needForWildCardTolerance = true; 132c48864ccaea00039c2f6a8390d21cffd3fbde054Federico Tomassetti continue; 133c48864ccaea00039c2f6a8390d21cffd3fbde054Federico Tomassetti } 134b32947e8c85bc21fe533173f50d4a0a91036fdafFederico Tomassetti if (method.hasVariadicParameter() && i == method.getNumberOfParams() - 1) { 135e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti if (new ResolvedArrayType(expectedType).isAssignableBy(actualType)) { 136b20f28d6034a54108c056947c631c360fa079138Federico Tomassetti continue; 137b20f28d6034a54108c056947c631c360fa079138Federico Tomassetti } 138b20f28d6034a54108c056947c631c360fa079138Federico Tomassetti } 139558fc9b4f808d718b9b266071078752ba68d4203Federico Tomassetti return false; 140558fc9b4f808d718b9b266071078752ba68d4203Federico Tomassetti } 141d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti } 142d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti } 143c48864ccaea00039c2f6a8390d21cffd3fbde054Federico Tomassetti return !withWildcardTolerance || needForWildCardTolerance; 144d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti } 145d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti 146e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti public static boolean isAssignableMatchTypeParameters(ResolvedType expected, ResolvedType actual, 147e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti Map<String, ResolvedType> matchedParameters) { 14869e724f5a168e148ea4479c872cfbf656fce8accFederico Tomassetti if (expected.isReferenceType() && actual.isReferenceType()) { 14969e724f5a168e148ea4479c872cfbf656fce8accFederico Tomassetti return isAssignableMatchTypeParameters(expected.asReferenceType(), actual.asReferenceType(), matchedParameters); 15069e724f5a168e148ea4479c872cfbf656fce8accFederico Tomassetti } else if (expected.isTypeVariable()) { 15169e724f5a168e148ea4479c872cfbf656fce8accFederico Tomassetti matchedParameters.put(expected.asTypeParameter().getName(), actual); 15269e724f5a168e148ea4479c872cfbf656fce8accFederico Tomassetti return true; 15369e724f5a168e148ea4479c872cfbf656fce8accFederico Tomassetti } else { 1541e7780e554428a10c73de88ca64e5933b2291593Federico Tomassetti throw new UnsupportedOperationException(expected.getClass().getCanonicalName() + " " + actual.getClass().getCanonicalName()); 15569e724f5a168e148ea4479c872cfbf656fce8accFederico Tomassetti } 15669e724f5a168e148ea4479c872cfbf656fce8accFederico Tomassetti } 15769e724f5a168e148ea4479c872cfbf656fce8accFederico Tomassetti 158e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti public static boolean isAssignableMatchTypeParameters(ResolvedReferenceType expected, ResolvedReferenceType actual, 159e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti Map<String, ResolvedType> matchedParameters) { 1603337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti if (actual.getQualifiedName().equals(expected.getQualifiedName())) { 1613337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti return isAssignableMatchTypeParametersMatchingQName(expected, actual, matchedParameters); 1623337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti } else { 163e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti List<ResolvedReferenceType> ancestors = actual.getAllAncestors(); 164e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti for (ResolvedReferenceType ancestor : ancestors) { 1653337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti if (isAssignableMatchTypeParametersMatchingQName(expected, ancestor, matchedParameters)) { 1663337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti return true; 1673337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti } 1683337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti } 1693337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti } 1703337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti return false; 1713337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti } 1723337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti 173e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti private static boolean isAssignableMatchTypeParametersMatchingQName(ResolvedReferenceType expected, ResolvedReferenceType actual, 174e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti Map<String, ResolvedType> matchedParameters) { 1753337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti 1763337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti if (!expected.getQualifiedName().equals(actual.getQualifiedName())) { 1773337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti return false; 1783337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti } 17970f3e66c944670a818922f101162226ef604b263Federico Tomassetti if (expected.typeParametersValues().size() != actual.typeParametersValues().size()) { 1803337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti throw new UnsupportedOperationException(); 1813337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti //return true; 1823337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti } 18370f3e66c944670a818922f101162226ef604b263Federico Tomassetti for (int i = 0; i < expected.typeParametersValues().size(); i++) { 184e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType expectedParam = expected.typeParametersValues().get(i); 185e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType actualParam = actual.typeParametersValues().get(i); 18689fe70d234005ccd9479e9c26f8c77d8eb35a6a7xdrop 18789fe70d234005ccd9479e9c26f8c77d8eb35a6a7xdrop // In the case of nested parameterizations eg. List<R> <-> List<Integer> 18889fe70d234005ccd9479e9c26f8c77d8eb35a6a7xdrop // we should peel off one layer and ensure R <-> Integer 18989fe70d234005ccd9479e9c26f8c77d8eb35a6a7xdrop if (expectedParam.isReferenceType() && actualParam.isReferenceType()){ 190e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedReferenceType r1 = expectedParam.asReferenceType(); 191e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedReferenceType r2 = actualParam.asReferenceType(); 19289fe70d234005ccd9479e9c26f8c77d8eb35a6a7xdrop 19389fe70d234005ccd9479e9c26f8c77d8eb35a6a7xdrop return isAssignableMatchTypeParametersMatchingQName(r1, r2, matchedParameters); 19489fe70d234005ccd9479e9c26f8c77d8eb35a6a7xdrop } 19589fe70d234005ccd9479e9c26f8c77d8eb35a6a7xdrop 1963337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti if (expectedParam.isTypeVariable()) { 1973337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti String expectedParamName = expectedParam.asTypeParameter().getName(); 1983337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti if (!actualParam.isTypeVariable() || !actualParam.asTypeParameter().getName().equals(expectedParamName)) { 19904395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel return matchTypeVariable(expectedParam.asTypeVariable(), actualParam, matchedParameters); 2003337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti } 2013337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti } else if (expectedParam.isReferenceType()) { 20204395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel if (actualParam.isTypeVariable()) { 20304395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel return matchTypeVariable(actualParam.asTypeVariable(), expectedParam, matchedParameters); 204c7331319573681ed2251cce3c2ea82348ff4d7c6mlangkabel } else if (!expectedParam.equals(actualParam)) { 2053337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti return false; 2063337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti } 20726c12a20f1206e2a1f63c46b6b41c304af8c7389Federico Tomassetti } else if (expectedParam.isWildcard()) { 2081e7780e554428a10c73de88ca64e5933b2291593Federico Tomassetti if (expectedParam.asWildcard().isExtends()) { 20969e724f5a168e148ea4479c872cfbf656fce8accFederico Tomassetti return isAssignableMatchTypeParameters(expectedParam.asWildcard().getBoundedType(), actual, matchedParameters); 21069e724f5a168e148ea4479c872cfbf656fce8accFederico Tomassetti } 21169e724f5a168e148ea4479c872cfbf656fce8accFederico Tomassetti // TODO verify super bound 21226c12a20f1206e2a1f63c46b6b41c304af8c7389Federico Tomassetti return true; 2133337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti } else { 21426c12a20f1206e2a1f63c46b6b41c304af8c7389Federico Tomassetti throw new UnsupportedOperationException(expectedParam.describe()); 2153337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti } 2163337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti } 2173337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti return true; 2183337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti } 2193337bf584f7ef47f4f56b81743ca0d83930763bfFederico Tomassetti 220e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti private static boolean matchTypeVariable(ResolvedTypeVariable typeVariable, ResolvedType type, Map<String, ResolvedType> matchedParameters) { 22104395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel String typeParameterName = typeVariable.asTypeParameter().getName(); 22204395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel if (matchedParameters.containsKey(typeParameterName)) { 223e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType matchedParameter = matchedParameters.get(typeParameterName); 22404395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel if (matchedParameter.isAssignableBy(type)) { 22504395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel return true; 22604395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel } else if (type.isAssignableBy(matchedParameter)) { 22704395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel // update matchedParameters to contain the more general type 22804395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel matchedParameters.put(typeParameterName, type); 22904395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel return true; 23004395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel } 23104395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel return false; 23204395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel } else { 23304395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel matchedParameters.put(typeParameterName, type); 23404395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel } 23504395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel return true; 23604395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel } 23704395d51f29cecbf4d58f8e2e23d7fcbbb1c6d0dmlangkabel 2385d8d0cb7947efcf2282f7d056302dd905f348532Federico Tomassetti public static ResolvedType replaceTypeParam(ResolvedType type, ResolvedTypeParameterDeclaration tp, TypeSolver typeSolver) { 23982eb44707b620803d424188a1eb8708fcaf093cbFederico Tomassetti if (type.isTypeVariable()) { 24082eb44707b620803d424188a1eb8708fcaf093cbFederico Tomassetti if (type.describe().equals(tp.getName())) { 241e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti List<ResolvedTypeParameterDeclaration.Bound> bounds = tp.getBounds(); 242eec165d9e3ef0ab1d93f69a231964984a3379762Federico Tomassetti if (bounds.size() > 1) { 243eec165d9e3ef0ab1d93f69a231964984a3379762Federico Tomassetti throw new UnsupportedOperationException(); 24449719b4acbe10e3714ceb4f7040acac34709f558Federico Tomassetti } else if (bounds.size() == 1) { 245eec165d9e3ef0ab1d93f69a231964984a3379762Federico Tomassetti return bounds.get(0).getType(); 246eec165d9e3ef0ab1d93f69a231964984a3379762Federico Tomassetti } else { 24782eb44707b620803d424188a1eb8708fcaf093cbFederico Tomassetti return new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver); 248eec165d9e3ef0ab1d93f69a231964984a3379762Federico Tomassetti } 249f821be8dfe72fcd3f4e14f75420617b87ddb8689Federico Tomassetti } 25082eb44707b620803d424188a1eb8708fcaf093cbFederico Tomassetti return type; 25182eb44707b620803d424188a1eb8708fcaf093cbFederico Tomassetti } else if (type.isPrimitive()) { 25282eb44707b620803d424188a1eb8708fcaf093cbFederico Tomassetti return type; 25382eb44707b620803d424188a1eb8708fcaf093cbFederico Tomassetti } else if (type.isArray()) { 2545d8d0cb7947efcf2282f7d056302dd905f348532Federico Tomassetti return new ResolvedArrayType(replaceTypeParam(type.asArrayType().getComponentType(), tp, typeSolver)); 25582eb44707b620803d424188a1eb8708fcaf093cbFederico Tomassetti } else if (type.isReferenceType()) { 2565d8d0cb7947efcf2282f7d056302dd905f348532Federico Tomassetti ResolvedReferenceType result = type.asReferenceType(); 257bfed113b416d139de8c5fedb4e39da353e31d992Federico Tomassetti result = result.transformTypeParameters(typeParam -> replaceTypeParam(typeParam, tp, typeSolver)).asReferenceType(); 25881d24cde385d47abd15f9e81cf22ff0413ee5d14Federico Tomassetti return result; 25982eb44707b620803d424188a1eb8708fcaf093cbFederico Tomassetti } else if (type.isWildcard()) { 26082eb44707b620803d424188a1eb8708fcaf093cbFederico Tomassetti if (type.describe().equals(tp.getName())) { 261e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti List<ResolvedTypeParameterDeclaration.Bound> bounds = tp.getBounds(); 262fdf266d3432a99bc960ab57f1294046281148c79Federico Tomassetti if (bounds.size() > 1) { 263fdf266d3432a99bc960ab57f1294046281148c79Federico Tomassetti throw new UnsupportedOperationException(); 264fdf266d3432a99bc960ab57f1294046281148c79Federico Tomassetti } else if (bounds.size() == 1) { 265fdf266d3432a99bc960ab57f1294046281148c79Federico Tomassetti return bounds.get(0).getType(); 266fdf266d3432a99bc960ab57f1294046281148c79Federico Tomassetti } else { 26782eb44707b620803d424188a1eb8708fcaf093cbFederico Tomassetti return new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver); 268fdf266d3432a99bc960ab57f1294046281148c79Federico Tomassetti } 269fdf266d3432a99bc960ab57f1294046281148c79Federico Tomassetti } 27082eb44707b620803d424188a1eb8708fcaf093cbFederico Tomassetti return type; 271ead147279ca0b84d2f479a714943b20cd689e7c7Federico Tomassetti } else { 2721e7780e554428a10c73de88ca64e5933b2291593Federico Tomassetti throw new UnsupportedOperationException("Replacing " + type + ", param " + tp + " with " + type.getClass().getCanonicalName()); 273f821be8dfe72fcd3f4e14f75420617b87ddb8689Federico Tomassetti } 274f821be8dfe72fcd3f4e14f75420617b87ddb8689Federico Tomassetti } 275f821be8dfe72fcd3f4e14f75420617b87ddb8689Federico Tomassetti 2765d8d0cb7947efcf2282f7d056302dd905f348532Federico Tomassetti public static boolean isApplicable(MethodUsage method, String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver) { 27774026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti if (!method.getName().equals(name)) { 27874026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti return false; 27974026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } 28074026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti // TODO Consider varargs 28188db8b2a8b93bcc692cb8fd5085ba68b8bcf1968Federico Tomassetti if (method.getNoParams() != argumentsTypes.size()) { 28274026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti return false; 28374026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } 28449719b4acbe10e3714ceb4f7040acac34709f558Federico Tomassetti for (int i = 0; i < method.getNoParams(); i++) { 285e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType expectedType = method.getParamType(i); 286e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType expectedTypeWithoutSubstitutions = expectedType; 287e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType expectedTypeWithInference = method.getParamType(i); 288e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType actualType = argumentsTypes.get(i); 2891e7780e554428a10c73de88ca64e5933b2291593Federico Tomassetti 290e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti List<ResolvedTypeParameterDeclaration> typeParameters = method.getDeclaration().getTypeParameters(); 29101f3fa874fcd280adfedc4b3807f0ce7e40535d2malte_langkabel typeParameters.addAll(method.declaringType().getTypeParameters()); 292acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 293acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (expectedType.describe().equals(actualType.describe())){ 294acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return true; 295acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 296acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 297e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti Map<ResolvedTypeParameterDeclaration, ResolvedType> derivedValues = new HashMap<>(); 298acdac6790f4424f8097b3aa6c888e825cac485f9xdrop for (int j = 0; j < method.getParamTypes().size(); j++) { 299e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedParameterDeclaration parameter = method.getDeclaration().getParam(i); 300e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType parameterType = parameter.getType(); 301acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (parameter.isVariadic()) { 302acdac6790f4424f8097b3aa6c888e825cac485f9xdrop parameterType = parameterType.asArrayType().getComponentType(); 303acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 304acdac6790f4424f8097b3aa6c888e825cac485f9xdrop inferTypes(argumentsTypes.get(j), parameterType, derivedValues); 305acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 306acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 307e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti for (Map.Entry<ResolvedTypeParameterDeclaration, ResolvedType> entry : derivedValues.entrySet()){ 308e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedTypeParameterDeclaration tp = entry.getKey(); 309acdac6790f4424f8097b3aa6c888e825cac485f9xdrop expectedTypeWithInference = expectedTypeWithInference.replaceTypeVariables(tp, entry.getValue()); 310acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 311acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 312e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti for (ResolvedTypeParameterDeclaration tp : typeParameters) { 313e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti if (tp.getBounds().isEmpty()) { 314631896a1d2f34eed89c41cc717f463ebbd69e401Federico Tomassetti //expectedType = expectedType.replaceTypeVariables(tp.getName(), new ReferenceTypeUsageImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver)); 315e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti expectedType = expectedType.replaceTypeVariables(tp, ResolvedWildcard.extendsBound(new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver))); 316e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti } else if (tp.getBounds().size() == 1) { 317e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedTypeParameterDeclaration.Bound bound = tp.getBounds().get(0); 318a6849db3884e47909d2d97fcac0b057ab13d544bFederico Tomassetti if (bound.isExtends()) { 319631896a1d2f34eed89c41cc717f463ebbd69e401Federico Tomassetti //expectedType = expectedType.replaceTypeVariables(tp.getName(), bound.getType()); 320e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti expectedType = expectedType.replaceTypeVariables(tp, ResolvedWildcard.extendsBound(bound.getType())); 321a6849db3884e47909d2d97fcac0b057ab13d544bFederico Tomassetti } else { 322631896a1d2f34eed89c41cc717f463ebbd69e401Federico Tomassetti //expectedType = expectedType.replaceTypeVariables(tp.getName(), new ReferenceTypeUsageImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver)); 323e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti expectedType = expectedType.replaceTypeVariables(tp, ResolvedWildcard.superBound(bound.getType())); 324454904fe0cb3b15aa506e3f5fa8f0c9fb1313f61Federico Tomassetti } 325454904fe0cb3b15aa506e3f5fa8f0c9fb1313f61Federico Tomassetti } else { 326454904fe0cb3b15aa506e3f5fa8f0c9fb1313f61Federico Tomassetti throw new UnsupportedOperationException(); 327454904fe0cb3b15aa506e3f5fa8f0c9fb1313f61Federico Tomassetti } 328454904fe0cb3b15aa506e3f5fa8f0c9fb1313f61Federico Tomassetti } 329e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType expectedType2 = expectedTypeWithoutSubstitutions; 330e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti for (ResolvedTypeParameterDeclaration tp : typeParameters) { 331e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti if (tp.getBounds().isEmpty()) { 332631896a1d2f34eed89c41cc717f463ebbd69e401Federico Tomassetti expectedType2 = expectedType2.replaceTypeVariables(tp, new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver)); 333e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti } else if (tp.getBounds().size() == 1) { 334e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedTypeParameterDeclaration.Bound bound = tp.getBounds().get(0); 335454904fe0cb3b15aa506e3f5fa8f0c9fb1313f61Federico Tomassetti if (bound.isExtends()) { 336631896a1d2f34eed89c41cc717f463ebbd69e401Federico Tomassetti expectedType2 = expectedType2.replaceTypeVariables(tp, bound.getType()); 337454904fe0cb3b15aa506e3f5fa8f0c9fb1313f61Federico Tomassetti } else { 338631896a1d2f34eed89c41cc717f463ebbd69e401Federico Tomassetti expectedType2 = expectedType2.replaceTypeVariables(tp, new ReferenceTypeImpl(typeSolver.solveType(Object.class.getCanonicalName()), typeSolver)); 339a6849db3884e47909d2d97fcac0b057ab13d544bFederico Tomassetti } 340a6849db3884e47909d2d97fcac0b057ab13d544bFederico Tomassetti } else { 341a6849db3884e47909d2d97fcac0b057ab13d544bFederico Tomassetti throw new UnsupportedOperationException(); 342a6849db3884e47909d2d97fcac0b057ab13d544bFederico Tomassetti } 343a6849db3884e47909d2d97fcac0b057ab13d544bFederico Tomassetti } 344bdb0b3525f68c94381a57016bd124db2252c4f74ayman abdelghany if (!expectedType.isAssignableBy(actualType) 345bdb0b3525f68c94381a57016bd124db2252c4f74ayman abdelghany && !expectedType2.isAssignableBy(actualType) 346acdac6790f4424f8097b3aa6c888e825cac485f9xdrop && !expectedTypeWithInference.isAssignableBy(actualType) 347bdb0b3525f68c94381a57016bd124db2252c4f74ayman abdelghany && !expectedTypeWithoutSubstitutions.isAssignableBy(actualType)) { 3481e7780e554428a10c73de88ca64e5933b2291593Federico Tomassetti return false; 34974026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } 35074026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } 35174026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti return true; 35274026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } 35374026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti 354e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti private static List<ResolvedMethodDeclaration> getMethodsWithoutDuplicates(List<ResolvedMethodDeclaration> methods) { 355e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti Set<ResolvedMethodDeclaration> s = new TreeSet<>((m1, m2) -> { 356e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti if (m1 instanceof JavaParserMethodDeclaration && m2 instanceof JavaParserMethodDeclaration && 357e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ((JavaParserMethodDeclaration) m1).getWrappedNode().equals(((JavaParserMethodDeclaration) m2).getWrappedNode())) { 358e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti return 0; 359dfbc101bfbffe83d27776868495634b3e7a256e7malte_langkabel } 360e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti return 1; 361dfbc101bfbffe83d27776868495634b3e7a256e7malte_langkabel }); 362dfbc101bfbffe83d27776868495634b3e7a256e7malte_langkabel s.addAll(methods); 363e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti List<ResolvedMethodDeclaration> res = new ArrayList<>(); 36437576d078d11264fec1a28bbffea400003160b6bFederico Tomassetti Set<String> usedSignatures = new HashSet<>(); 365e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti for (ResolvedMethodDeclaration md : methods) { 36637576d078d11264fec1a28bbffea400003160b6bFederico Tomassetti String signature = md.getQualifiedSignature(); 36737576d078d11264fec1a28bbffea400003160b6bFederico Tomassetti if (!usedSignatures.contains(signature)) { 36837576d078d11264fec1a28bbffea400003160b6bFederico Tomassetti usedSignatures.add(signature); 36937576d078d11264fec1a28bbffea400003160b6bFederico Tomassetti res.add(md); 37037576d078d11264fec1a28bbffea400003160b6bFederico Tomassetti } 37137576d078d11264fec1a28bbffea400003160b6bFederico Tomassetti } 372dfbc101bfbffe83d27776868495634b3e7a256e7malte_langkabel return res; 373dfbc101bfbffe83d27776868495634b3e7a256e7malte_langkabel } 3741e7780e554428a10c73de88ca64e5933b2291593Federico Tomassetti 375a7fa0c3db19bd74be9affdd624447251963b68afFederico Tomassetti /** 376effd4c172ad6e4d60d68a749121a0960040edd63Federico Tomassetti * @param methods we expect the methods to be ordered such that inherited methods are later in the list 377a7fa0c3db19bd74be9affdd624447251963b68afFederico Tomassetti * @param name 37888db8b2a8b93bcc692cb8fd5085ba68b8bcf1968Federico Tomassetti * @param argumentsTypes 379a7fa0c3db19bd74be9affdd624447251963b68afFederico Tomassetti * @param typeSolver 380a7fa0c3db19bd74be9affdd624447251963b68afFederico Tomassetti * @return 381a7fa0c3db19bd74be9affdd624447251963b68afFederico Tomassetti */ 382223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti public static SymbolReference<ResolvedMethodDeclaration> findMostApplicable(List<ResolvedMethodDeclaration> methods, 383223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver) { 384223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti SymbolReference<ResolvedMethodDeclaration> res = findMostApplicable(methods, name, argumentsTypes, typeSolver, false); 385c48864ccaea00039c2f6a8390d21cffd3fbde054Federico Tomassetti if (res.isSolved()) { 386c48864ccaea00039c2f6a8390d21cffd3fbde054Federico Tomassetti return res; 387c48864ccaea00039c2f6a8390d21cffd3fbde054Federico Tomassetti } 38888db8b2a8b93bcc692cb8fd5085ba68b8bcf1968Federico Tomassetti return findMostApplicable(methods, name, argumentsTypes, typeSolver, true); 389c48864ccaea00039c2f6a8390d21cffd3fbde054Federico Tomassetti } 390c48864ccaea00039c2f6a8390d21cffd3fbde054Federico Tomassetti 391223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti public static SymbolReference<ResolvedMethodDeclaration> findMostApplicable(List<ResolvedMethodDeclaration> methods, 392223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver, boolean wildcardTolerance) { 393223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti List<ResolvedMethodDeclaration> applicableMethods = getMethodsWithoutDuplicates(methods).stream().filter((m) -> isApplicable(m, name, argumentsTypes, typeSolver, wildcardTolerance)).collect(Collectors.toList()); 394d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti if (applicableMethods.isEmpty()) { 395e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti return SymbolReference.unsolved(ResolvedMethodDeclaration.class); 396d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti } 397acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 398936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide if (applicableMethods.size() > 1) { 399936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide List<Integer> nullParamIndexes = new ArrayList<>(); 400936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide for (int i = 0; i < argumentsTypes.size(); i++) { 401936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide if (argumentsTypes.get(i).isNull()) { 402936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide nullParamIndexes.add(i); 403936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide } 404936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide } 405936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide if (!nullParamIndexes.isEmpty()) { 406936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide // remove method with array param if a non array exists and arg is null 407223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti Set<ResolvedMethodDeclaration> removeCandidates = new HashSet<>(); 408936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide for (Integer nullParamIndex: nullParamIndexes) { 409223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti for (ResolvedMethodDeclaration methDecl: applicableMethods) { 410936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide if (methDecl.getParam(nullParamIndex.intValue()).getType().isArray()) { 411936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide removeCandidates.add(methDecl); 412936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide } 413936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide } 414936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide } 415936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide if (!removeCandidates.isEmpty() && removeCandidates.size() < applicableMethods.size()) { 416936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide applicableMethods.removeAll(removeCandidates); 417936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide } 418936b3bf34af0bbdfd804c9f69c7a52b654cf6e1eFred Lefévère-Laoide } 419c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide } 420d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti if (applicableMethods.size() == 1) { 421d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti return SymbolReference.solved(applicableMethods.get(0)); 422d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti } else { 423223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti ResolvedMethodDeclaration winningCandidate = applicableMethods.get(0); 424223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti ResolvedMethodDeclaration other = null; 425c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide boolean possibleAmbiguity = false; 42649719b4acbe10e3714ceb4f7040acac34709f558Federico Tomassetti for (int i = 1; i < applicableMethods.size(); i++) { 427c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide other = applicableMethods.get(i); 428acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (isMoreSpecific(winningCandidate, other, argumentsTypes, typeSolver)) { 429c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide possibleAmbiguity = false; 430acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } else if (isMoreSpecific(other, winningCandidate, argumentsTypes, typeSolver)) { 431c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide possibleAmbiguity = false; 43227bee3fd5da7ae397014a33e4365608f77d04485Federico Tomassetti winningCandidate = other; 43327bee3fd5da7ae397014a33e4365608f77d04485Federico Tomassetti } else { 434a7fa0c3db19bd74be9affdd624447251963b68afFederico Tomassetti if (winningCandidate.declaringType().getQualifiedName().equals(other.declaringType().getQualifiedName())) { 435c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide possibleAmbiguity = true; 436a7fa0c3db19bd74be9affdd624447251963b68afFederico Tomassetti } else { 437a7fa0c3db19bd74be9affdd624447251963b68afFederico Tomassetti // we expect the methods to be ordered such that inherited methods are later in the list 438a7fa0c3db19bd74be9affdd624447251963b68afFederico Tomassetti } 43927bee3fd5da7ae397014a33e4365608f77d04485Federico Tomassetti } 44027bee3fd5da7ae397014a33e4365608f77d04485Federico Tomassetti } 441c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide if (possibleAmbiguity) { 442c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide // pick the first exact match if it exists 443c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide if (!isExactMatch(winningCandidate, argumentsTypes)) { 444c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide if (isExactMatch(other, argumentsTypes)) { 445c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide winningCandidate = other; 446c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide } else { 447c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide throw new MethodAmbiguityException("Ambiguous method call: cannot find a most applicable method: " + winningCandidate + ", " + other); 448c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide } 449c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide } 450c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide } 45127bee3fd5da7ae397014a33e4365608f77d04485Federico Tomassetti return SymbolReference.solved(winningCandidate); 45227bee3fd5da7ae397014a33e4365608f77d04485Federico Tomassetti } 45327bee3fd5da7ae397014a33e4365608f77d04485Federico Tomassetti } 45427bee3fd5da7ae397014a33e4365608f77d04485Federico Tomassetti 455223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti protected static boolean isExactMatch(ResolvedMethodLikeDeclaration method, List<ResolvedType> argumentsTypes) { 456c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide for (int i = 0; i < method.getNumberOfParams(); i++) { 457c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide if (!method.getParam(i).getType().equals(argumentsTypes.get(i))) { 458c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide return false; 459c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide } 460c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide } 461c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide return true; 462c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide } 463c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide 464223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti private static boolean isMoreSpecific(ResolvedMethodDeclaration methodA, ResolvedMethodDeclaration methodB, 465223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti List<ResolvedType> argumentTypes, TypeSolver typeSolver) { 46627bee3fd5da7ae397014a33e4365608f77d04485Federico Tomassetti boolean oneMoreSpecificFound = false; 467b32947e8c85bc21fe533173f50d4a0a91036fdafFederico Tomassetti if (methodA.getNumberOfParams() < methodB.getNumberOfParams()) { 4686e654694b8d141fd5503b46f9e77b8763cfa9a81Federico Tomassetti return true; 4696e654694b8d141fd5503b46f9e77b8763cfa9a81Federico Tomassetti } 470b32947e8c85bc21fe533173f50d4a0a91036fdafFederico Tomassetti if (methodA.getNumberOfParams() > methodB.getNumberOfParams()) { 4716e654694b8d141fd5503b46f9e77b8763cfa9a81Federico Tomassetti return false; 4726e654694b8d141fd5503b46f9e77b8763cfa9a81Federico Tomassetti } 473b32947e8c85bc21fe533173f50d4a0a91036fdafFederico Tomassetti for (int i = 0; i < methodA.getNumberOfParams(); i++) { 474223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti ResolvedType tdA = methodA.getParam(i).getType(); 475223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti ResolvedType tdB = methodB.getParam(i).getType(); 47627bee3fd5da7ae397014a33e4365608f77d04485Federico Tomassetti // B is more specific 477adb02497ed443e836ae552e20bcb11ab8c1ab623Federico Tomassetti if (tdB.isAssignableBy(tdA) && !tdA.isAssignableBy(tdB)) { 478590b94f8538d2c2fc3080c9b606bfaaacebcbde7Federico Tomassetti oneMoreSpecificFound = true; 47927bee3fd5da7ae397014a33e4365608f77d04485Federico Tomassetti } 48027bee3fd5da7ae397014a33e4365608f77d04485Federico Tomassetti // A is more specific 481adb02497ed443e836ae552e20bcb11ab8c1ab623Federico Tomassetti if (tdA.isAssignableBy(tdB) && !tdB.isAssignableBy(tdA)) { 482590b94f8538d2c2fc3080c9b606bfaaacebcbde7Federico Tomassetti return false; 48327bee3fd5da7ae397014a33e4365608f77d04485Federico Tomassetti } 484acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 485acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 486acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (!oneMoreSpecificFound) { 487acdac6790f4424f8097b3aa6c888e825cac485f9xdrop int lastIndex = argumentTypes.size() - 1; 488acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 489acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (methodA.hasVariadicParameter() && !methodB.hasVariadicParameter()) { 490acdac6790f4424f8097b3aa6c888e825cac485f9xdrop // if the last argument is an array then m1 is more specific 491acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (argumentTypes.get(lastIndex).isArray()) { 492acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return true; 493acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 494acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 495acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (!argumentTypes.get(lastIndex).isArray()) { 496acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return false; 497acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 498acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 499acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (!methodA.hasVariadicParameter() && methodB.hasVariadicParameter()) { 500acdac6790f4424f8097b3aa6c888e825cac485f9xdrop // if the last argument is an array and m1 is not variadic then 501acdac6790f4424f8097b3aa6c888e825cac485f9xdrop // it is not more specific 502acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (argumentTypes.get(lastIndex).isArray()) { 503acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return false; 504acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 505acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 506acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (!argumentTypes.get(lastIndex).isArray()) { 507acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return true; 508acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 5096e654694b8d141fd5503b46f9e77b8763cfa9a81Federico Tomassetti } 510d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti } 511acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 51227bee3fd5da7ae397014a33e4365608f77d04485Federico Tomassetti return oneMoreSpecificFound; 513d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti } 514d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti 51574026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti private static boolean isMoreSpecific(MethodUsage methodA, MethodUsage methodB, TypeSolver typeSolver) { 51674026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti boolean oneMoreSpecificFound = false; 51749719b4acbe10e3714ceb4f7040acac34709f558Federico Tomassetti for (int i = 0; i < methodA.getNoParams(); i++) { 518e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType tdA = methodA.getParamType(i); 519e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti ResolvedType tdB = methodB.getParamType(i); 520fb07f9b8b66fdb7aed984f451267c8b02ec976c9Federico Tomassetti 521adb02497ed443e836ae552e20bcb11ab8c1ab623Federico Tomassetti boolean aIsAssignableByB = tdA.isAssignableBy(tdB); 522adb02497ed443e836ae552e20bcb11ab8c1ab623Federico Tomassetti boolean bIsAssignableByA = tdB.isAssignableBy(tdA); 523fb07f9b8b66fdb7aed984f451267c8b02ec976c9Federico Tomassetti 52474026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti // B is more specific 525fb07f9b8b66fdb7aed984f451267c8b02ec976c9Federico Tomassetti if (bIsAssignableByA && !aIsAssignableByB) { 52674026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti oneMoreSpecificFound = true; 52774026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } 52874026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti // A is more specific 529fb07f9b8b66fdb7aed984f451267c8b02ec976c9Federico Tomassetti if (aIsAssignableByB && !bIsAssignableByA) { 53074026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti return false; 53174026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } 53274026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } 53374026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti return oneMoreSpecificFound; 53474026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } 53574026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti 536e15d5a8aa84a34917e4ef47135dfc62e58ea7650Federico Tomassetti public static Optional<MethodUsage> findMostApplicableUsage(List<MethodUsage> methods, String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver) { 53788db8b2a8b93bcc692cb8fd5085ba68b8bcf1968Federico Tomassetti List<MethodUsage> applicableMethods = methods.stream().filter((m) -> isApplicable(m, name, argumentsTypes, typeSolver)).collect(Collectors.toList()); 538acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 53974026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti if (applicableMethods.isEmpty()) { 54074026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti return Optional.empty(); 54174026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } 54274026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti if (applicableMethods.size() == 1) { 54374026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti return Optional.of(applicableMethods.get(0)); 54474026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } else { 54574026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti MethodUsage winningCandidate = applicableMethods.get(0); 54649719b4acbe10e3714ceb4f7040acac34709f558Federico Tomassetti for (int i = 1; i < applicableMethods.size(); i++) { 54774026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti MethodUsage other = applicableMethods.get(i); 54874026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti if (isMoreSpecific(winningCandidate, other, typeSolver)) { 54974026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti // nothing to do 55074026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } else if (isMoreSpecific(other, winningCandidate, typeSolver)) { 55174026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti winningCandidate = other; 55274026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } else { 55374026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti if (winningCandidate.declaringType().getQualifiedName().equals(other.declaringType().getQualifiedName())) { 554283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti if (!areOverride(winningCandidate, other)) { 555283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti throw new MethodAmbiguityException("Ambiguous method call: cannot find a most applicable method: " + winningCandidate + ", " + other + ". First declared in " + winningCandidate.declaringType().getQualifiedName()); 556283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti } 55774026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } else { 55874026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti // we expect the methods to be ordered such that inherited methods are later in the list 559dc04a5a13190654977eb689d85be429b45cb0215Federico Tomassetti //throw new UnsupportedOperationException(); 56074026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } 56174026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } 56274026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } 56374026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti return Optional.of(winningCandidate); 56474026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } 56574026e2be2b8b569f1b1644ecb09456c1729ecc1Federico Tomassetti } 566283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti 567283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti private static boolean areOverride(MethodUsage winningCandidate, MethodUsage other) { 568283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti if (!winningCandidate.getName().equals(other.getName())) { 569283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti return false; 570283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti } 571283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti if (winningCandidate.getNoParams() != other.getNoParams()) { 572283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti return false; 573283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti } 57449719b4acbe10e3714ceb4f7040acac34709f558Federico Tomassetti for (int i = 0; i < winningCandidate.getNoParams(); i++) { 575283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti if (!winningCandidate.getParamTypes().get(i).equals(other.getParamTypes().get(i))) { 576283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti return false; 577283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti } 578283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti } 579283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti return true; 580283204dd5840cb11dd6c73dbbb196e80db79c9a4Federico Tomassetti } 581656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti 582223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti public static SymbolReference<ResolvedMethodDeclaration> solveMethodInType(ResolvedTypeDeclaration typeDeclaration, 583223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver) { 584acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return solveMethodInType(typeDeclaration, name, argumentsTypes, false, typeSolver); 585acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 586acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 587acdac6790f4424f8097b3aa6c888e825cac485f9xdrop /** 588acdac6790f4424f8097b3aa6c888e825cac485f9xdrop * Replace TypeDeclaration.solveMethod 589acdac6790f4424f8097b3aa6c888e825cac485f9xdrop * 590acdac6790f4424f8097b3aa6c888e825cac485f9xdrop * @param typeDeclaration 591acdac6790f4424f8097b3aa6c888e825cac485f9xdrop * @param name 592acdac6790f4424f8097b3aa6c888e825cac485f9xdrop * @param argumentsTypes 593acdac6790f4424f8097b3aa6c888e825cac485f9xdrop * @param staticOnly 594acdac6790f4424f8097b3aa6c888e825cac485f9xdrop * @return 595acdac6790f4424f8097b3aa6c888e825cac485f9xdrop */ 596223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti public static SymbolReference<ResolvedMethodDeclaration> solveMethodInType(ResolvedTypeDeclaration typeDeclaration, 597223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti String name, List<ResolvedType> argumentsTypes, boolean staticOnly, 598223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti TypeSolver typeSolver) { 599656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti if (typeDeclaration instanceof JavaParserClassDeclaration) { 6001e7780e554428a10c73de88ca64e5933b2291593Federico Tomassetti Context ctx = ((JavaParserClassDeclaration) typeDeclaration).getContext(); 60117ac5ada0476c72aa79a2e0c39311e90bfa0fe60xdrop return ctx.solveMethod(name, argumentsTypes, staticOnly, typeSolver); 602656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti } 603656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti if (typeDeclaration instanceof JavaParserInterfaceDeclaration) { 6041e7780e554428a10c73de88ca64e5933b2291593Federico Tomassetti Context ctx = ((JavaParserInterfaceDeclaration) typeDeclaration).getContext(); 60517ac5ada0476c72aa79a2e0c39311e90bfa0fe60xdrop return ctx.solveMethod(name, argumentsTypes, staticOnly, typeSolver); 606656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti } 607656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti if (typeDeclaration instanceof JavaParserEnumDeclaration) { 60888db8b2a8b93bcc692cb8fd5085ba68b8bcf1968Federico Tomassetti if (name.equals("values") && argumentsTypes.isEmpty()) { 609656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti return SymbolReference.solved(new JavaParserEnumDeclaration.ValuesMethod((JavaParserEnumDeclaration) typeDeclaration, typeSolver)); 610656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti } 6111e7780e554428a10c73de88ca64e5933b2291593Federico Tomassetti Context ctx = ((JavaParserEnumDeclaration) typeDeclaration).getContext(); 61217ac5ada0476c72aa79a2e0c39311e90bfa0fe60xdrop return ctx.solveMethod(name, argumentsTypes, staticOnly, typeSolver); 613656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti } 61416720991418fda8f29abd4888fd1a5969f99d259malte_langkabel if (typeDeclaration instanceof JavaParserAnonymousClassDeclaration) { 61516720991418fda8f29abd4888fd1a5969f99d259malte_langkabel Context ctx = ((JavaParserAnonymousClassDeclaration) typeDeclaration).getContext(); 61616720991418fda8f29abd4888fd1a5969f99d259malte_langkabel return ctx.solveMethod(name, argumentsTypes, staticOnly, typeSolver); 61716720991418fda8f29abd4888fd1a5969f99d259malte_langkabel } 618656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti if (typeDeclaration instanceof ReflectionClassDeclaration) { 61917ac5ada0476c72aa79a2e0c39311e90bfa0fe60xdrop return ((ReflectionClassDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly); 620656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti } 621656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti if (typeDeclaration instanceof ReflectionInterfaceDeclaration) { 62217ac5ada0476c72aa79a2e0c39311e90bfa0fe60xdrop return ((ReflectionInterfaceDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly); 623c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide } 624c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide if (typeDeclaration instanceof ReflectionEnumDeclaration) { 62517ac5ada0476c72aa79a2e0c39311e90bfa0fe60xdrop return ((ReflectionEnumDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly); 626656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti } 627656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti if (typeDeclaration instanceof JavassistInterfaceDeclaration) { 62817ac5ada0476c72aa79a2e0c39311e90bfa0fe60xdrop return ((JavassistInterfaceDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly); 629656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti } 630656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti if (typeDeclaration instanceof JavassistClassDeclaration) { 63117ac5ada0476c72aa79a2e0c39311e90bfa0fe60xdrop return ((JavassistClassDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly); 632c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide } 633c990d23490f5c4ac4322119b03d5951b63eef055Fred Lefévère-Laoide if (typeDeclaration instanceof JavassistEnumDeclaration) { 63417ac5ada0476c72aa79a2e0c39311e90bfa0fe60xdrop return ((JavassistEnumDeclaration) typeDeclaration).solveMethod(name, argumentsTypes, staticOnly); 635656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti } 636656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti throw new UnsupportedOperationException(typeDeclaration.getClass().getCanonicalName()); 637656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti } 638656bb37a1dba87d61d24e69f2346f35dbc73d81dFederico Tomassetti 639223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti private static void inferTypes(ResolvedType source, ResolvedType target, Map<ResolvedTypeParameterDeclaration, ResolvedType> mappings) { 640acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 641acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 642acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (source.equals(target)) { 643acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return; 644acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 645acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (source.isReferenceType() && target.isReferenceType()) { 646223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti ResolvedReferenceType sourceRefType = source.asReferenceType(); 647223fc7650a7a3b89b43d81160f40326aaeaa98f1Federico Tomassetti ResolvedReferenceType targetRefType = target.asReferenceType(); 648acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (sourceRefType.getQualifiedName().equals(targetRefType.getQualifiedName())) { 649acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (!sourceRefType.isRawType() && !targetRefType.isRawType()) { 650acdac6790f4424f8097b3aa6c888e825cac485f9xdrop for (int i = 0; i < sourceRefType.typeParametersValues().size(); i++) { 651acdac6790f4424f8097b3aa6c888e825cac485f9xdrop inferTypes(sourceRefType.typeParametersValues().get(i), targetRefType.typeParametersValues().get(i), mappings); 652acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 653acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 654acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 655acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return; 656acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 657acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (source.isReferenceType() && target.isWildcard()) { 658acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (target.asWildcard().isBounded()) { 659acdac6790f4424f8097b3aa6c888e825cac485f9xdrop inferTypes(source, target.asWildcard().getBoundedType(), mappings); 660acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return; 661acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 662acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return; 663acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 664acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (source.isWildcard() && target.isWildcard()) { 665acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return; 666acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 667acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (source.isReferenceType() && target.isTypeVariable()) { 668acdac6790f4424f8097b3aa6c888e825cac485f9xdrop mappings.put(target.asTypeParameter(), source); 669acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return; 670acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 671acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 672acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (source.isWildcard() && target.isReferenceType()){ 673acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (source.asWildcard().isBounded()){ 674acdac6790f4424f8097b3aa6c888e825cac485f9xdrop inferTypes(source.asWildcard().getBoundedType(), target, mappings); 675acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 676acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return; 677acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 678acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 679acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (source.isWildcard() && target.isTypeVariable()) { 680acdac6790f4424f8097b3aa6c888e825cac485f9xdrop mappings.put(target.asTypeParameter(), source); 681acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return; 682acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 683acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (source.isTypeVariable() && target.isTypeVariable()) { 684acdac6790f4424f8097b3aa6c888e825cac485f9xdrop mappings.put(target.asTypeParameter(), source); 685acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return; 686acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 687acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (source.isPrimitive() || target.isPrimitive()) { 688acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return; 689acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 690acdac6790f4424f8097b3aa6c888e825cac485f9xdrop if (source.isNull()) { 691acdac6790f4424f8097b3aa6c888e825cac485f9xdrop return; 692acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 693acdac6790f4424f8097b3aa6c888e825cac485f9xdrop } 694acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 695acdac6790f4424f8097b3aa6c888e825cac485f9xdrop 696d420a496cd03b7e9b5c4cce5074d8a74da69f3cdFederico Tomassetti} 697