ltk_ritobin 0.12.0

Ritobin text format parser and writer for League Toolkit
Documentation
use crate::span::Span;
use crate::{
    ast::{
        builder::Builder,
        diagnostics::{
            Diagnostic::{self},
            MaybeSpanDiag,
        },
        resolve::literals::ExpectedType,
        Value,
    },
    cst::Kind,
    parse::Token,
    Node, RitoType,
};

impl<'a> Builder<'a> {
    pub(crate) fn resolve_literal(
        &mut self,
        text: &str,
        token: &Token,
        expected_type: Option<ExpectedType>,
        expected_type_span: Option<Span>,
    ) -> Value {
        match Value::eval(text, token, expected_type, expected_type_span) {
            Ok(value) => value,
            Err(e) => {
                self.push(Diagnostic::from(e).default_span(token.span));
                match expected_type {
                    Some(ExpectedType::Exact(kind)) => Value::Unresolved {
                        span: token.span,
                        kind,
                    },
                    _ => Value::Unknown(token.span),
                }
            }
        }
    }
    pub(crate) fn resolve_value(
        &mut self,
        wrapper: &Node,
        numeric_hint: Option<impl Into<ExpectedType>>,
        numeric_hint_span: Option<Span>,
    ) -> Result<Value, Diagnostic> {
        self.resolve_value_inner(wrapper, numeric_hint.map(Into::into), numeric_hint_span)
    }

    fn resolve_value_inner(
        &mut self,
        wrapper: &Node,
        numeric_hint: Option<ExpectedType>,
        numeric_hint_span: Option<Span>,
    ) -> Result<Value, Diagnostic> {
        let Some(child) = wrapper.children.get(self.cst).first() else {
            return Err(Diagnostic::CustomSpan(
                "[resolve_value] node has no children",
                wrapper.span,
            ));
        };
        let Some(node) = child.tree(self.cst) else {
            return Err(Diagnostic::CustomSpan(
                "[resolve_value] first child is not a node",
                wrapper.span,
            ));
        };
        match node.kind {
            Kind::Class => {
                let Some(ExpectedType::Exact(kind)) = numeric_hint else {
                    return Err(Diagnostic::CustomSpan(
                        "Cannot resolve class block with no type hint",
                        node.span,
                    ));
                };
                self.resolve_class(node, kind)
            }
            Kind::Block => {
                let Some(ExpectedType::Exact(kind)) = numeric_hint else {
                    return Err(Diagnostic::CustomSpan(
                        "Cannot resolve block with no type hint",
                        node.span,
                    ));
                };
                self.resolve_block_value(node, kind, numeric_hint_span)
                    .map_err(|e| e.fallback(node.span).diagnostic)
            }
            Kind::Literal => {
                let Some(token_child) = node.children.get(self.cst).first() else {
                    return Err(Diagnostic::CustomSpan(
                        "[resolve_value] literal node has no children",
                        wrapper.span,
                    ));
                };
                let Some(token) = token_child.token(self.cst) else {
                    return Err(Diagnostic::CustomSpan(
                        "[resolve_value] literal node's first child is not a token",
                        wrapper.span,
                    ));
                };
                Ok(self.resolve_literal(self.text, token, numeric_hint, numeric_hint_span))
            }
            Kind::ErrorTree => Ok(Value::Unknown(node.span)),
            _ => Err(Diagnostic::CustomSpan(
                "[resolve_value] cannot resolve this node kind",
                node.span,
            )),
        }
    }

    pub(crate) fn resolve_list_item_block(
        &mut self,
        node: &Node,
        hint: impl Into<RitoType>,
        hint_span: Option<Span>,
    ) -> Result<Value, MaybeSpanDiag> {
        self.resolve_block_value(node, hint, hint_span)
    }
}