df_ls_syntax_analysis 0.3.0-rc.1

A language server for Dwarf Fortress RAW files
Documentation
#![allow(clippy::needless_update)]

use df_ls_core::{Reference, ReferenceTo};
use df_ls_debug_structure::*;
use df_ls_diagnostics::lsp_types::*;
use df_ls_lexical_analysis::test_utils::LexerTestBuilder;
use df_ls_syntax_analysis::test_utils::SyntaxTestBuilder;

/// Testing `wrong_arg_type` error is produced when an int is given instead of a Ref
#[test]
fn wrong_arg_type_ref_to_int() {
    SyntaxTestBuilder::from_lexer_test_builder(
        LexerTestBuilder::test_source(
            "h
            [MAIN:TYPE2]

            [BIPEDAL:MONSTER]
                [NAME:test]
                [EDUCATION:inn:beer:5]
            [MAIN:TYPE1]

            [TYPE1:111]
                [ITEM:T1]
            ",
        )
        .add_test_lexer_diagnostics_codes(vec![])
        .add_test_lexer_diagnostics_ranges(vec![]),
    )
    .add_test_structure(DebugRaw {
        header: "h".to_owned(),
        token_structure: vec![MainToken {
            type_1: vec![],
            type_2: vec![Type2Token::Bipedal(HumanToken {
                reference: Some(ReferenceTo::new("MONSTER".to_owned())),
                name: Some("test".to_owned()),
                educations: vec![("inn".to_owned(), "beer".to_owned(), 5)],
                ..Default::default()
            })],
            ..Default::default()
        }],
    })
    .add_test_syntax_diagnostics_codes(vec![
        "wrong_arg_type",
        "token_is_missing",
        "unknown_token",
        "unchecked_code",
    ])
    .add_test_syntax_diagnostics_ranges(vec![
        Range {
            start: Position {
                line: 8,
                character: 19,
            },
            end: Position {
                line: 8,
                character: 22,
            },
        },
        Range {
            start: Position {
                line: 9,
                character: 16,
            },
            end: Position {
                line: 9,
                character: 25,
            },
        },
        Range {
            start: Position {
                line: 9,
                character: 16,
            },
            end: Position {
                line: 9,
                character: 25,
            },
        },
        Range {
            start: Position {
                line: 9,
                character: 25,
            },
            end: Position {
                line: 10,
                character: 12,
            },
        },
    ])
    .run_test();
}

/// Testing `wrong_arg_type` error is produced
/// when a char is given instead of a Ref
#[test]
fn wrong_arg_type_ref_to_char() {
    SyntaxTestBuilder::from_lexer_test_builder(
        LexerTestBuilder::test_source(
            "h
            [MAIN:TYPE1]

            [TYPE1:'c']
                [ITEM:T1]

            [MAIN:TYPE2]

            [BIPEDAL:MONSTER]
                [NAME:test]
                [EDUCATION:inn:beer:5]
            ",
        )
        .add_test_lexer_diagnostics_codes(vec![])
        .add_test_lexer_diagnostics_ranges(vec![]),
    )
    .add_test_structure(DebugRaw {
        header: "".to_owned(), // TODO this should still be correctly deserialized. See #20
        token_structure: vec![],
    })
    .add_test_syntax_diagnostics_codes(vec![
        "wrong_arg_type",
        "token_is_missing",
        "token_not_expected",
        "unchecked_code",
    ])
    .add_test_syntax_diagnostics_ranges(vec![
        Range {
            start: Position {
                line: 3,
                character: 19,
            },
            end: Position {
                line: 3,
                character: 22,
            },
        },
        Range {
            start: Position {
                line: 4,
                character: 16,
            },
            end: Position {
                line: 4,
                character: 25,
            },
        },
        Range {
            start: Position {
                line: 4,
                character: 16,
            },
            end: Position {
                line: 4,
                character: 25,
            },
        },
        Range {
            start: Position {
                line: 4,
                character: 25,
            },
            end: Position {
                line: 11,
                character: 12,
            },
        },
    ])
    .run_test();
}

// Due to #32, references can accept strings without giving a `wrong_arg_type` error.

/// Testing `wrong_arg_type` error is produced when an "empty" is given instead of a Ref
#[test]
fn wrong_arg_type_ref_to_empty() {
    SyntaxTestBuilder::from_lexer_test_builder(
        LexerTestBuilder::test_source(
            "h
            [MAIN:TYPE1]

            [TYPE1:]
                [ITEM:T1]

            [MAIN:TYPE2]

            [BIPEDAL:MONSTER]
                [NAME:test]
                [EDUCATION:inn:beer:5]
            ",
        )
        .add_test_lexer_diagnostics_codes(vec![])
        .add_test_lexer_diagnostics_ranges(vec![]),
    )
    .add_test_structure(DebugRaw {
        header: "".to_owned(), // TODO this should still be correctly deserialized. See #20
        token_structure: vec![],
    })
    .add_test_syntax_diagnostics_codes(vec![
        "wrong_arg_type",
        "token_is_missing",
        "token_not_expected",
        "unchecked_code",
    ])
    .add_test_syntax_diagnostics_ranges(vec![
        Range {
            start: Position {
                line: 3,
                character: 19,
            },
            end: Position {
                line: 3,
                character: 19,
            },
        },
        Range {
            start: Position {
                line: 4,
                character: 16,
            },
            end: Position {
                line: 4,
                character: 25,
            },
        },
        Range {
            start: Position {
                line: 4,
                character: 16,
            },
            end: Position {
                line: 4,
                character: 25,
            },
        },
        Range {
            start: Position {
                line: 4,
                character: 25,
            },
            end: Position {
                line: 11,
                character: 12,
            },
        },
    ])
    .run_test();
}

/// Testing `wrong_arg_type` error is produced when an int is given instead of a string
#[test]
fn wrong_arg_type_string_to_int() {
    SyntaxTestBuilder::from_lexer_test_builder(
        LexerTestBuilder::test_source(
            "h
            [MAIN:TYPE1]

            [TYPE1:DOG]
                [ITEM:T1]

            [MAIN:TYPE2]

            [BIPEDAL:MONSTER]
                [NAME:111]
                [EDUCATION:inn:beer:5]
            ",
        )
        .add_test_lexer_diagnostics_codes(vec![])
        .add_test_lexer_diagnostics_ranges(vec![]),
    )
    .add_test_structure(DebugRaw {
        header: "h".to_owned(),
        token_structure: vec![MainToken {
            type_1: vec![Type1Token {
                reference: Some(Reference("DOG".to_owned())),
                list: vec![Reference("T1".to_owned())],
                ..Default::default()
            }],
            type_2: vec![Type2Token::Bipedal(HumanToken {
                reference: Some(ReferenceTo::new("MONSTER".to_owned())),
                name: None,
                educations: vec![("inn".to_owned(), "beer".to_owned(), 5)],
                ..Default::default()
            })],
            ..Default::default()
        }],
    })
    .add_test_syntax_diagnostics_codes(vec!["wrong_arg_type"])
    .add_test_syntax_diagnostics_ranges(vec![Range {
        start: Position {
            line: 9,
            character: 22,
        },
        end: Position {
            line: 9,
            character: 25,
        },
    }])
    .run_test();
}

/// Testing `wrong_arg_type` error is produced
/// when a char is given instead of a string
#[test]
fn wrong_arg_type_string_to_char() {
    SyntaxTestBuilder::from_lexer_test_builder(
        LexerTestBuilder::test_source(
            "h
            [MAIN:TYPE1]

            [TYPE1:DOG]
                [ITEM:T1]

            [MAIN:TYPE2]

            [BIPEDAL:MONSTER]
                [NAME:'A']
                [EDUCATION:inn:beer:5]
            ",
        )
        .add_test_lexer_diagnostics_codes(vec![])
        .add_test_lexer_diagnostics_ranges(vec![]),
    )
    .add_test_structure(DebugRaw {
        header: "h".to_owned(),
        token_structure: vec![MainToken {
            type_1: vec![Type1Token {
                reference: Some(Reference("DOG".to_owned())),
                list: vec![Reference("T1".to_owned())],
                ..Default::default()
            }],
            type_2: vec![Type2Token::Bipedal(HumanToken {
                reference: Some(ReferenceTo::new("MONSTER".to_owned())),
                name: None,
                educations: vec![("inn".to_owned(), "beer".to_owned(), 5)],
                ..Default::default()
            })],
            ..Default::default()
        }],
    })
    .add_test_syntax_diagnostics_codes(vec!["wrong_arg_type"])
    .add_test_syntax_diagnostics_ranges(vec![Range {
        start: Position {
            line: 9,
            character: 22,
        },
        end: Position {
            line: 9,
            character: 25,
        },
    }])
    .run_test();
}

// Due to #100, strings can accept references without giving a `wrong_arg_type` error.

/// Testing `wrong_arg_type` error is produced when an "empty" is given instead of a string
#[test]
fn wrong_arg_type_string_to_empty() {
    SyntaxTestBuilder::from_lexer_test_builder(
        LexerTestBuilder::test_source(
            "h
            [MAIN:TYPE1]

            [TYPE1:DOG]
                [ITEM:T1]

            [MAIN:TYPE2]

            [BIPEDAL:MONSTER]
                [NAME:]
                [EDUCATION:inn:beer:5]
            ",
        )
        .add_test_lexer_diagnostics_codes(vec![])
        .add_test_lexer_diagnostics_ranges(vec![]),
    )
    .add_test_structure(DebugRaw {
        header: "h".to_owned(),
        token_structure: vec![MainToken {
            type_1: vec![Type1Token {
                reference: Some(Reference("DOG".to_owned())),
                list: vec![Reference("T1".to_owned())],
                ..Default::default()
            }],
            type_2: vec![Type2Token::Bipedal(HumanToken {
                reference: Some(ReferenceTo::new("MONSTER".to_owned())),
                name: None,
                educations: vec![("inn".to_owned(), "beer".to_owned(), 5)],
                ..Default::default()
            })],
            ..Default::default()
        }],
    })
    .add_test_syntax_diagnostics_codes(vec!["wrong_arg_type"])
    .add_test_syntax_diagnostics_ranges(vec![Range {
        start: Position {
            line: 9,
            character: 22,
        },
        end: Position {
            line: 9,
            character: 22,
        },
    }])
    .run_test();
}

// Testing `wrong_arg_type` errors are produced
// when a string is given instead an int in a multi-int token
#[test]
fn wrong_arg_type_int() {
    SyntaxTestBuilder::from_lexer_test_builder(
        LexerTestBuilder::test_source(
            "h
            [MAIN:TYPE1]

            [TYPE1:DOG]
                [ITEM:T1]

            [MAIN:TYPE2]

            [BIPEDAL:MONSTER]
                [NAME:my name]
                [EDUCATION:inn:beer:to long]
            ",
        )
        .add_test_lexer_diagnostics_codes(vec![])
        .add_test_lexer_diagnostics_ranges(vec![]),
    )
    .add_test_structure(DebugRaw {
        header: "h".to_owned(),
        token_structure: vec![MainToken {
            type_1: vec![Type1Token {
                reference: Some(Reference("DOG".to_owned())),
                list: vec![Reference("T1".to_owned())],
                ..Default::default()
            }],
            type_2: vec![Type2Token::Bipedal(HumanToken {
                reference: Some(ReferenceTo::new("MONSTER".to_owned())),
                name: Some("my name".to_owned()),
                ..Default::default()
            })],
            ..Default::default()
        }],
    })
    .add_test_syntax_diagnostics_codes(vec!["wrong_arg_type"])
    .add_test_syntax_diagnostics_ranges(vec![Range {
        start: Position {
            line: 10,
            character: 36,
        },
        end: Position {
            line: 10,
            character: 43,
        },
    }])
    .run_test();
}

// Testing 3 `wrong_arg_type` errors are produced
// when a char, reference and string are given instead of 3 ints
#[test]
fn wrong_arg_type_int_multiple() {
    SyntaxTestBuilder::from_lexer_test_builder(
        LexerTestBuilder::test_source(
            "h
            [MAIN:TYPE1]

            [TYPE1:DOG]
                [ITEM:T1]

            [MAIN:TYPE2]

            [BIPEDAL:MONSTER]
                [NAME:my name]
                [EDUCATION:inn:beer:'c']
                [EDUCATION:inn:beer:REF]
            ",
        )
        .add_test_lexer_diagnostics_codes(vec![])
        .add_test_lexer_diagnostics_ranges(vec![]),
    )
    .add_test_structure(DebugRaw {
        header: "h".to_owned(),
        token_structure: vec![MainToken {
            type_1: vec![Type1Token {
                reference: Some(Reference("DOG".to_owned())),
                list: vec![Reference("T1".to_owned())],
                ..Default::default()
            }],
            type_2: vec![Type2Token::Bipedal(HumanToken {
                reference: Some(ReferenceTo::new("MONSTER".to_owned())),
                name: Some("my name".to_owned()),
                ..Default::default()
            })],
            ..Default::default()
        }],
    })
    .add_test_syntax_diagnostics_codes(vec!["wrong_arg_type", "wrong_arg_type"])
    .add_test_syntax_diagnostics_ranges(vec![
        Range {
            start: Position {
                line: 10,
                character: 36,
            },
            end: Position {
                line: 10,
                character: 39,
            },
        },
        Range {
            start: Position {
                line: 11,
                character: 36,
            },
            end: Position {
                line: 11,
                character: 39,
            },
        },
    ])
    .run_test();
}