Search in sources :

Example 1 with TypeParameterDeclaration

use of com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration in project javaparser by javaparser.

the class MethodUsage method replaceTypeParameter.

public MethodUsage replaceTypeParameter(TypeParameterDeclaration typeParameter, Type type) {
    if (type == null) {
        throw new IllegalArgumentException();
    }
    // TODO if the method declaration has a type param with that name ignore this call
    MethodUsage res = new MethodUsage(declaration, paramTypes, returnType, typeParametersMap.toBuilder().setValue(typeParameter, type).build());
    Map<TypeParameterDeclaration, Type> inferredTypes = new HashMap<>();
    for (int i = 0; i < paramTypes.size(); i++) {
        Type originalParamType = paramTypes.get(i);
        Type newParamType = originalParamType.replaceTypeVariables(typeParameter, type, inferredTypes);
        res = res.replaceParamType(i, newParamType);
    }
    Type oldReturnType = res.returnType;
    Type newReturnType = oldReturnType.replaceTypeVariables(typeParameter, type, inferredTypes);
    res = res.replaceReturnType(newReturnType);
    return res;
}
Also used : Type(com.github.javaparser.symbolsolver.model.typesystem.Type) TypeParameterDeclaration(com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration)

Example 2 with TypeParameterDeclaration

use of com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration in project javaparser by javaparser.

the class ConstructorResolutionLogic method isApplicable.

private static boolean isApplicable(ConstructorDeclaration constructor, List<Type> argumentsTypes, TypeSolver typeSolver, boolean withWildcardTolerance) {
    if (constructor.hasVariadicParameter()) {
        int pos = constructor.getNumberOfParams() - 1;
        if (constructor.getNumberOfParams() == argumentsTypes.size()) {
            // check if the last value is directly assignable as an array
            Type expectedType = constructor.getLastParam().getType();
            Type actualType = argumentsTypes.get(pos);
            if (!expectedType.isAssignableBy(actualType)) {
                for (TypeParameterDeclaration tp : constructor.getTypeParameters()) {
                    expectedType = MethodResolutionLogic.replaceTypeParam(expectedType, tp, typeSolver);
                }
                if (!expectedType.isAssignableBy(actualType)) {
                    if (actualType.isArray() && expectedType.isAssignableBy(actualType.asArrayType().getComponentType())) {
                        argumentsTypes.set(pos, actualType.asArrayType().getComponentType());
                    } else {
                        argumentsTypes = groupVariadicParamValues(argumentsTypes, pos, constructor.getLastParam().getType());
                    }
                }
            }
        // else it is already assignable, nothing to do
        } else {
            if (pos > argumentsTypes.size()) {
                return false;
            }
            argumentsTypes = groupVariadicParamValues(argumentsTypes, pos, constructor.getLastParam().getType());
        }
    }
    if (constructor.getNumberOfParams() != argumentsTypes.size()) {
        return false;
    }
    Map<String, Type> matchedParameters = new HashMap<>();
    boolean needForWildCardTolerance = false;
    for (int i = 0; i < constructor.getNumberOfParams(); i++) {
        Type expectedType = constructor.getParam(i).getType();
        Type actualType = argumentsTypes.get(i);
        if ((expectedType.isTypeVariable() && !(expectedType.isWildcard())) && expectedType.asTypeParameter().declaredOnMethod()) {
            matchedParameters.put(expectedType.asTypeParameter().getName(), actualType);
            continue;
        }
        boolean isAssignableWithoutSubstitution = expectedType.isAssignableBy(actualType) || (constructor.getParam(i).isVariadic() && new ArrayType(expectedType).isAssignableBy(actualType));
        if (!isAssignableWithoutSubstitution && expectedType.isReferenceType() && actualType.isReferenceType()) {
            isAssignableWithoutSubstitution = MethodResolutionLogic.isAssignableMatchTypeParameters(expectedType.asReferenceType(), actualType.asReferenceType(), matchedParameters);
        }
        if (!isAssignableWithoutSubstitution) {
            List<TypeParameterDeclaration> typeParameters = constructor.getTypeParameters();
            typeParameters.addAll(constructor.declaringType().getTypeParameters());
            for (TypeParameterDeclaration tp : typeParameters) {
                expectedType = MethodResolutionLogic.replaceTypeParam(expectedType, tp, typeSolver);
            }
            if (!expectedType.isAssignableBy(actualType)) {
                if (actualType.isWildcard() && withWildcardTolerance && !expectedType.isPrimitive()) {
                    needForWildCardTolerance = true;
                    continue;
                }
                if (constructor.hasVariadicParameter() && i == constructor.getNumberOfParams() - 1) {
                    if (new ArrayType(expectedType).isAssignableBy(actualType)) {
                        continue;
                    }
                }
                return false;
            }
        }
    }
    return !withWildcardTolerance || needForWildCardTolerance;
}
Also used : ArrayType(com.github.javaparser.symbolsolver.model.typesystem.ArrayType) Type(com.github.javaparser.symbolsolver.model.typesystem.Type) ArrayType(com.github.javaparser.symbolsolver.model.typesystem.ArrayType) TypeParameterDeclaration(com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration) HashMap(java.util.HashMap)

Example 3 with TypeParameterDeclaration

use of com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration in project javaparser by javaparser.

the class ReflectionFactory method typeUsageFor.

public static Type typeUsageFor(java.lang.reflect.Type type, TypeSolver typeSolver) {
    if (type instanceof java.lang.reflect.TypeVariable) {
        java.lang.reflect.TypeVariable<?> tv = (java.lang.reflect.TypeVariable<?>) type;
        boolean declaredOnClass = tv.getGenericDeclaration() instanceof java.lang.reflect.Type;
        TypeParameterDeclaration typeParameter = new ReflectionTypeParameter(tv, declaredOnClass, typeSolver);
        return new com.github.javaparser.symbolsolver.model.typesystem.TypeVariable(typeParameter);
    } else if (type instanceof ParameterizedType) {
        ParameterizedType pt = (ParameterizedType) type;
        ReferenceType rawType = typeUsageFor(pt.getRawType(), typeSolver).asReferenceType();
        List<java.lang.reflect.Type> actualTypes = new ArrayList<>();
        actualTypes.addAll(Arrays.asList(pt.getActualTypeArguments()));
        // we consume the actual types
        rawType = rawType.transformTypeParameters(tp -> typeUsageFor(actualTypes.remove(0), typeSolver)).asReferenceType();
        return rawType;
    } else if (type instanceof Class) {
        Class<?> c = (Class<?>) type;
        if (c.isPrimitive()) {
            if (c.getName().equals(Void.TYPE.getName())) {
                return VoidType.INSTANCE;
            } else {
                return PrimitiveType.byName(c.getName());
            }
        } else if (c.isArray()) {
            return new ArrayType(typeUsageFor(c.getComponentType(), typeSolver));
        } else {
            return new ReferenceTypeImpl(typeDeclarationFor(c, typeSolver), typeSolver);
        }
    } else if (type instanceof GenericArrayType) {
        GenericArrayType genericArrayType = (GenericArrayType) type;
        return new ArrayType(typeUsageFor(genericArrayType.getGenericComponentType(), typeSolver));
    } else if (type instanceof WildcardType) {
        WildcardType wildcardType = (WildcardType) type;
        if (wildcardType.getLowerBounds().length > 0 && wildcardType.getUpperBounds().length > 0) {
            if (wildcardType.getUpperBounds().length == 1 && wildcardType.getUpperBounds()[0].getTypeName().equals("java.lang.Object")) {
            // ok, it does not matter
            }
        }
        if (wildcardType.getLowerBounds().length > 0) {
            if (wildcardType.getLowerBounds().length > 1) {
                throw new UnsupportedOperationException();
            }
            return Wildcard.superBound(typeUsageFor(wildcardType.getLowerBounds()[0], typeSolver));
        }
        if (wildcardType.getUpperBounds().length > 0) {
            if (wildcardType.getUpperBounds().length > 1) {
                throw new UnsupportedOperationException();
            }
            return Wildcard.extendsBound(typeUsageFor(wildcardType.getUpperBounds()[0], typeSolver));
        }
        return Wildcard.UNBOUNDED;
    } else {
        throw new UnsupportedOperationException(type.getClass().getCanonicalName() + " " + type);
    }
}
Also used : GenericArrayType(java.lang.reflect.GenericArrayType) Arrays(java.util.Arrays) List(java.util.List) AccessLevel(com.github.javaparser.symbolsolver.model.declarations.AccessLevel) ParameterizedType(java.lang.reflect.ParameterizedType) TypeParameterDeclaration(com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration) TypeSolver(com.github.javaparser.symbolsolver.model.resolution.TypeSolver) com.github.javaparser.symbolsolver.model.typesystem(com.github.javaparser.symbolsolver.model.typesystem) Modifier(java.lang.reflect.Modifier) WildcardType(java.lang.reflect.WildcardType) ReferenceTypeDeclaration(com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration) ArrayList(java.util.ArrayList) GenericArrayType(java.lang.reflect.GenericArrayType) ParameterizedType(java.lang.reflect.ParameterizedType) GenericArrayType(java.lang.reflect.GenericArrayType) GenericArrayType(java.lang.reflect.GenericArrayType) ParameterizedType(java.lang.reflect.ParameterizedType) WildcardType(java.lang.reflect.WildcardType) WildcardType(java.lang.reflect.WildcardType) TypeParameterDeclaration(com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration) List(java.util.List) ArrayList(java.util.ArrayList)

Example 4 with TypeParameterDeclaration

use of com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration in project javaparser by javaparser.

the class ReflectionMethodResolutionLogic method solveMethodAsUsage.

static Optional<MethodUsage> solveMethodAsUsage(String name, List<Type> argumentsTypes, TypeSolver typeSolver, Context invokationContext, List<Type> typeParameterValues, ReferenceTypeDeclaration scopeType, Class clazz) {
    if (typeParameterValues.size() != scopeType.getTypeParameters().size()) {
        // if it is zero we are going to ignore them
        if (!scopeType.getTypeParameters().isEmpty()) {
            // Parameters not specified, so default to Object
            typeParameterValues = new ArrayList<>();
            for (int i = 0; i < scopeType.getTypeParameters().size(); i++) {
                typeParameterValues.add(new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver));
            }
        }
    }
    List<MethodUsage> methods = new ArrayList<>();
    for (Method method : clazz.getMethods()) {
        if (method.getName().equals(name) && !method.isBridge() && !method.isSynthetic()) {
            MethodDeclaration methodDeclaration = new ReflectionMethodDeclaration(method, typeSolver);
            MethodUsage methodUsage = replaceParams(typeParameterValues, scopeType, methodDeclaration);
            methods.add(methodUsage);
        }
    }
    for (ReferenceType ancestor : scopeType.getAncestors()) {
        SymbolReference<MethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(ancestor.getTypeDeclaration(), name, argumentsTypes, typeSolver);
        if (ref.isSolved()) {
            MethodDeclaration correspondingDeclaration = ref.getCorrespondingDeclaration();
            MethodUsage methodUsage = replaceParams(typeParameterValues, ancestor.getTypeDeclaration(), correspondingDeclaration);
            methods.add(methodUsage);
        }
    }
    if (scopeType.getAncestors().isEmpty()) {
        ReferenceTypeImpl objectClass = new ReferenceTypeImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
        SymbolReference<MethodDeclaration> ref = MethodResolutionLogic.solveMethodInType(objectClass.getTypeDeclaration(), name, argumentsTypes, typeSolver);
        if (ref.isSolved()) {
            MethodUsage usage = replaceParams(typeParameterValues, objectClass.getTypeDeclaration(), ref.getCorrespondingDeclaration());
            methods.add(usage);
        }
    }
    final List<Type> finalTypeParameterValues = typeParameterValues;
    argumentsTypes = argumentsTypes.stream().map((pt) -> {
        int i = 0;
        for (TypeParameterDeclaration tp : scopeType.getTypeParameters()) {
            pt = pt.replaceTypeVariables(tp, finalTypeParameterValues.get(i));
            i++;
        }
        return pt;
    }).collect(Collectors.toList());
    return MethodResolutionLogic.findMostApplicableUsage(methods, name, argumentsTypes, typeSolver);
}
Also used : MethodDeclaration(com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration) ReferenceTypeImpl(com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl) ArrayList(java.util.ArrayList) Method(java.lang.reflect.Method) ReferenceType(com.github.javaparser.symbolsolver.model.typesystem.ReferenceType) ReferenceType(com.github.javaparser.symbolsolver.model.typesystem.ReferenceType) Type(com.github.javaparser.symbolsolver.model.typesystem.Type) TypeParameterDeclaration(com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration) MethodUsage(com.github.javaparser.symbolsolver.model.methods.MethodUsage)

Example 5 with TypeParameterDeclaration

use of com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration in project javaparser by javaparser.

the class MethodCallExprContext method solveMethodAsUsage.

@Override
public Optional<MethodUsage> solveMethodAsUsage(String name, List<Type> argumentsTypes, TypeSolver typeSolver) {
    if (wrappedNode.getScope().isPresent()) {
        Expression scope = wrappedNode.getScope().get();
        // Consider static method calls
        if (scope instanceof NameExpr) {
            String className = ((NameExpr) scope).getName().getId();
            SymbolReference<TypeDeclaration> ref = solveType(className, typeSolver);
            if (ref.isSolved()) {
                SymbolReference<MethodDeclaration> m = MethodResolutionLogic.solveMethodInType(ref.getCorrespondingDeclaration(), name, argumentsTypes, typeSolver);
                if (m.isSolved()) {
                    MethodUsage methodUsage = new MethodUsage(m.getCorrespondingDeclaration());
                    methodUsage = resolveMethodTypeParametersFromExplicitList(typeSolver, methodUsage);
                    methodUsage = resolveMethodTypeParameters(methodUsage, argumentsTypes);
                    return Optional.of(methodUsage);
                } else {
                    throw new UnsolvedSymbolException(ref.getCorrespondingDeclaration().toString(), "Method '" + name + "' with parameterTypes " + argumentsTypes);
                }
            }
        }
        Type typeOfScope = JavaParserFacade.get(typeSolver).getType(scope);
        // we can replace the parameter types from the scope into the typeParametersValues
        Map<TypeParameterDeclaration, Type> inferredTypes = new HashMap<>();
        for (int i = 0; i < argumentsTypes.size(); i++) {
            // by replacing types I can also find new equivalences
            // for example if I replace T=U with String because I know that T=String I can derive that also U equal String
            Type originalArgumentType = argumentsTypes.get(i);
            Type updatedArgumentType = usingParameterTypesFromScope(typeOfScope, originalArgumentType, inferredTypes);
            argumentsTypes.set(i, updatedArgumentType);
        }
        for (int i = 0; i < argumentsTypes.size(); i++) {
            Type updatedArgumentType = applyInferredTypes(argumentsTypes.get(i), inferredTypes);
            argumentsTypes.set(i, updatedArgumentType);
        }
        return solveMethodAsUsage(typeOfScope, name, argumentsTypes, typeSolver, this);
    } else {
        Context parentContext = getParent();
        while (parentContext instanceof MethodCallExprContext) {
            parentContext = parentContext.getParent();
        }
        return parentContext.solveMethodAsUsage(name, argumentsTypes, typeSolver);
    }
}
Also used : UnsolvedSymbolException(com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException) Context(com.github.javaparser.symbolsolver.core.resolution.Context) HashMap(java.util.HashMap) MethodDeclaration(com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration) NameExpr(com.github.javaparser.ast.expr.NameExpr) ArrayType(com.github.javaparser.symbolsolver.model.typesystem.ArrayType) ReferenceType(com.github.javaparser.symbolsolver.model.typesystem.ReferenceType) Type(com.github.javaparser.symbolsolver.model.typesystem.Type) Expression(com.github.javaparser.ast.expr.Expression) TypeParameterDeclaration(com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration) MethodUsage(com.github.javaparser.symbolsolver.model.methods.MethodUsage) TypeDeclaration(com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration)

Aggregations

TypeParameterDeclaration (com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration)9 Type (com.github.javaparser.symbolsolver.model.typesystem.Type)6 MethodUsage (com.github.javaparser.symbolsolver.model.methods.MethodUsage)4 ArrayType (com.github.javaparser.symbolsolver.model.typesystem.ArrayType)4 ReferenceType (com.github.javaparser.symbolsolver.model.typesystem.ReferenceType)4 HashMap (java.util.HashMap)4 MethodDeclaration (com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration)2 ReferenceTypeDeclaration (com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration)2 UnsolvedSymbolException (com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException)2 ArrayList (java.util.ArrayList)2 Expression (com.github.javaparser.ast.expr.Expression)1 NameExpr (com.github.javaparser.ast.expr.NameExpr)1 Context (com.github.javaparser.symbolsolver.core.resolution.Context)1 AccessLevel (com.github.javaparser.symbolsolver.model.declarations.AccessLevel)1 ParameterDeclaration (com.github.javaparser.symbolsolver.model.declarations.ParameterDeclaration)1 TypeDeclaration (com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration)1 TypeSolver (com.github.javaparser.symbolsolver.model.resolution.TypeSolver)1 com.github.javaparser.symbolsolver.model.typesystem (com.github.javaparser.symbolsolver.model.typesystem)1 ReferenceTypeImpl (com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl)1 TypeVariable (com.github.javaparser.symbolsolver.model.typesystem.TypeVariable)1