wat_service 0.10.2

WebAssembly Text Format language service.
Documentation
use super::Diagnostic;
use crate::data_set::CONST_INSTRS;
use wat_syntax::{
    AmberNode, SyntaxKind, TextRange,
    ast::{AstNode, Instr},
};

const DIAGNOSTIC_CODE: &str = "const-expr";

pub fn check(node: AmberNode) -> Option<Diagnostic> {
    let mut first = None;
    let mut last = None;
    let mut is_const = true;
    node.children_by_kind(Instr::can_cast).for_each(|instr| {
        if first.is_none() {
            first = Some(instr);
        }
        last = Some(instr);
        is_const &= check_instr(instr);
    });
    if !is_const
        && let Some(first) = first
        && let Some(last) = last
    {
        Some(Diagnostic {
            range: TextRange::cover(first.text_range(), last.text_range()),
            code: DIAGNOSTIC_CODE.into(),
            message: "expression must be constant".into(),
            ..Default::default()
        })
    } else {
        None
    }
}

fn check_instr(instr: AmberNode) -> bool {
    instr
        .tokens_by_kind(SyntaxKind::INSTR_NAME)
        .next()
        .is_some_and(|instr_name| CONST_INSTRS.contains(&instr_name.text()))
        && instr.children_by_kind(Instr::can_cast).all(check_instr)
}