wat_service 0.8.0

WebAssembly Text Format language service.
Documentation
use crate::{
    LanguageService,
    binder::{SymbolKind, SymbolTable},
    document::Document,
    helpers, mutability,
    uri::InternUri,
};
use line_index::LineIndex;
use lspt::{Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, Location, Union2};

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

pub fn check(
    service: &LanguageService,
    diagnostics: &mut Vec<Diagnostic>,
    uri: InternUri,
    document: Document,
    line_index: &LineIndex,
    symbol_table: &SymbolTable,
) {
    let mutabilities = mutability::get_mutabilities(service, document);
    let mutation_actions = mutability::get_mutation_actions(service, 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: helpers::rowan_range_to_lsp_range(line_index, key.text_range()),
                            severity: Some(DiagnosticSeverity::Error),
                            source: Some("wat".into()),
                            code: Some(Union2::B(DIAGNOSTIC_CODE.into())),
                            message: format!(
                                "mutating the immutable {kind} `{}` is not allowed",
                                ref_symbol.idx.render(service)
                            ),
                            related_information: Some(vec![DiagnosticRelatedInformation {
                                location: Location {
                                    uri: uri.raw(service),
                                    range: helpers::rowan_range_to_lsp_range(
                                        line_index,
                                        def_key.text_range(),
                                    ),
                                },
                                message: format!("immutable {kind} defined here"),
                            }]),
                            ..Default::default()
                        }
                    })
            }),
    );
}