m2-syn 0.4.0

Typed syntax trees, traversal, and parser adapters for Macaulay2
Documentation
//! Integration tests for realtime parser.

use m2_syn::{Lex, LexErrorKind, ParseError, RealtimeParser, Spanned, TextEdit};

#[test]
fn realtime_parser_retains_and_then_completes_an_unclosed_group() {
    let mut parser = RealtimeParser::new("[x").unwrap();
    let source_id = parser.syntax().span().source_id();
    assert_eq!(parser.source(), "[x");
    assert_eq!(parser.syntax().to_m2(), "[x");
    assert_eq!(parser.diagnostics().len(), 1);
    assert_eq!(
        parser.diagnostics()[0].kind(),
        LexErrorKind::UnterminatedGroup
    );
    assert_eq!(parser.diagnostics()[0].span().bounds(), Some((0, 2)));
    assert_eq!(
        parser.diagnostics()[0].unclosed_expression(),
        Some("array expression")
    );
    assert_eq!(parser.diagnostics()[0].expected(), Some("]"));
    assert_eq!(parser.diagnostics()[0].found(), Some("end of input"));
    assert_eq!(
        parser.diagnostics()[0].to_string(),
        "unclosed array expression: expected `]`, found end of input"
    );

    parser.apply_edit(&TextEdit::insertion(2, ", y")).unwrap();
    assert_eq!(parser.syntax().span().source_id(), source_id);
    assert_eq!(parser.source(), "[x, y");
    assert_eq!(parser.syntax().to_m2(), "[x, y");
    assert_eq!(parser.diagnostics()[0].span().bounds(), Some((0, 5)));
    assert!(!parser.changed_ranges().is_empty());

    parser.apply_edit(&TextEdit::insertion(5, "]")).unwrap();
    assert_eq!(parser.source(), "[x, y]");
    assert_eq!(parser.syntax().to_m2(), "[x, y]");
    assert!(parser.diagnostics().is_empty());
    assert_eq!(parser.syntax().span().text(), Some("[x, y]"));
}

#[test]
fn realtime_parser_handles_multibyte_offsets_and_rejects_invalid_edits_transactionally() {
    let mut parser = RealtimeParser::new("é + x").unwrap();
    parser
        .apply_edit(&TextEdit::insertion("é + x".len(), " + β"))
        .unwrap();
    assert_eq!(parser.source(), "é + x + β");
    assert_eq!(parser.syntax().to_m2(), "é + x + β");

    let previous = parser.source().to_owned();
    assert!(matches!(
        parser.apply_edit(&TextEdit::insertion(usize::MAX, "x")),
        Err(ParseError::InvalidEdit)
    ));
    assert_eq!(parser.source(), previous);
    assert_eq!(parser.syntax().to_m2(), "é + x + β");
}