Search in sources :

Example 1 with JavaMethodInfo

use of com.redhat.qute.commons.JavaMethodInfo in project quarkus-ls by redhat-developer.

the class QuteDiagnostics method validateMethodPart.

/**
 * Validate the given method part.
 *
 * @param part                     the method part to validate.
 * @param ownerSection             the owner section and null otherwise.
 * @param template                 the template.
 * @param projectUri               the project Uri.
 * @param resolutionContext        the resolution context.
 * @param baseType                 the base object type.
 * @param iterableOfType           the iterable of type.
 * @param diagnostics              the diagnostic list to fill.
 * @param resolvingJavaTypeContext the resolving Java type context.
 *
 * @return the Java type returned by the member part and null otherwise.
 */
private ResolvedJavaTypeInfo validateMethodPart(MethodPart methodPart, Section ownerSection, Template template, String projectUri, QuteValidationSettings validationSettings, ResolutionContext resolutionContext, ResolvedJavaTypeInfo resolvedJavaType, ResolvedJavaTypeInfo iter, List<Diagnostic> diagnostics, ResolvingJavaTypeContext resolvingJavaTypeContext) {
    // Validate parameters of the method part
    boolean undefinedType = false;
    List<ResolvedJavaTypeInfo> parameterTypes = new ArrayList<>();
    for (Parameter parameter : methodPart.getParameters()) {
        ResolvedJavaTypeInfo result = null;
        Expression expression = parameter.getJavaTypeExpression();
        if (expression != null) {
            result = validateExpression(expression, ownerSection, template, validationSettings, resolutionContext, resolvingJavaTypeContext, diagnostics);
        }
        if (result == null) {
            undefinedType = true;
        }
        parameterTypes.add(result);
    }
    if (undefinedType) {
        // One of parameter cannot be resolved as type, teh validation is stopped
        return null;
    }
    // All parameters are resolved, validate the existing of method name according
    // to the computed parameter types
    String methodName = methodPart.getPartName();
    String namespace = methodPart.getNamespace();
    JavaMemberResult result = javaCache.findMethod(resolvedJavaType, namespace, methodName, parameterTypes, projectUri);
    JavaMethodInfo method = (JavaMethodInfo) result.getMember();
    if (method == null) {
        QuteErrorCode errorCode = QuteErrorCode.UnknownMethod;
        String arg = null;
        if (namespace != null) {
            // ex :{config.getXXXX()}
            errorCode = QuteErrorCode.UnknownNamespaceResolverMethod;
            arg = namespace;
        } else {
            // ex : {@org.acme.Item item}
            // {item.getXXXX()}
            arg = resolvedJavaType.getSignature();
            InvalidMethodReason reason = javaCache.getInvalidMethodReason(methodName, resolvedJavaType, projectUri);
            if (reason != null) {
                switch(reason) {
                    case VoidReturn:
                        errorCode = QuteErrorCode.InvalidMethodVoid;
                        break;
                    case Static:
                        errorCode = QuteErrorCode.InvalidMethodStatic;
                        break;
                    case FromObject:
                        errorCode = QuteErrorCode.InvalidMethodFromObject;
                        break;
                    default:
                }
            }
        }
        Range range = QutePositionUtility.createRange(methodPart);
        Diagnostic diagnostic = createDiagnostic(range, DiagnosticSeverity.Error, errorCode, methodName, arg);
        diagnostics.add(diagnostic);
        return null;
    }
    boolean matchVirtualMethod = result.isMatchVirtualMethod();
    if (!matchVirtualMethod) {
        Range range = QutePositionUtility.createRange(methodPart);
        Diagnostic diagnostic = createDiagnostic(range, DiagnosticSeverity.Error, // 
        QuteErrorCode.InvalidVirtualMethod, // 
        method.getName(), // 
        method.getSimpleSourceType(), resolvedJavaType.getJavaElementSimpleType());
        diagnostics.add(diagnostic);
        return null;
    }
    boolean matchParameters = result.isMatchParameters();
    if (!matchParameters) {
        // The method codePointAt(int) in the type String is not applicable for the
        // arguments ()
        StringBuilder expectedSignature = new StringBuilder("(");
        boolean ignoreParameter = method.isVirtual();
        for (JavaParameterInfo parameter : method.getParameters()) {
            if (!ignoreParameter) {
                if (expectedSignature.length() > 1) {
                    expectedSignature.append(", ");
                }
                expectedSignature.append(parameter.getJavaElementSimpleType());
            }
            ignoreParameter = false;
        }
        expectedSignature.append(")");
        expectedSignature.insert(0, method.getName());
        StringBuilder actualSignature = new StringBuilder("(");
        for (ResolvedJavaTypeInfo parameterType : parameterTypes) {
            if (actualSignature.length() > 1) {
                actualSignature.append(", ");
            }
            actualSignature.append(parameterType != null ? parameterType.getJavaElementSimpleType() : parameterType);
        }
        actualSignature.append(")");
        Range range = QutePositionUtility.createRange(methodPart);
        Diagnostic diagnostic = createDiagnostic(range, DiagnosticSeverity.Error, // 
        QuteErrorCode.InvalidMethodParameter, // 
        expectedSignature.toString(), // 
        method.getSimpleSourceType(), /* String */
        actualSignature.toString());
        diagnostics.add(diagnostic);
        return null;
    }
    String memberType = method.resolveJavaElementType(iter);
    return validateJavaTypePart(methodPart, ownerSection, projectUri, diagnostics, resolvingJavaTypeContext, memberType);
}
Also used : JavaMemberResult(com.redhat.qute.project.JavaMemberResult) ResolvedJavaTypeInfo(com.redhat.qute.commons.ResolvedJavaTypeInfo) ArrayList(java.util.ArrayList) DiagnosticDataFactory.createDiagnostic(com.redhat.qute.services.diagnostics.DiagnosticDataFactory.createDiagnostic) Diagnostic(org.eclipse.lsp4j.Diagnostic) Range(org.eclipse.lsp4j.Range) QuteErrorCode(com.redhat.qute.services.diagnostics.QuteErrorCode) JavaMethodInfo(com.redhat.qute.commons.JavaMethodInfo) Expression(com.redhat.qute.parser.template.Expression) Parameter(com.redhat.qute.parser.template.Parameter) InvalidMethodReason(com.redhat.qute.commons.InvalidMethodReason) JavaParameterInfo(com.redhat.qute.commons.JavaParameterInfo)

Example 2 with JavaMethodInfo

use of com.redhat.qute.commons.JavaMethodInfo in project quarkus-ls by redhat-developer.

the class QuteProjectRegistry method findMethod.

/**
 * Returns the member method retrieved by the given property or method name and
 * null otherwise.
 *
 * @param baseType             the Java base type.
 * @param propertyOrMethodName property or method name
 *
 * @return the member field retrieved by the given property or method name and
 *         null otherwise.
 */
protected static JavaMethodInfo findMethod(ResolvedJavaTypeInfo baseType, String propertyOrMethodName) {
    List<JavaMethodInfo> methods = baseType.getMethods();
    if (methods == null || methods.isEmpty() || isEmpty(propertyOrMethodName)) {
        return null;
    }
    String getterMethodName = computeGetterName(propertyOrMethodName);
    String booleanGetterName = computeBooleanGetterName(propertyOrMethodName);
    for (JavaMethodInfo method : methods) {
        if (isMatchMethod(method, propertyOrMethodName, getterMethodName, booleanGetterName)) {
            return method;
        }
    }
    return null;
}
Also used : JavaMethodInfo(com.redhat.qute.commons.JavaMethodInfo)

Example 3 with JavaMethodInfo

use of com.redhat.qute.commons.JavaMethodInfo in project quarkus-ls by redhat-developer.

the class MockQuteProject method registerMethod.

protected static JavaMemberInfo registerMethod(String methodSignature, ResolvedJavaTypeInfo resolvedType) {
    JavaMethodInfo member = new JavaMethodInfo();
    member.setSignature(methodSignature);
    resolvedType.getMethods().add(member);
    return member;
}
Also used : JavaMethodInfo(com.redhat.qute.commons.JavaMethodInfo)

Example 4 with JavaMethodInfo

use of com.redhat.qute.commons.JavaMethodInfo in project quarkus-ls by redhat-developer.

the class DocumentationUtils method createDocumentation.

private static StringBuilder createDocumentation(JavaMemberInfo member, ResolvedJavaTypeInfo iterableOfResolvedType, boolean markdown) {
    StringBuilder documentation = new StringBuilder();
    // Title
    if (markdown) {
        documentation.append("```java");
        documentation.append(System.lineSeparator());
    }
    documentation.append(getSimpleType(member.resolveJavaElementType(iterableOfResolvedType)));
    documentation.append(" ");
    String sourceType = member.getSourceType();
    if (sourceType != null) {
        documentation.append(sourceType);
        documentation.append(".");
    }
    documentation.append(member.getName());
    if (member.getJavaElementKind() == JavaElementKind.METHOD) {
        documentation.append('(');
        JavaMethodInfo methodInfo = (JavaMethodInfo) member;
        boolean virtualMethod = methodInfo.isVirtual();
        List<JavaParameterInfo> parameters = methodInfo.getParameters();
        int start = virtualMethod ? 1 : 0;
        for (int i = start; i < parameters.size(); i++) {
            JavaParameterInfo parameter = parameters.get(i);
            String type = parameter.getJavaElementSimpleType();
            String name = parameter.getName();
            if (i > start) {
                documentation.append(", ");
            }
            documentation.append(type);
            documentation.append(' ');
            documentation.append(name);
        }
        documentation.append(')');
    }
    if (markdown) {
        documentation.append(System.lineSeparator());
        documentation.append("```");
    }
    if (member.getDocumentation() != null) {
        documentation.append(System.lineSeparator());
        documentation.append(member.getDocumentation());
    }
    return documentation;
}
Also used : JavaMethodInfo(com.redhat.qute.commons.JavaMethodInfo) JavaParameterInfo(com.redhat.qute.commons.JavaParameterInfo)

Example 5 with JavaMethodInfo

use of com.redhat.qute.commons.JavaMethodInfo in project quarkus-ls by redhat-developer.

the class QuteSupportForTemplate method getResolvedJavaType.

/**
 * Returns the resolved type (fields and methods) for the given Java type.
 *
 * @param params  the Java type to resolve.
 * @param utils   the JDT LS utility.
 * @param monitor the progress monitor.
 *
 * @return the resolved type (fields and methods) for the given Java type.
 *
 * @throws CoreException
 */
public ResolvedJavaTypeInfo getResolvedJavaType(QuteResolvedJavaTypeParams params, IJDTUtils utils, IProgressMonitor monitor) throws CoreException {
    if (monitor.isCanceled()) {
        throw new OperationCanceledException();
    }
    String projectUri = params.getProjectUri();
    IJavaProject javaProject = getJavaProjectFromProjectUri(projectUri);
    if (javaProject == null) {
        return null;
    }
    String typeName = params.getClassName();
    int index = typeName.indexOf('<');
    if (index != -1) {
        // ex : java.util.List<org.acme.Item>
        String iterableClassName = typeName.substring(0, index);
        IType iterableType = findType(iterableClassName, javaProject, monitor);
        if (iterableType == null) {
            return null;
        }
        boolean iterable = isIterable(iterableType, monitor);
        if (!iterable) {
            return null;
        }
        String iterableOf = typeName.substring(index + 1, typeName.length() - 1);
        iterableOf = getFullQualifiedName(monitor, javaProject, iterableOf);
        iterableClassName = iterableType.getFullyQualifiedName('.');
        typeName = iterableClassName + "<" + iterableOf + ">";
        return createIterableType(typeName, iterableClassName, iterableOf);
    } else if (typeName.endsWith("[]")) {
        // ex : org.acme.Item[]
        String iterableOf = typeName.substring(0, typeName.length() - 2);
        IType iterableOfType = findType(iterableOf, javaProject, monitor);
        if (iterableOfType == null) {
            return null;
        }
        iterableOf = getFullQualifiedName(monitor, javaProject, iterableOf);
        typeName = iterableOf + "[]";
        return createIterableType(typeName, null, iterableOf);
    }
    // ex : org.acme.Item, java.util.List, ...
    IType type = findType(typeName, javaProject, monitor);
    if (type == null) {
        return null;
    }
    ITypeResolver typeResolver = createTypeResolver(type);
    // 1) Collect fields
    List<JavaFieldInfo> fieldsInfo = new ArrayList<>();
    // Standard fields
    IField[] fields = type.getFields();
    for (IField field : fields) {
        if (isValidField(field)) {
            // Only public fields are available
            JavaFieldInfo info = new JavaFieldInfo();
            info.setSignature(typeResolver.resolveFieldSignature(field));
            fieldsInfo.add(info);
        }
    }
    // Record fields
    if (type.isRecord()) {
        for (IField field : type.getRecordComponents()) {
            // All record components are valid
            JavaFieldInfo info = new JavaFieldInfo();
            info.setSignature(typeResolver.resolveFieldSignature(field));
            fieldsInfo.add(info);
        }
    }
    // 2) Collect methods
    List<JavaMethodInfo> methodsInfo = new ArrayList<>();
    Map<String, InvalidMethodReason> invalidMethods = new HashMap<>();
    IMethod[] methods = type.getMethods();
    for (IMethod method : methods) {
        if (isValidMethod(method, type.isInterface())) {
            try {
                InvalidMethodReason invalid = getValidMethodForQute(method, typeName);
                if (invalid != null) {
                    invalidMethods.put(method.getElementName(), invalid);
                } else {
                    JavaMethodInfo info = new JavaMethodInfo();
                    info.setSignature(typeResolver.resolveMethodSignature(method));
                    methodsInfo.add(info);
                }
            } catch (Exception e) {
                LOGGER.log(Level.SEVERE, "Error while getting method signature of '" + method.getElementName() + "'.", e);
            }
        }
    }
    // Collect type extensions
    List<String> extendedTypes = null;
    if (type.isInterface()) {
        IType[] interfaces = findImplementedInterfaces(type, monitor);
        if (interfaces != null && interfaces.length > 0) {
            extendedTypes = // 
            Stream.of(interfaces).map(// 
            interfaceType -> interfaceType.getFullyQualifiedName()).collect(Collectors.toList());
        }
    } else {
        // ex : String implements CharSequence, ....
        ITypeHierarchy typeHierarchy = type.newSupertypeHierarchy(monitor);
        IType[] allSuperTypes = typeHierarchy.getSupertypes(type);
        extendedTypes = // 
        Stream.of(allSuperTypes).map(// 
        superType -> superType.getFullyQualifiedName()).collect(Collectors.toList());
    }
    if (extendedTypes != null) {
        extendedTypes.remove(typeName);
    }
    ResolvedJavaTypeInfo resolvedType = new ResolvedJavaTypeInfo();
    String typeSignature = AbstractTypeResolver.resolveJavaTypeSignature(type);
    resolvedType.setSignature(typeSignature);
    resolvedType.setFields(fieldsInfo);
    resolvedType.setMethods(methodsInfo);
    resolvedType.setInvalidMethods(invalidMethods);
    resolvedType.setExtendedTypes(extendedTypes);
    return resolvedType;
}
Also used : JavaFieldInfo(com.redhat.qute.commons.JavaFieldInfo) HashMap(java.util.HashMap) OperationCanceledException(org.eclipse.core.runtime.OperationCanceledException) ArrayList(java.util.ArrayList) ResolvedJavaTypeInfo(com.redhat.qute.commons.ResolvedJavaTypeInfo) ITypeResolver(com.redhat.qute.jdt.internal.resolver.ITypeResolver) IField(org.eclipse.jdt.core.IField) CoreException(org.eclipse.core.runtime.CoreException) OperationCanceledException(org.eclipse.core.runtime.OperationCanceledException) JavaModelException(org.eclipse.jdt.core.JavaModelException) IType(org.eclipse.jdt.core.IType) JavaMethodInfo(com.redhat.qute.commons.JavaMethodInfo) ITypeHierarchy(org.eclipse.jdt.core.ITypeHierarchy) IJavaProject(org.eclipse.jdt.core.IJavaProject) InvalidMethodReason(com.redhat.qute.commons.InvalidMethodReason) IMethod(org.eclipse.jdt.core.IMethod)

Aggregations

JavaMethodInfo (com.redhat.qute.commons.JavaMethodInfo)12 ResolvedJavaTypeInfo (com.redhat.qute.commons.ResolvedJavaTypeInfo)9 InvalidMethodReason (com.redhat.qute.commons.InvalidMethodReason)6 QuteResolvedJavaTypeParams (com.redhat.qute.commons.QuteResolvedJavaTypeParams)4 NullProgressMonitor (org.eclipse.core.runtime.NullProgressMonitor)4 Test (org.junit.Test)4 JavaFieldInfo (com.redhat.qute.commons.JavaFieldInfo)2 JavaParameterInfo (com.redhat.qute.commons.JavaParameterInfo)2 ArrayList (java.util.ArrayList)2 Range (org.eclipse.lsp4j.Range)2 ITypeResolver (com.redhat.qute.jdt.internal.resolver.ITypeResolver)1 Expression (com.redhat.qute.parser.template.Expression)1 Parameter (com.redhat.qute.parser.template.Parameter)1 JavaMemberResult (com.redhat.qute.project.JavaMemberResult)1 DiagnosticDataFactory.createDiagnostic (com.redhat.qute.services.diagnostics.DiagnosticDataFactory.createDiagnostic)1 QuteErrorCode (com.redhat.qute.services.diagnostics.QuteErrorCode)1 HashMap (java.util.HashMap)1 CoreException (org.eclipse.core.runtime.CoreException)1 OperationCanceledException (org.eclipse.core.runtime.OperationCanceledException)1 IField (org.eclipse.jdt.core.IField)1