#![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; #[test] fn message_token_not_expected() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [TEST]", ) .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(vec![Diagnostic { range: Range { start: Position { line: 1, character: 12, }, end: Position { line: 1, character: 18, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String("token_not_expected".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "Expected a different token.".to_owned(), ..Default::default() }]) .run_test(); } #[test] fn message_token_is_missing() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:TYPE1] [ITEM:DOG]", ) .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(vec![ Diagnostic { range: Range { start: Position { line: 2, character: 12, }, end: Position { line: 2, character: 22, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String("token_is_missing".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "Suggest adding one of following tokens here: `TYPE1`.".to_owned(), ..Default::default() }, Diagnostic { range: Range { start: Position { line: 2, character: 12, }, end: Position { line: 2, character: 22, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String("token_not_expected".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "Expected a different token.".to_owned(), ..Default::default() }, ]) .run_test(); } #[test] fn message_invalid_second_par_type() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:T]", ) .add_test_lexer_diagnostics_codes(vec![]) .add_test_lexer_diagnostics_ranges(vec![]), ) .add_test_structure(DebugRaw { header: "h".to_owned(), token_structure: vec![MainToken { ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 1, character: 18, }, end: Position { line: 1, character: 19, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String("invalid_second_par_type".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "`T` is not a valid type in `MAIN`, valid types are \ `TYPE1`, `TYPE2`, `TYPE3`, `TYPE4`, `PROFESSION`, `DEBUG`." .to_owned(), ..Default::default() }]) .run_test(); } #[test] fn message_unknown_token() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:TYPE1] [TYPE1:DOG] [TEST]", ) .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())), ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 3, character: 12, }, end: Position { line: 3, character: 18, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String("unknown_token".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "Unrecognized token `TEST`.".to_owned(), ..Default::default() }]) .run_test(); } #[test] fn message_wrong_arg_number_to_many() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:TYPE1] [TYPE1:DOG] [ITEM: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())), ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 3, character: 12, }, end: Position { line: 3, character: 25, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String("wrong_arg_number".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "Expected 1 arguments, found 4.".to_owned(), ..Default::default() }]) .run_test(); } #[test] fn message_wrong_arg_number_to_few() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:TYPE1] [TYPE1:DOG] [ITEM]", ) .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())), ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 3, character: 12, }, end: Position { line: 3, character: 18, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String("wrong_arg_number".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "Expected at least 1 arguments, found 0.".to_owned(), ..Default::default() }]) .run_test(); } #[test] fn message_wrong_arg_type() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:TYPE1] [TYPE1:DOG] [ITEM: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())), ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 3, character: 18, }, end: Position { line: 3, character: 19, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String("wrong_arg_type".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "Expected Reference, found Integer.".to_owned(), ..Default::default() }]) .run_test(); } #[test] fn message_wrong_enum_value() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:PROFESSION] [PROFESSION:DOG] [GENDER:NOT]", ) .add_test_lexer_diagnostics_codes(vec![]) .add_test_lexer_diagnostics_ranges(vec![]), ) .add_test_structure(DebugRaw { header: "h".to_owned(), token_structure: vec![MainToken { professions: vec![ProfessionToken { reference: Some(ReferenceTo::new("DOG".to_owned())), ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 3, character: 24, }, end: Position { line: 3, character: 27, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String("wrong_enum_value".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "The value `NOT` is not allowed in this enum. Allowed value are: `MALE`, `FEMALE`, `OTHER`.".to_owned(), ..Default::default() }]) .run_test(); } #[test] fn message_too_large_int() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:PROFESSION] [PROFESSION:DOG] [DIFFICULTY:60000]", ) .add_test_lexer_diagnostics_codes(vec![]) .add_test_lexer_diagnostics_ranges(vec![]), ) .add_test_structure(DebugRaw { header: "h".to_owned(), token_structure: vec![MainToken { professions: vec![ProfessionToken { reference: Some(ReferenceTo::new("DOG".to_owned())), ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 3, character: 28, }, end: Position { line: 3, character: 33, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String("too_large_int".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "This parameter does not accept values larger than 255.".to_owned(), ..Default::default() }]) .run_test(); } #[test] fn message_too_small_int() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:PROFESSION] [PROFESSION:DOG] [DIFFICULTY:-200]", ) .add_test_lexer_diagnostics_codes(vec![]) .add_test_lexer_diagnostics_ranges(vec![]), ) .add_test_structure(DebugRaw { header: "h".to_owned(), token_structure: vec![MainToken { professions: vec![ProfessionToken { reference: Some(ReferenceTo::new("DOG".to_owned())), ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 3, character: 28, }, end: Position { line: 3, character: 32, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String("too_small_int".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "This parameter does not accept values smaller than 0.".to_owned(), ..Default::default() }]) .run_test(); } #[test] #[ignore = "This error can not happen because of lexer"] fn message_char_wrong_quote() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:PROFESSION] [PROFESSION:DOG] [SYMBOL:'a!]", ) .add_test_lexer_diagnostics_codes(vec![]) .add_test_lexer_diagnostics_ranges(vec![]), ) .add_test_structure(DebugRaw { header: "h".to_owned(), token_structure: vec![MainToken { professions: vec![ProfessionToken { reference: Some(ReferenceTo::new("DOG".to_owned())), ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 3, character: 16, }, end: Position { line: 3, character: 19, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String("char_wrong_quote".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "Expected `'`(single quote) but found something `!`.".to_owned(), ..Default::default() }]) .run_test(); } #[test] #[ignore = "This error can not happen because of lexer"] fn message_char_expected_more_chars() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:PROFESSION] [PROFESSION:DOG] [SYMBOL:']", ) .add_test_lexer_diagnostics_codes(vec![]) .add_test_lexer_diagnostics_ranges(vec![]), ) .add_test_structure(DebugRaw { header: "h".to_owned(), token_structure: vec![MainToken { professions: vec![ProfessionToken { reference: Some(ReferenceTo::new("DOG".to_owned())), ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 3, character: 16, }, end: Position { line: 3, character: 17, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String( "char_expected_more_chars".to_owned(), )), source: Some("DF RAW Language Server".to_owned()), message: "Expected `'a'`(1 character in single quote) but found only 1 character." .to_owned(), ..Default::default() }]) .run_test(); } #[test] #[ignore = "This error can not happen because of lexer"] fn message_expected_integer() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:PROFESSION] [PROFESSION:DOG] [DIFFICULTY:12.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 { professions: vec![ProfessionToken { reference: Some(ReferenceTo::new("DOG".to_owned())), ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 3, character: 20, }, end: Position { line: 3, character: 24, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String("expected_integer".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "Expected an Integer, but found `12.5`. \ Could not covert this to an Integer: Not an Integer." .to_owned(), ..Default::default() }]) .run_test(); } #[test] fn message_duplicate_token_warn() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:PROFESSION] [PROFESSION:DOG] [DIFFICULTY:12] [DIFFICULTY:35]", ) .add_test_lexer_diagnostics_codes(vec![]) .add_test_lexer_diagnostics_ranges(vec![]), ) .add_test_structure(DebugRaw { header: "h".to_owned(), token_structure: vec![MainToken { professions: vec![ProfessionToken { reference: Some(ReferenceTo::new("DOG".to_owned())), difficulty: Some(12), ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 4, character: 16, }, end: Position { line: 4, character: 31, }, }, severity: Some(DiagnosticSeverity::WARNING), code: Some(NumberOrString::String("duplicate_token_warn".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "Duplicate token: `DIFFICULTY` already exists in this `PROFESSION`.".to_owned(), ..Default::default() }]) .run_test(); } #[test] fn message_duplicate_token_error() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:PROFESSION] [PROFESSION:DOG] [DIFFICULTY_HARD:12] [DIFFICULTY_HARD:35]", ) .add_test_lexer_diagnostics_codes(vec![]) .add_test_lexer_diagnostics_ranges(vec![]), ) .add_test_structure(DebugRaw { header: "h".to_owned(), token_structure: vec![MainToken { professions: vec![ProfessionToken { reference: Some(ReferenceTo::new("DOG".to_owned())), difficulty_hard: Some(12), ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 4, character: 16, }, end: Position { line: 4, character: 36, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String("duplicate_token_error".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "Duplicate token: `DIFFICULTY_HARD` already exists in this `PROFESSION`." .to_owned(), ..Default::default() }]) .run_test(); } #[test] fn message_reference_is_string() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:PROFESSION] [PROFESSION:Dog]", ) .add_test_lexer_diagnostics_codes(vec![]) .add_test_lexer_diagnostics_ranges(vec![]), ) .add_test_structure(DebugRaw { header: "h".to_owned(), token_structure: vec![MainToken { professions: vec![ProfessionToken { reference: Some(ReferenceTo::new("Dog".to_owned())), ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 2, character: 24, }, end: Position { line: 2, character: 27, }, }, severity: Some(DiagnosticSeverity::WARNING), code: Some(NumberOrString::String("reference_is_string".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "Expected `Reference` but found `String`. Make sure to only use UPPERCASE, numbers and `_`." .to_owned(), ..Default::default() }]) .run_test(); } #[test] fn message_string_is_reference() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:PROFESSION] [PROFESSION:DOG] [ARG:CPU]", ) .add_test_lexer_diagnostics_codes(vec![]) .add_test_lexer_diagnostics_ranges(vec![]), ) .add_test_structure(DebugRaw { header: "h".to_owned(), token_structure: vec![MainToken { professions: vec![ProfessionToken { reference: Some(ReferenceTo::new("DOG".to_owned())), argument: Some(("CPU".to_owned(), None)), ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 3, character: 17, }, end: Position { line: 3, character: 20, }, }, severity: Some(DiagnosticSeverity::WARNING), code: Some(NumberOrString::String("string_is_reference".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "Expected `String` but found `Reference`. \ If possible, try to use at least 1 lowercase character, space, \ or special character like `.` or `,` or `!`." .to_owned(), ..Default::default() }]) .run_test(); } #[test] fn message_alias() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:PROFESSION] [PROFESSION:DOG] [JOB:DRINKING]", ) .add_test_lexer_diagnostics_codes(vec![]) .add_test_lexer_diagnostics_ranges(vec![]), ) .add_test_structure(DebugRaw { header: "h".to_owned(), token_structure: vec![MainToken { professions: vec![ProfessionToken { reference: Some(ReferenceTo::new("DOG".to_owned())), name: vec![Reference("DRINKING".to_owned())], ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![Diagnostic { range: Range { start: Position { line: 3, character: 17, }, end: Position { line: 3, character: 20, }, }, severity: Some(DiagnosticSeverity::WARNING), code: Some(NumberOrString::String("alias".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "The token `JOB` is an alias, please use `NAME`.".to_owned(), ..Default::default() }]) .run_test(); } #[test] fn message_unchecked_code() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "h [MAIN:PROFESSION] [PROFESSION:DOG] [TTTTTTT] [TEST]", ) .add_test_lexer_diagnostics_codes(vec![]) .add_test_lexer_diagnostics_ranges(vec![]), ) .add_test_structure(DebugRaw { header: "h".to_owned(), token_structure: vec![MainToken { professions: vec![ProfessionToken { reference: Some(ReferenceTo::new("DOG".to_owned())), ..Default::default() }], ..Default::default() }], }) .add_test_syntax_diagnostics(vec![ Diagnostic { range: Range { start: Position { line: 3, character: 16, }, end: Position { line: 3, character: 25, }, }, severity: Some(DiagnosticSeverity::ERROR), code: Some(NumberOrString::String("unknown_token".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "Unrecognized token `TTTTTTT`.".to_owned(), ..Default::default() }, Diagnostic { range: Range { start: Position { line: 3, character: 25, }, end: Position { line: 4, character: 18, }, }, severity: Some(DiagnosticSeverity::WARNING), code: Some(NumberOrString::String("unchecked_code".to_owned())), source: Some("DF RAW Language Server".to_owned()), message: "This code could not be checked because of previous error.".to_owned(), ..Default::default() }, ]) .run_test(); }