a2kit 4.4.0

Retro disk image and language utility
Documentation
//! Test of Merlin diagnostics modules.

use super::super::{MerlinVersion,diagnostics,settings};
use lsp_types::DiagnosticSeverity;

#[cfg(test)]
fn test_diagnostics(prog_name: &str, vers: Option<MerlinVersion>, unused: Option<DiagnosticSeverity>, expected_messages: &[&str]) {
    use crate::lang::server::Analysis;
    let ws = std::env::current_dir().expect("no cwd").join("tests").join("merlin");
    let path = ws.join(prog_name);
    let ws_uri = crate::lang::uri_from_path(&ws).expect("bad URI");
    let doc = crate::lang::Document::from_file_path(&path).expect("failed to create doc");
    let mut analyzer = diagnostics::Analyzer::new();
    let mut config = settings::Settings::new();
    if let Some(v) = vers {
        config.version = v;
    }
    config.flag.unused_labels = unused;
    analyzer.set_config(config);
    analyzer.init_workspace(vec![ws_uri], Vec::new()).expect("could not init workspace");
    analyzer.analyze(&doc).expect("could not analyze");
    let diag_set = analyzer.get_diags(&doc);
    assert_eq!(diag_set.len(),expected_messages.len());
	for i in 0..diag_set.len() {
		assert_eq!(expected_messages[i],diag_set[i].message);
	}
}

mod processors {
    use super::MerlinVersion;
    #[test]
    fn disable_65c02() {
        super::test_diagnostics("test-65c02-disabled.S", None, None, &[
            "macro is undefined",
            "macro is undefined",
            "macro name matches a disabled instruction",
            "macro name matches a disabled instruction"
        ]);
    }
    #[test]
    fn enable_65c02() {
        super::test_diagnostics("test-65c02-disabled.S", Some(MerlinVersion::Merlin32), None, &[
        ]);
    }
    #[test]
    fn disable_65816() {
        super::test_diagnostics("test-65816-disabled.S", None, None, &[
            "addressing mode disabled, use XC pseudo-op to enable"
        ]);
    }
    #[test]
    fn enable_65816() {
        super::test_diagnostics("test-65816-disabled.S", Some(MerlinVersion::Merlin32), None, &[
            "this would cause the XC count to exceed 2"
        ]);
    }
}

mod macros {
    use super::MerlinVersion;
    #[test]
    fn matches_instruction() {
        super::test_diagnostics("test-matches-instruction.S", None, None, &[
            "macro name matches a mnemonic",
            "macro name matches a mnemonic",
            "folding range is never closed",
            "folding range is never closed",
            "macro is never referenced",
            "macro is never referenced",
        ]);
    }
    #[test]
    fn undefined() {
        super::test_diagnostics("test-mac-undefined.S", None, None, &[
            "macro is undefined",
            "macro is undefined",
            "macro is undefined"
        ]);
    }
    #[test]
    fn forward_ref() {
        super::test_diagnostics("test-mac-forward.S", None, None, &[
            "macro is forward referenced"
        ]);
    }
    #[test]
    fn context() {
        super::test_diagnostics("test-mac-context.S", None, None, &[
            "macro is never referenced",
            "macro cannot be used here"
        ]);
    }
    #[test]
    fn termination() {
        super::test_diagnostics("test-mac-termination.S", None, None, &[
            "unmatched end of macro (EOM terminates all preceding MAC)",
            "macro is never referenced",
        ]);
    }
    #[test]
    fn pseudo_ops() {
        super::test_diagnostics("test-mac-psops.S", None, None, &[
            "macro is never referenced",
            "pseudo operation cannot be used in a macro",
            "pseudo operation cannot be used in a macro",
            "pseudo operation cannot be used in a macro"
        ]);
    }
    #[test]
    fn variables() {
        super::test_diagnostics("test-mac-vars.S", None, None, &[
            "macro substitution variable cannot label a line",
            "macro substitution variable cannot label a line",
            "extension cannot evaluate, assuming true",
            "macro substitution variable referenced outside macro",
            "macro is never referenced",
            "macro substitution variable referenced outside macro",
            "macro substitution variable referenced outside macro",
        ]);
    }
    #[test]
    fn arguments() {
        super::test_diagnostics("test-mac-args.S", None, None, &[
            "assembly disabled by ELSE",
            "argument missing: `]3`",
            "argument not used",
            "conditionally missing argument: `]2`",
            "argument not used",
            "uninterpreted literal"
        ]);
    }
    #[test]
    fn recursive_refs() {
        super::test_diagnostics("test-mac-recursive-refs.S", Some(MerlinVersion::Merlin32), None, &[
            "evaluation was deferred",
            "evaluation was deferred",
            "evaluation was deferred",
            "evaluation was deferred",
            "assembly disabled by DO",
            "evaluation was deferred",
            "forward reference check deferred",
            "macro is never referenced",
        ]);
    }
    #[test]
    fn nested() {
        super::test_diagnostics("test-mac-nested.S", None, None, &[
            "label is undefined in this scope",
            "label is undefined in this scope",
        ]);
    }
}

mod declarations {
    use lsp_types::DiagnosticSeverity;

    #[test]
    fn undefined_global() {
        super::test_diagnostics("test-decs-un-glob.S", None, None, &[
            "global label is undefined"
        ]);
    }
    #[test]
    fn undefined_local() {
        super::test_diagnostics("test-decs-un-loc.S", None, None, &[
            "local label is not defined in this scope"
        ]);
    }
    #[test]
    fn forward_variable() {
        super::test_diagnostics("test-decs-fwd-var.S", None, None, &[
            "macro substitution variable cannot label a line",
            "variable is forward referenced"
        ]);
    }
    #[test]
    fn forward_variable_strict() {
        super::test_diagnostics("test-decs-fwd-var.S", None, Some(DiagnosticSeverity::WARNING), &[
            "macro substitution variable cannot label a line",
            "label is never referenced",
            "if this is intentional, change it to _SCOPE",
            "label is never referenced",
            "if this is intentional, change it to :_loc1",
            "variable is forward referenced",
            "label is never referenced",
            "if this is intentional, change it to ]_1",
        ]);
    }
    #[test]
    fn redefinitions() {
        super::test_diagnostics("test-decs-redefined.S", None, None, &[
            "redefinition of a global label",
            "redefinition of a local label"
        ]);
    }
}

mod locals {
    #[test]
    fn no_scope() {
        super::test_diagnostics("test-loc-noscope.S", None, None, &[
            "no global scope is defined yet"
        ]);
    }
    #[test]
    fn forbidden_pseudo_op() {
        super::test_diagnostics("test-loc-psops.S", None, None, &[
            "cannot use local label for EQU",
            "cannot use local label for ENT",
            "cannot use local label for EXT"
        ]);
    }
    #[test]
    fn local_in_macro() {
        super::test_diagnostics("test-loc-macro.S", None, None, &[
            "macro is never referenced",
            "cannot use local labels in a macro"
        ]);
    }

}

mod equates {
    use super::MerlinVersion;
    #[test]
    fn externals() {
        super::test_diagnostics("test-ext-equates.S", None, None, &[
            "pseudo-op argument is disabled for the selected Merlin version",
            "pseudo-op argument is disabled for the selected Merlin version",
            "pseudo-op argument is disabled for the selected Merlin version"
        ]);
    }
    #[test]
    fn externals32() {
        super::test_diagnostics("test-ext-equates.S", Some(MerlinVersion::Merlin32), None, &[
        ]);
    }
    #[test]
    fn entries() {
        super::test_diagnostics("test-ent-equates.S", None, None, &[
            "entry label declared, but never defined",
            "pseudo-op argument is disabled for the selected Merlin version",
            "pseudo-op argument is disabled for the selected Merlin version",
            "pseudo-op argument is disabled for the selected Merlin version"
        ]);
    }
    #[test]
    fn entries32() {
        super::test_diagnostics("test-ent-equates.S", Some(MerlinVersion::Merlin32), None, &[
            "entry label declared, but never defined",
        ]);
    }
}

mod forward {
    #[test]
    fn psop_fwd() {
        super::test_diagnostics("test-ill-fwd.S", None, None, &[
            "evaluation was deferred",
            "illegal forward reference",
            "forward reference check deferred"
        ])
    }
}