ltk_ritobin 0.8.2

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

impl<'a> Builder<'a> {
    pub(crate) fn resolve_literal(
        &mut self,
        text: &str,
        token: &Token,
        kind_hint: Option<RitoType>,
        kind_hint_span: Option<Span>,
    ) -> Value {
        match Value::eval(text, token, kind_hint, kind_hint_span) {
            Ok(value) => value,
            Err(e) => {
                self.push(e.default_span(token.span));
                kind_hint
                    .map(|k| Value::Unresolved {
                        span: token.span,
                        kind: k.base,
                    })
                    .unwrap_or(Value::Unknown(token.span))
            }
        }
    }
    pub(crate) fn resolve_value(
        &mut self,
        wrapper: &Node,
        hint: Option<RitoType>,
        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(hint) = hint else {
                    return Err(Diagnostic::CustomSpan(
                        "Cannot resolve class block with no type hint",
                        node.span,
                    ));
                };
                self.resolve_class(node, hint)
            }
            Kind::Block => {
                let Some(hint) = hint else {
                    return Err(Diagnostic::CustomSpan(
                        "Cannot resolve block with no type hint",
                        node.span,
                    ));
                };
                self.resolve_block_value(node, hint, 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, hint, hint_span))
            }
            Kind::ErrorTree => Ok(Value::Unknown(node.span)),
            kind => {
                eprintln!("cannot resolve {kind:?}");
                Err(Diagnostic::CustomSpan(
                    "[resolve_value] cannot resolve this node kind",
                    node.span,
                ))
            }
        }
    }

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