wat_service 0.10.0

WebAssembly Text Format language service.
Documentation
use super::{Diagnostic, RelatedInformation};
use crate::{
    binder::{SymbolKind, SymbolTable},
    document::Document,
    mutability,
};

const DIAGNOSTIC_CODE: &str = "mutated-immutable";

pub fn check(
    db: &dyn salsa::Database,
    diagnostics: &mut Vec<Diagnostic>,
    document: Document,
    symbol_table: &SymbolTable,
) {
    let mutabilities = mutability::get_mutabilities(db, document);
    let mutation_actions = mutability::get_mutation_actions(db, document);
    diagnostics.extend(
        mutation_actions
            .iter()
            .filter(|(_, action)| action.kind == mutability::MutationActionKind::Set)
            .filter_map(|(key, action)| {
                action
                    .target
                    .and_then(|target| mutabilities.get_key_value(&target))
                    .filter(|(_, mutability)| mutability.mut_keyword.is_none())
                    .zip(symbol_table.symbols.get(key))
                    .map(|((def_key, _), ref_symbol)| {
                        let kind = match ref_symbol.kind {
                            SymbolKind::GlobalRef => "global",
                            SymbolKind::TypeUse => "array",
                            SymbolKind::FieldRef => "field",
                            _ => unreachable!(),
                        };
                        Diagnostic {
                            range: key.text_range(),
                            code: DIAGNOSTIC_CODE.into(),
                            message: format!(
                                "mutating the immutable {kind} `{}` is not allowed",
                                ref_symbol.idx.render(db)
                            ),
                            related_information: Some(vec![RelatedInformation {
                                range: def_key.text_range(),
                                message: format!("immutable {kind} defined here"),
                            }]),
                            ..Default::default()
                        }
                    })
            }),
    );
}