Search in sources :

Example 1 with ResolvedJavaTypeInfo

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

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

the class QuteDiagnostics method validateDataModel.

private void validateDataModel(Node parent, Template template, QuteValidationSettings validationSettings, ResolvingJavaTypeContext resolvingJavaTypeContext, ResolutionContext currentContext, List<Diagnostic> diagnostics) {
    ResolutionContext previousContext = currentContext;
    List<Node> children = parent.getChildren();
    for (Node node : children) {
        switch(node.getKind()) {
            case ParameterDeclaration:
                {
                    ParameterDeclaration parameter = (ParameterDeclaration) node;
                    String javaTypeToResolve = parameter.getJavaType();
                    if (!StringUtils.isEmpty(javaTypeToResolve)) {
                        String projectUri = template.getProjectUri();
                        if (projectUri != null) {
                            List<JavaTypeRangeOffset> classNameRanges = parameter.getJavaTypeNameRanges();
                            for (RangeOffset classNameRange : classNameRanges) {
                                String className = template.getText(classNameRange);
                                ResolvedJavaTypeInfo resolvedJavaType = resolveJavaType(className, projectUri, resolvingJavaTypeContext);
                                if (resolvedJavaType == null) {
                                    // Java type doesn't exist
                                    Range range = QutePositionUtility.createRange(classNameRange, template);
                                    Diagnostic diagnostic = createDiagnostic(range, DiagnosticSeverity.Error, QuteErrorCode.UnknownType, className);
                                    diagnostics.add(diagnostic);
                                } else if (!isResolvingJavaType(resolvedJavaType)) {
                                    currentContext.put(javaTypeToResolve, resolvedJavaType);
                                }
                            }
                        }
                    }
                    break;
                }
            case Section:
                {
                    Section section = (Section) node;
                    if (canChangeContext(section)) {
                        currentContext = new ResolutionContext(currentContext);
                    }
                    List<Parameter> parameters = section.getParameters();
                    // validate expression parameters
                    for (Parameter parameter : parameters) {
                        Expression expression = parameter.getJavaTypeExpression();
                        if (expression != null) {
                            ResolvedJavaTypeInfo result = validateExpression(expression, section, template, validationSettings, previousContext, resolvingJavaTypeContext, diagnostics);
                            switch(section.getSectionKind()) {
                                case FOR:
                                case EACH:
                                    String alias = ((LoopSection) section).getAlias();
                                    currentContext.put(alias, result);
                                    break;
                                case WITH:
                                    currentContext.setWithObject(result);
                                    break;
                                case LET:
                                case SET:
                                    currentContext.put(parameter.getName(), result);
                                    break;
                                default:
                            }
                        }
                    }
                    switch(section.getSectionKind()) {
                        case INCLUDE:
                            validateIncludeSection((IncludeSection) section, diagnostics);
                            break;
                        default:
                            validateSectionTag(section, template, resolvingJavaTypeContext, diagnostics);
                    }
                    break;
                }
            case Expression:
                {
                    validateExpression((Expression) node, null, template, validationSettings, previousContext, resolvingJavaTypeContext, diagnostics);
                    break;
                }
            default:
        }
        validateDataModel(node, template, validationSettings, resolvingJavaTypeContext, currentContext, diagnostics);
    }
}
Also used : Node(com.redhat.qute.parser.template.Node) ResolvedJavaTypeInfo(com.redhat.qute.commons.ResolvedJavaTypeInfo) DiagnosticDataFactory.createDiagnostic(com.redhat.qute.services.diagnostics.DiagnosticDataFactory.createDiagnostic) Diagnostic(org.eclipse.lsp4j.Diagnostic) Range(org.eclipse.lsp4j.Range) IncludeSection(com.redhat.qute.parser.template.sections.IncludeSection) LoopSection(com.redhat.qute.parser.template.sections.LoopSection) Section(com.redhat.qute.parser.template.Section) Expression(com.redhat.qute.parser.template.Expression) JavaTypeRangeOffset(com.redhat.qute.parser.template.ParameterDeclaration.JavaTypeRangeOffset) RangeOffset(com.redhat.qute.parser.template.RangeOffset) Parameter(com.redhat.qute.parser.template.Parameter) IncludeSection(com.redhat.qute.parser.template.sections.IncludeSection) List(java.util.List) ArrayList(java.util.ArrayList) ParameterDeclaration(com.redhat.qute.parser.template.ParameterDeclaration)

Example 3 with ResolvedJavaTypeInfo

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

the class QuteDiagnostics method validateExpression.

private ResolvedJavaTypeInfo validateExpression(Expression expression, Section ownerSection, Template template, QuteValidationSettings validationSettings, ResolutionContext resolutionContext, ResolvingJavaTypeContext resolvingJavaTypeContext, List<Diagnostic> diagnostics) {
    try {
        String projectUri = template.getProjectUri();
        String literalJavaType = expression.getLiteralJavaType();
        if (literalJavaType != null) {
            // The expression is a literal:
            // - {'abcd'} : string literal
            // - {true} : boolean literal
            // - {null} : null literal
            // - {123} : integer literal
            ResolvedJavaTypeInfo resolvedLiteralType = javaCache.resolveJavaType(literalJavaType, projectUri).getNow(null);
            if (resolvedLiteralType == null) {
                return null;
            }
            return validateIterable(expression.getLastPart(), ownerSection, resolvedLiteralType, resolvedLiteralType.getName(), diagnostics);
        }
        // The expression reference Java data model (ex : {item})
        ResolvedJavaTypeInfo resolvedJavaType = null;
        List<Node> expressionChildren = expression.getExpressionContent();
        for (Node expressionChild : expressionChildren) {
            if (expressionChild.getKind() == NodeKind.ExpressionParts) {
                Parts parts = (Parts) expressionChild;
                resolvedJavaType = validateExpressionParts(parts, ownerSection, template, projectUri, validationSettings, resolutionContext, resolvingJavaTypeContext, diagnostics);
            }
        }
        return resolvedJavaType;
    } catch (CancellationException e) {
        throw e;
    } catch (Exception e) {
        LOGGER.log(Level.SEVERE, "Error while validating expression '" + expression.getContent() + "' in '" + template.getUri() + "'.", e);
        return null;
    }
}
Also used : Parts(com.redhat.qute.parser.expression.Parts) CancellationException(java.util.concurrent.CancellationException) Node(com.redhat.qute.parser.template.Node) ResolvedJavaTypeInfo(com.redhat.qute.commons.ResolvedJavaTypeInfo) CancellationException(java.util.concurrent.CancellationException)

Example 4 with ResolvedJavaTypeInfo

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

the class QuteProjectRegistry method resolveJavaType.

public CompletableFuture<ResolvedJavaTypeInfo> resolveJavaType(String javaTypeName, String projectUri) {
    CompletableFuture<ResolvedJavaTypeInfo> primitiveType = javaPrimitiveTypes.get(javaTypeName);
    if (primitiveType != null) {
        // It's a primitive type like boolean, double, float, etc
        return primitiveType;
    }
    if (StringUtils.isEmpty(javaTypeName) || StringUtils.isEmpty(projectUri)) {
        return RESOLVED_JAVA_CLASSINFO_NULL_FUTURE;
    }
    QuteProject project = getProject(projectUri);
    if (project == null) {
        return RESOLVED_JAVA_CLASSINFO_NULL_FUTURE;
    }
    CompletableFuture<ResolvedJavaTypeInfo> future = project.getResolvedJavaType(javaTypeName);
    if (future == null || future.isCancelled() || future.isCompletedExceptionally()) {
        QuteResolvedJavaTypeParams params = new QuteResolvedJavaTypeParams(javaTypeName, projectUri);
        future = // 
        getResolvedJavaType(params).thenCompose(c -> {
            if (c != null) {
                // Update members with the resolved class
                c.getFields().forEach(f -> {
                    f.setJavaType(c);
                });
                c.getMethods().forEach(m -> {
                    m.setJavaType(c);
                });
                // Load extended Java types
                if (c.getExtendedTypes() != null) {
                    List<CompletableFuture<ResolvedJavaTypeInfo>> resolvingExtendedFutures = new ArrayList<>();
                    for (String extendedType : c.getExtendedTypes()) {
                        CompletableFuture<ResolvedJavaTypeInfo> extendedFuture = resolveJavaType(extendedType, projectUri);
                        if (!extendedFuture.isDone()) {
                            resolvingExtendedFutures.add(extendedFuture);
                        }
                    }
                    if (!resolvingExtendedFutures.isEmpty()) {
                        CompletableFuture<Void> allFutures = CompletableFuture.allOf(resolvingExtendedFutures.toArray(new CompletableFuture[resolvingExtendedFutures.size()]));
                        return // 
                        allFutures.thenApply(a -> c);
                    }
                }
            }
            return CompletableFuture.completedFuture(c);
        });
        project.registerResolvedJavaType(javaTypeName, future);
    }
    return future;
}
Also used : Template(com.redhat.qute.parser.template.Template) QuteJavaTypesProvider(com.redhat.qute.ls.api.QuteJavaTypesProvider) RESOLVED_JAVA_CLASSINFO_NULL_FUTURE(com.redhat.qute.services.QuteCompletableFutures.RESOLVED_JAVA_CLASSINFO_NULL_FUTURE) MethodValueResolver(com.redhat.qute.project.datamodel.resolvers.MethodValueResolver) JavaFieldInfo(com.redhat.qute.commons.JavaFieldInfo) DataModelProject(com.redhat.qute.commons.datamodel.DataModelProject) StringUtils(com.redhat.qute.utils.StringUtils) ProjectInfo(com.redhat.qute.commons.ProjectInfo) QuteJavaTypesParams(com.redhat.qute.commons.QuteJavaTypesParams) QuteJavaDefinitionProvider(com.redhat.qute.ls.api.QuteJavaDefinitionProvider) ValueResolversRegistry(com.redhat.qute.project.datamodel.resolvers.ValueResolversRegistry) DataModelParameter(com.redhat.qute.commons.datamodel.DataModelParameter) LiteralSupport(com.redhat.qute.parser.template.LiteralSupport) Map(java.util.Map) Location(org.eclipse.lsp4j.Location) QuteUserTagProvider(com.redhat.qute.ls.api.QuteUserTagProvider) METHOD_VALUE_RESOLVERS_NULL_FUTURE(com.redhat.qute.services.QuteCompletableFutures.METHOD_VALUE_RESOLVERS_NULL_FUTURE) UserTagInfo(com.redhat.qute.commons.usertags.UserTagInfo) DataModelTemplate(com.redhat.qute.commons.datamodel.DataModelTemplate) LiteralSupport.getPrimitiveObjectType(com.redhat.qute.parser.template.LiteralSupport.getPrimitiveObjectType) ExtendedDataModelTemplate(com.redhat.qute.project.datamodel.ExtendedDataModelTemplate) JavaTypeInfo(com.redhat.qute.commons.JavaTypeInfo) Set(java.util.Set) QuteResolvedJavaTypeProvider(com.redhat.qute.ls.api.QuteResolvedJavaTypeProvider) List(java.util.List) NAMESPACE_RESOLVER_INFO_NULL_FUTURE(com.redhat.qute.services.QuteCompletableFutures.NAMESPACE_RESOLVER_INFO_NULL_FUTURE) JavaDataModelChangeEvent(com.redhat.qute.commons.datamodel.JavaDataModelChangeEvent) ResolvedJavaTypeInfo(com.redhat.qute.commons.ResolvedJavaTypeInfo) FieldValueResolver(com.redhat.qute.project.datamodel.resolvers.FieldValueResolver) JAVA_ELEMENT_INFO_NULL_FUTURE(com.redhat.qute.services.QuteCompletableFutures.JAVA_ELEMENT_INFO_NULL_FUTURE) JavaElementInfo(com.redhat.qute.commons.JavaElementInfo) ValueResolver(com.redhat.qute.project.datamodel.resolvers.ValueResolver) TypeValueResolver(com.redhat.qute.project.datamodel.resolvers.TypeValueResolver) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) ArrayList(java.util.ArrayList) QuteResolvedJavaTypeParams(com.redhat.qute.commons.QuteResolvedJavaTypeParams) QuteDataModelProjectParams(com.redhat.qute.commons.datamodel.QuteDataModelProjectParams) JavaMemberInfo(com.redhat.qute.commons.JavaMemberInfo) NamespaceResolverInfo(com.redhat.qute.commons.datamodel.resolvers.NamespaceResolverInfo) QuteUserTagParams(com.redhat.qute.commons.usertags.QuteUserTagParams) ExtendedDataModelProject(com.redhat.qute.project.datamodel.ExtendedDataModelProject) JavaParameterInfo(com.redhat.qute.commons.JavaParameterInfo) QuteDataModelProjectProvider(com.redhat.qute.ls.api.QuteDataModelProjectProvider) QuteProjectInfoProvider(com.redhat.qute.ls.api.QuteProjectInfoProvider) EXTENDED_TEMPLATE_DATAMODEL_NULL_FUTURE(com.redhat.qute.services.QuteCompletableFutures.EXTENDED_TEMPLATE_DATAMODEL_NULL_FUTURE) Collections(java.util.Collections) JavaMethodInfo(com.redhat.qute.commons.JavaMethodInfo) QuteJavaDefinitionParams(com.redhat.qute.commons.QuteJavaDefinitionParams) QuteResolvedJavaTypeParams(com.redhat.qute.commons.QuteResolvedJavaTypeParams) CompletableFuture(java.util.concurrent.CompletableFuture) ResolvedJavaTypeInfo(com.redhat.qute.commons.ResolvedJavaTypeInfo) List(java.util.List) ArrayList(java.util.ArrayList)

Example 5 with ResolvedJavaTypeInfo

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

the class QuteProjectRegistry method isMatchParameters.

private boolean isMatchParameters(JavaMethodInfo method, List<ResolvedJavaTypeInfo> parameterTypes, String projectUri) {
    boolean virtualMethod = method.isVirtual();
    if (parameterTypes.size() != (method.getParameters().size() - (virtualMethod ? 1 : 0))) {
        return false;
    }
    for (int i = 0; i < parameterTypes.size(); i++) {
        JavaParameterInfo parameterInfo = method.getParameters().get(i + (virtualMethod ? 1 : 0));
        ResolvedJavaTypeInfo result = parameterTypes.get(i);
        String parameterType = parameterInfo.getType();
        if (!isMatchType(result, parameterType, projectUri)) {
            return false;
        }
    }
    return true;
}
Also used : ResolvedJavaTypeInfo(com.redhat.qute.commons.ResolvedJavaTypeInfo) JavaParameterInfo(com.redhat.qute.commons.JavaParameterInfo)

Aggregations

ResolvedJavaTypeInfo (com.redhat.qute.commons.ResolvedJavaTypeInfo)36 JavaMethodInfo (com.redhat.qute.commons.JavaMethodInfo)11 QuteResolvedJavaTypeParams (com.redhat.qute.commons.QuteResolvedJavaTypeParams)10 InvalidMethodReason (com.redhat.qute.commons.InvalidMethodReason)8 NullProgressMonitor (org.eclipse.core.runtime.NullProgressMonitor)8 Test (org.junit.Test)8 ArrayList (java.util.ArrayList)7 JavaMemberInfo (com.redhat.qute.commons.JavaMemberInfo)6 Part (com.redhat.qute.parser.expression.Part)6 Range (org.eclipse.lsp4j.Range)6 JavaFieldInfo (com.redhat.qute.commons.JavaFieldInfo)5 ObjectPart (com.redhat.qute.parser.expression.ObjectPart)5 Parts (com.redhat.qute.parser.expression.Parts)5 Expression (com.redhat.qute.parser.template.Expression)5 Parameter (com.redhat.qute.parser.template.Parameter)5 MethodValueResolver (com.redhat.qute.project.datamodel.resolvers.MethodValueResolver)5 DiagnosticDataFactory.createDiagnostic (com.redhat.qute.services.diagnostics.DiagnosticDataFactory.createDiagnostic)5 List (java.util.List)5 CompletableFuture (java.util.concurrent.CompletableFuture)5 Diagnostic (org.eclipse.lsp4j.Diagnostic)5