private Optional<MethodUsage> solveMethodAsUsage(ResolvedReferenceType refType, String name,
                                                     List<ResolvedType> argumentsTypes, TypeSolver typeSolver,
                                                     Context invokationContext) {
        Optional<MethodUsage> ref = ContextHelper.solveMethodAsUsage(refType.getTypeDeclaration(), name, argumentsTypes, typeSolver, invokationContext, refType.typeParametersValues());
        if (ref.isPresent()) {
            MethodUsage methodUsage = ref.get();

            methodUsage = resolveMethodTypeParametersFromExplicitList(typeSolver, methodUsage);

            // At this stage I should derive from the context and the value some information on the type parameters
            // for example, when calling:
            // myStream.collect(Collectors.toList())
            // I should be able to figure out that considering the type of the stream (e.g., Stream<String>)
            // and considering that Stream has this method:
            //
            // <R,A> R collect(Collector<? super T,A,R> collector)
            //
            // and collector has this method:
            //
            // static <T> Collector<T,?,List<T>>   toList()
            //
            // In this case collect.R has to be equal to List<toList.T>
            // And toList.T has to be equal to ? super Stream.T
            // Therefore R has to be equal to List<? super Stream.T>.
            // In our example Stream.T equal to String, so the R (and the result of the call to collect) is
            // List<? super String>

            Map<ResolvedTypeParameterDeclaration, ResolvedType> derivedValues = new HashMap<>();
            for (int i = 0; i < methodUsage.getParamTypes().size(); i++) {
                ResolvedParameterDeclaration parameter = methodUsage.getDeclaration().getParam(i);
                ResolvedType parameterType = parameter.getType();
                if (parameter.isVariadic()) {
                	parameterType = parameterType.asArrayType().getComponentType();
                }
                inferTypes(argumentsTypes.get(i), parameterType, derivedValues);
            }

            for (Map.Entry<ResolvedTypeParameterDeclaration, ResolvedType> entry : derivedValues.entrySet()){
                methodUsage = methodUsage.replaceTypeParameter(entry.getKey(), entry.getValue());
            }

            ResolvedType returnType = refType.useThisTypeParametersOnTheGivenType(methodUsage.returnType());
            if (returnType != methodUsage.returnType()) {
                methodUsage = methodUsage.replaceReturnType(returnType);
            }
            for (int i = 0; i < methodUsage.getParamTypes().size(); i++) {
                ResolvedType replaced = refType.useThisTypeParametersOnTheGivenType(methodUsage.getParamTypes().get(i));
                methodUsage = methodUsage.replaceParamType(i, replaced);
            }
            return Optional.of(methodUsage);
        } else {
            return ref;
        }
    }
private Optional<MethodUsage> solveMethodAsUsage(ResolvedReferenceType refType, String name,
                                                     List<ResolvedType> argumentsTypes, TypeSolver typeSolver,
                                                     Context invokationContext) {
        Optional<MethodUsage> ref = ContextHelper.solveMethodAsUsage(refType.getTypeDeclaration(), name, argumentsTypes, typeSolver, invokationContext, refType.typeParametersValues());
        if (ref.isPresent()) {
            MethodUsage methodUsage = ref.get();

            methodUsage = resolveMethodTypeParametersFromExplicitList(typeSolver, methodUsage);

            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            

            Map<ResolvedTypeParameterDeclaration, ResolvedType> derivedValues = new HashMap<>();
            for (int i = 0; i < methodUsage.getParamTypes().size(); i++) {
                ResolvedParameterDeclaration parameter = methodUsage.getDeclaration().getParam(i);
                ResolvedType parameterType = parameter.getType();
                if (parameter.isVariadic()) {
                	parameterType = parameterType.asArrayType().getComponentType();
                }
                inferTypes(argumentsTypes.get(i), parameterType, derivedValues);
            }

            for (Map.Entry<ResolvedTypeParameterDeclaration, ResolvedType> entry : derivedValues.entrySet()){
                methodUsage = methodUsage.replaceTypeParameter(entry.getKey(), entry.getValue());
            }

            ResolvedType returnType = refType.useThisTypeParametersOnTheGivenType(methodUsage.returnType());
            if (returnType != methodUsage.returnType()) {
                methodUsage = methodUsage.replaceReturnType(returnType);
            }
            for (int i = 0; i < methodUsage.getParamTypes().size(); i++) {
                ResolvedType replaced = refType.useThisTypeParametersOnTheGivenType(methodUsage.getParamTypes().get(i));
                methodUsage = methodUsage.replaceParamType(i, replaced);
            }
            return Optional.of(methodUsage);
        } else {
            return ref;
        }
    }
private Optional < MethodUsage > solveMethodAsUsage ( ResolvedReferenceType refType , String name , List < ResolvedType > argumentsTypes , TypeSolver typeSolver , Context invokationContext ) { Optional < MethodUsage > ref = ContextHelper . solveMethodAsUsage ( refType . getTypeDeclaration ( ) , name , argumentsTypes , typeSolver , invokationContext , refType . typeParametersValues ( ) ) ; if ( ref . isPresent ( ) ) { MethodUsage methodUsage = ref . get ( ) ; methodUsage = resolveMethodTypeParametersFromExplicitList ( typeSolver , methodUsage ) ; // At this stage I should derive from the context and the value some information on the type parameters // for example, when calling: // myStream.collect(Collectors.toList()) // I should be able to figure out that considering the type of the stream (e.g., Stream<String>) // and considering that Stream has this method: // // <R,A> R collect(Collector<? super T,A,R> collector) // // and collector has this method: // // static <T> Collector<T,?,List<T>>   toList() // // In this case collect.R has to be equal to List<toList.T> // And toList.T has to be equal to ? super Stream.T // Therefore R has to be equal to List<? super Stream.T>. // In our example Stream.T equal to String, so the R (and the result of the call to collect) is // List<? super String> Map < ResolvedTypeParameterDeclaration , ResolvedType > derivedValues = new HashMap <> ( ) ; for ( int i = 0 ; i < methodUsage . getParamTypes ( ) . size ( ) ; i ++ ) { ResolvedParameterDeclaration parameter = methodUsage . getDeclaration ( ) . getParam ( i ) ; ResolvedType parameterType = parameter . getType ( ) ; if ( parameter . isVariadic ( ) ) { parameterType = parameterType . asArrayType ( ) . getComponentType ( ) ; } inferTypes ( argumentsTypes . get ( i ) , parameterType , derivedValues ) ; } for ( Map . Entry < ResolvedTypeParameterDeclaration , ResolvedType > entry : derivedValues . entrySet ( ) ) { methodUsage = methodUsage . replaceTypeParameter ( entry . getKey ( ) , entry . getValue ( ) ) ; } ResolvedType returnType = refType . useThisTypeParametersOnTheGivenType ( methodUsage . returnType ( ) ) ; if ( returnType != methodUsage . returnType ( ) ) { methodUsage = methodUsage . replaceReturnType ( returnType ) ; } for ( int i = 0 ; i < methodUsage . getParamTypes ( ) . size ( ) ; i ++ ) { ResolvedType replaced = refType . useThisTypeParametersOnTheGivenType ( methodUsage . getParamTypes ( ) . get ( i ) ) ; methodUsage = methodUsage . replaceParamType ( i , replaced ) ; } return Optional . of ( methodUsage ) ; } else { return ref ; } }
/
/