wat_service 0.10.1

WebAssembly Text Format language service.
Documentation
use super::Diagnostic;
use crate::{
    binder::{SymbolKind, SymbolTable},
    config::LintLevel,
    document::Document,
    mutability,
};
use lspt::{DiagnosticSeverity, DiagnosticTag};

const DIAGNOSTIC_CODE: &str = "needless-mut";

pub fn check(
    db: &dyn salsa::Database,
    diagnostics: &mut Vec<Diagnostic>,
    lint_level: LintLevel,
    document: Document,
    symbol_table: &SymbolTable,
) {
    let severity = match lint_level {
        LintLevel::Allow => return,
        LintLevel::Hint => DiagnosticSeverity::Hint,
        LintLevel::Warn => DiagnosticSeverity::Warning,
        LintLevel::Deny => DiagnosticSeverity::Error,
    };

    let mutation_actions = mutability::get_mutation_actions(db, document);
    diagnostics.extend(
        mutability::get_mutabilities(db, document)
            .iter()
            .filter(|(key, mutability)| {
                mutability.mut_keyword.is_some()
                    && !mutability.cross_module
                    && mutation_actions
                        .values()
                        .filter(|action| action.target.is_some_and(|target| target == **key))
                        .all(|action| action.kind == mutability::MutationActionKind::Get)
            })
            .filter_map(|(key, mutability)| symbol_table.symbols.get(key).zip(mutability.mut_keyword))
            .map(|(symbol, keyword_range)| {
                let kind = match symbol.kind {
                    SymbolKind::GlobalDef => "global",
                    SymbolKind::Type => "array",
                    SymbolKind::FieldDef => "field",
                    _ => unreachable!(),
                };
                Diagnostic {
                    range: keyword_range,
                    severity,
                    code: DIAGNOSTIC_CODE.into(),
                    message: format!("{kind} `{}` is unnecessarily mutable", symbol.idx.render(db)),
                    tags: Some(vec![DiagnosticTag::Unnecessary]),
                    ..Default::default()
                }
            }),
    );
}