Skip to main content

cmake_tidy_parser/
lib.rs

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}