1mod parsed;
2mod parser;
3mod token_source;
4
5pub use parsed::{ParseError, Parsed};
6pub use parser::parse_file;
7
8#[cfg(test)]
9mod tests {
10 use cmake_tidy_ast::{Argument, Statement};
11
12 use crate::parse_file;
13
14 #[test]
15 fn parses_simple_command_invocations() {
16 let parsed =
17 parse_file("cmake_minimum_required(VERSION 3.30)\nproject(example LANGUAGES C CXX)\n");
18
19 assert!(parsed.errors.is_empty());
20 assert_eq!(parsed.syntax.items.len(), 2);
21
22 let Statement::Command(command) = &parsed.syntax.items[0];
23 assert_eq!(command.name.text, "cmake_minimum_required");
24 assert_eq!(command.arguments.len(), 2);
25
26 let Argument::Unquoted(version) = &command.arguments[0] else {
27 panic!("expected an unquoted argument");
28 };
29 assert_eq!(version.text, "VERSION");
30 }
31
32 #[test]
33 fn parses_nested_parenthesized_arguments() {
34 let parsed = parse_file("if((A AND B) OR C)\nendif()");
35 assert!(parsed.errors.is_empty());
36
37 let Statement::Command(command) = &parsed.syntax.items[0];
38 assert!(matches!(command.arguments[0], Argument::ParenGroup(_)));
39 }
40
41 #[test]
42 fn reports_missing_left_paren_after_command_name() {
43 let parsed = parse_file("project example");
44
45 assert_eq!(parsed.syntax.items.len(), 2);
46 assert_eq!(parsed.errors.len(), 2);
47 assert_eq!(parsed.errors[0].message, "expected `(` after command name");
48 assert_eq!(parsed.errors[1].message, "expected `(` after command name");
49 }
50
51 #[test]
52 fn reports_missing_closing_paren() {
53 let parsed = parse_file("project(example");
54
55 assert_eq!(parsed.syntax.items.len(), 1);
56 assert_eq!(parsed.errors.len(), 1);
57 assert_eq!(
58 parsed.errors[0].message,
59 "expected `)` to close command invocation"
60 );
61 }
62
63 #[test]
64 fn reports_non_identifier_at_statement_start() {
65 let parsed = parse_file("\"oops\"\nproject(example)\n");
66
67 assert_eq!(parsed.syntax.items.len(), 1);
68 assert_eq!(parsed.errors.len(), 1);
69 assert_eq!(parsed.errors[0].message, "expected a command name");
70
71 let Statement::Command(command) = &parsed.syntax.items[0];
72 assert_eq!(command.name.text, "project");
73 }
74
75 #[test]
76 fn reports_nested_group_missing_outer_closing_paren() {
77 let parsed = parse_file("project(()\n");
78
79 assert_eq!(parsed.syntax.items.len(), 1);
80 assert_eq!(parsed.errors.len(), 1);
81 assert_eq!(
82 parsed.errors[0].message,
83 "expected `)` to close command invocation"
84 );
85 }
86}