teo-parser 0.3.0

Parser for Teo schema language
Documentation
use maplit::btreemap;
use crate::ast::arith_expr::ArithExpr;
use crate::ast::expression::ExpressionKind;
use crate::ast::literals::ArrayLiteral;
use crate::ast::unit::Unit;
use crate::ast::use_middlewares::UseMiddlewaresBlock;
use crate::expr::{ExprInfo, ReferenceInfo, ReferenceType};
use crate::r#type::reference::Reference;
use crate::r#type::Type;
use crate::resolver::resolve_argument_list::resolve_argument_list;
use crate::resolver::resolve_identifier::{resolve_identifier_path_names_with_filter_to_top, resolve_identifier_with_diagnostic_message};
use crate::resolver::resolve_unit::resolve_unit;
use crate::resolver::resolver_context::ResolverContext;
use crate::traits::node_trait::NodeTrait;
use crate::traits::resolved::Resolve;
use crate::utils::top_filter::top_filter_for_middleware;

pub(super) fn resolve_use_middlewares_block<'a>(block: &'a UseMiddlewaresBlock, context: &'a ResolverContext<'a>) {
    let actual_availability = context.current_availability();
    *block.actual_availability.borrow_mut() = actual_availability;
    resolve_use_middlewares_array_literal(block.array_literal(), context)
}

fn resolve_use_middlewares_array_literal<'a>(array_literal: &'a ArrayLiteral, context: &'a ResolverContext<'a>) {
    for expression in array_literal.expressions() {
        match &expression.kind {
            ExpressionKind::Identifier(i) => { expression.resolve(resolve_identifier_with_diagnostic_message(i, context)); },
            ExpressionKind::Unit(u) => { expression.resolve(resolve_unit(u, context, &Type::Middleware, &btreemap! {})); },
            ExpressionKind::ArithExpr(a) => match a {
                ArithExpr::Expression(e) => match &e.as_ref().kind {
                    ExpressionKind::Unit(u) => { expression.resolve(resolve_middleware_unit(u, context)); },
                    _ => context.insert_diagnostics_error(expression.span(), "unexpected middleware expression"),
                },
                _ => context.insert_diagnostics_error(expression.span(), "unexpected middleware expression"),
            }
            _ => context.insert_diagnostics_error(expression.span(), "unexpected middleware expression"),
        }
    }
}

fn resolve_middleware_unit<'a>(unit: &'a Unit, context: &'a ResolverContext<'a>) -> ExprInfo {
    let mut path = vec![];
    let mut arg_list = None;
    for expression in unit.expressions() {
        match &expression.kind {
            ExpressionKind::Identifier(identifier) => path.push(identifier.name()),
            ExpressionKind::ArgumentList(argument_list) => arg_list = Some(argument_list),
            _ => (),
        }
    }
    if let Some(middleware_declaration) = resolve_identifier_path_names_with_filter_to_top(
        &path,
        context.schema,
        context.source(),
        &context.current_namespace_path(),
        &top_filter_for_middleware(),
        context.current_availability(),
    ).map(|t| t.as_middleware_declaration()).flatten() {
        if middleware_declaration.argument_list_declaration().is_none() {
            if !arg_list.is_none() {
                context.insert_diagnostics_error(arg_list.unwrap().span, "middleware requires no arguments")
            }
        } else if let Some(argument_list) = middleware_declaration.argument_list_declaration() {
            if !argument_list.every_argument_is_optional() && arg_list.is_none() {
                context.insert_diagnostics_error(unit.span, "middleware requires argument list");
            }
            if let Some(arg_list) = arg_list {
                resolve_argument_list(unit.span, Some(arg_list), middleware_declaration.callable_variants(), &btreemap! {}, context, None);
            }
        }
        ExprInfo {
            r#type: Type::Middleware,
            value: None,
            reference_info: Some(ReferenceInfo::new(ReferenceType::Middleware, Reference::new(middleware_declaration.path.clone(), middleware_declaration.string_path.clone()), None)),
        }
    } else {
        ExprInfo::undetermined()
    }
}