Search in sources :

Example 1 with InvalidMethodReason

use of com.redhat.qute.commons.InvalidMethodReason 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 InvalidMethodReason

use of com.redhat.qute.commons.InvalidMethodReason 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)

Example 3 with InvalidMethodReason

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

the class TemplateGetResolvedJavaTypeTest method list.

@Test
public void list() throws Exception {
    loadMavenProject(QuteMavenProjectName.qute_quickstart);
    QuteResolvedJavaTypeParams params = new QuteResolvedJavaTypeParams("java.util.List", QuteMavenProjectName.qute_quickstart);
    ResolvedJavaTypeInfo result = QuteSupportForTemplate.getInstance().getResolvedJavaType(params, getJDTUtils(), new NullProgressMonitor());
    Assert.assertEquals("java.util.List<E>", result.getSignature());
    Assert.assertTrue(result.isIterable());
    Assert.assertEquals("java.util.List", result.getIterableType());
    Assert.assertEquals("java.lang.Object", result.getIterableOf());
    // Invalid method void clear();
    JavaMethodInfo clearMethod = findMethod(result, "clear");
    Assert.assertNull(clearMethod);
    InvalidMethodReason reason = result.getInvalidMethodReason("clear");
    Assert.assertEquals(InvalidMethodReason.VoidReturn, reason);
    params = new QuteResolvedJavaTypeParams("List", QuteMavenProjectName.qute_quickstart);
    result = QuteSupportForTemplate.getInstance().getResolvedJavaType(params, getJDTUtils(), new NullProgressMonitor());
    Assert.assertNull(result);
    params = new QuteResolvedJavaTypeParams("List<String>", QuteMavenProjectName.qute_quickstart);
    Assert.assertNull(result);
    params = new QuteResolvedJavaTypeParams("List<java.lang.String>", QuteMavenProjectName.qute_quickstart);
    result = QuteSupportForTemplate.getInstance().getResolvedJavaType(params, getJDTUtils(), new NullProgressMonitor());
    Assert.assertNull(result);
    params = new QuteResolvedJavaTypeParams("java.util.List<java.lang.String>", QuteMavenProjectName.qute_quickstart);
    result = QuteSupportForTemplate.getInstance().getResolvedJavaType(params, getJDTUtils(), new NullProgressMonitor());
    Assert.assertEquals("java.util.List<java.lang.String>", result.getSignature());
    Assert.assertTrue(result.isIterable());
    Assert.assertEquals("java.util.List", result.getIterableType());
    Assert.assertEquals("java.lang.String", result.getIterableOf());
}
Also used : QuteResolvedJavaTypeParams(com.redhat.qute.commons.QuteResolvedJavaTypeParams) NullProgressMonitor(org.eclipse.core.runtime.NullProgressMonitor) JavaMethodInfo(com.redhat.qute.commons.JavaMethodInfo) ResolvedJavaTypeInfo(com.redhat.qute.commons.ResolvedJavaTypeInfo) InvalidMethodReason(com.redhat.qute.commons.InvalidMethodReason) Test(org.junit.Test)

Example 4 with InvalidMethodReason

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

the class TemplateGetResolvedJavaTypeTest method item.

@Test
public void item() throws Exception {
    loadMavenProject(QuteMavenProjectName.qute_quickstart);
    QuteResolvedJavaTypeParams params = new QuteResolvedJavaTypeParams("org.acme.qute.Item", QuteMavenProjectName.qute_quickstart);
    ResolvedJavaTypeInfo result = QuteSupportForTemplate.getInstance().getResolvedJavaType(params, getJDTUtils(), new NullProgressMonitor());
    Assert.assertNotNull(result);
    Assert.assertEquals("org.acme.qute.Item", result.getSignature());
    Assert.assertFalse(result.isIterable());
    // Fields
    Assert.assertNotNull(result.getFields());
    Assert.assertEquals(2, result.getFields().size());
    Assert.assertEquals("name", result.getFields().get(0).getName());
    Assert.assertEquals("java.lang.String", result.getFields().get(0).getType());
    Assert.assertEquals("price", result.getFields().get(1).getName());
    Assert.assertEquals("java.math.BigDecimal", result.getFields().get(1).getType());
    // Methods
    Assert.assertNotNull(result.getMethods());
    Assert.assertEquals(1, result.getMethods().size());
    Assert.assertEquals("getDerivedItems() : org.acme.qute.Item[]", result.getMethods().get(0).getSignature());
    // Invalid methods(static method)
    JavaMethodInfo discountedPriceMethod = findMethod(result, "staticMethod");
    Assert.assertNull(discountedPriceMethod);
    InvalidMethodReason reason = result.getInvalidMethodReason("staticMethod");
    Assert.assertEquals(InvalidMethodReason.Static, reason);
}
Also used : QuteResolvedJavaTypeParams(com.redhat.qute.commons.QuteResolvedJavaTypeParams) NullProgressMonitor(org.eclipse.core.runtime.NullProgressMonitor) JavaMethodInfo(com.redhat.qute.commons.JavaMethodInfo) ResolvedJavaTypeInfo(com.redhat.qute.commons.ResolvedJavaTypeInfo) InvalidMethodReason(com.redhat.qute.commons.InvalidMethodReason) Test(org.junit.Test)

Example 5 with InvalidMethodReason

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

the class TemplateGetResolvedJavaTypeTest method object.

@Test
public void object() throws Exception {
    loadMavenProject(QuteMavenProjectName.qute_quickstart);
    QuteResolvedJavaTypeParams params = new QuteResolvedJavaTypeParams("java.lang.Object", QuteMavenProjectName.qute_quickstart);
    ResolvedJavaTypeInfo result = QuteSupportForTemplate.getInstance().getResolvedJavaType(params, getJDTUtils(), new NullProgressMonitor());
    Assert.assertNotNull(result);
    Assert.assertEquals("java.lang.Object", result.getSignature());
    Assert.assertFalse(result.isIterable());
    // None valid methods
    Assert.assertNotNull(result.getMethods());
    Assert.assertTrue(result.getMethods().isEmpty());
    // Invalid method codePointAt(int index)
    JavaMethodInfo waitMethod = findMethod(result, "wait");
    Assert.assertNull(waitMethod);
    InvalidMethodReason reason = result.getInvalidMethodReason("wait");
    Assert.assertEquals(InvalidMethodReason.FromObject, reason);
}
Also used : QuteResolvedJavaTypeParams(com.redhat.qute.commons.QuteResolvedJavaTypeParams) NullProgressMonitor(org.eclipse.core.runtime.NullProgressMonitor) JavaMethodInfo(com.redhat.qute.commons.JavaMethodInfo) ResolvedJavaTypeInfo(com.redhat.qute.commons.ResolvedJavaTypeInfo) InvalidMethodReason(com.redhat.qute.commons.InvalidMethodReason) Test(org.junit.Test)

Aggregations

InvalidMethodReason (com.redhat.qute.commons.InvalidMethodReason)6 JavaMethodInfo (com.redhat.qute.commons.JavaMethodInfo)6 ResolvedJavaTypeInfo (com.redhat.qute.commons.ResolvedJavaTypeInfo)6 QuteResolvedJavaTypeParams (com.redhat.qute.commons.QuteResolvedJavaTypeParams)4 NullProgressMonitor (org.eclipse.core.runtime.NullProgressMonitor)4 Test (org.junit.Test)4 ArrayList (java.util.ArrayList)2 JavaFieldInfo (com.redhat.qute.commons.JavaFieldInfo)1 JavaParameterInfo (com.redhat.qute.commons.JavaParameterInfo)1 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 IJavaProject (org.eclipse.jdt.core.IJavaProject)1