cmake_parser/doc/command/scripting/
cmake_language.rs

1use cmake_parser_derive::CMake;
2
3use crate::{
4    doc::command_scope::{CommandScope, ToCommandScope},
5    Token,
6};
7
8/// Call meta-operations on CMake commands.
9///
10/// Reference: <https://cmake.org/cmake/help/v3.26/command/cmake_language.html>
11#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
12#[cmake(pkg = "crate", transparent)]
13pub enum CMakeLanguage<'t> {
14    Call(CMakeLanguageCall<'t>),
15    Eval(CMakeLanguageEval<'t>),
16    Defer(CMakeLanguageDefer<'t>),
17    SetDependencyProvider(CMakeLanguageSetDependencyProvider<'t>),
18    GetMessageLogLevel(CMakeLanguageGetMessageLogLevel<'t>),
19}
20
21impl<'t> ToCommandScope for CMakeLanguage<'t> {
22    fn to_command_scope(&self) -> CommandScope {
23        CommandScope::Scripting
24    }
25}
26
27#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
28#[cmake(pkg = "crate", positional)]
29pub struct CMakeLanguageCall<'t> {
30    pub command: Token<'t>,
31    pub args: Option<Vec<Token<'t>>>,
32}
33
34#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
35#[cmake(pkg = "crate")]
36pub struct CMakeLanguageEval<'t> {
37    pub code: Vec<Token<'t>>,
38}
39
40#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
41#[cmake(pkg = "crate", untagged)]
42pub enum CMakeLanguageDefer<'t> {
43    Call(CMakeLanguageDeferCall<'t>),
44    GetCallIds(CMakeLanguageDeferGetCallIds<'t>),
45    GetCall(CMakeLanguageDeferGetCall<'t>),
46    CancelCall(CMakeLanguageDeferCancelCall<'t>),
47}
48
49#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
50#[cmake(pkg = "crate", default = "options")]
51pub struct CMakeLanguageDeferCall<'t> {
52    #[cmake(rename = "")]
53    pub options: Option<Vec<DeferCallOption<'t>>>,
54    pub call: CMakeLanguageCall<'t>,
55}
56
57#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
58#[cmake(pkg = "crate", list, transparent)]
59pub enum DeferCallOption<'t> {
60    Directory(Token<'t>),
61    Id(Token<'t>),
62    IdVar(Token<'t>),
63}
64
65#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
66#[cmake(pkg = "crate", positional, transparent)]
67pub struct CMakeLanguageDeferGetCallIds<'t> {
68    pub directory: Option<Token<'t>>,
69    #[cmake(rename = "GET_CALL_IDS")]
70    pub var: Token<'t>,
71}
72
73#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
74#[cmake(pkg = "crate", positional)]
75pub struct CMakeLanguageDeferGetCall<'t> {
76    #[cmake(transparent)]
77    pub directory: Option<Token<'t>>,
78    #[cmake(transparent, rename = "GET_CALL")]
79    pub id: Token<'t>,
80    pub var: Token<'t>,
81}
82
83#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
84#[cmake(pkg = "crate", positional, transparent)]
85pub struct CMakeLanguageDeferCancelCall<'t> {
86    pub directory: Option<Token<'t>>,
87    #[cmake(rename = "CANCEL_CALL")]
88    pub ids: Vec<Token<'t>>,
89}
90
91#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
92#[cmake(pkg = "crate", positional)]
93pub struct CMakeLanguageSetDependencyProvider<'t> {
94    pub command: Token<'t>,
95    #[cmake(transparent)]
96    pub supported_methods: Vec<SuportedMethod>,
97}
98
99#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
100#[cmake(pkg = "crate", list)]
101pub enum SuportedMethod {
102    FindPackage,
103    #[cmake(rename = "FETCHCONTENT_MAKEAVAILABLE_SERIAL")]
104    FetchContentMakeAvailableSerial,
105}
106
107#[derive(CMake, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
108#[cmake(pkg = "crate", positional)]
109pub struct CMakeLanguageGetMessageLogLevel<'t> {
110    pub out_var: Token<'t>,
111}
112
113#[cfg(test)]
114mod tests {
115    use super::*;
116    use crate::doc::cmake_parse::tests::{quoted_token, quoted_tokens_vec, token, tokens_vec};
117    use crate::*;
118    use pretty_assertions::assert_eq;
119
120    #[test]
121    fn cmake_language() {
122        let src = include_bytes!("../../../../../fixture/commands/scripting/cmake_language");
123        let cmakelists = parse_cmakelists(src).unwrap();
124        let doc = Doc::from(cmakelists);
125        assert_eq!(
126            doc.commands(),
127            Ok(vec![
128                Command::CMakeLanguage(Box::new(CMakeLanguage::Call(CMakeLanguageCall {
129                    command: token(b"${message_command}"),
130                    args: Some(vec![token(b"STATUS"), quoted_token(b"Hello World!")]),
131                }))),
132                Command::CMakeLanguage(Box::new(CMakeLanguage::Eval(CMakeLanguageEval {
133                    code: quoted_tokens_vec([br###"
134  if (${condition})
135    message(STATUS TRUE)
136  else()
137    message(STATUS FALSE)
138  endif()"###]),
139                }))),
140                Command::CMakeLanguage(Box::new(CMakeLanguage::Defer(CMakeLanguageDefer::Call(
141                    CMakeLanguageDeferCall {
142                        options: None,
143                        call: CMakeLanguageCall {
144                            command: token(b"message"),
145                            args: Some(vec![quoted_token(b"${deferred_message}")]),
146                        }
147                    }
148                )))),
149                Command::CMakeLanguage(Box::new(CMakeLanguage::Defer(CMakeLanguageDefer::Call(
150                    CMakeLanguageDeferCall {
151                        options: Some(vec![DeferCallOption::IdVar(token(b"id"))]),
152                        call: CMakeLanguageCall {
153                            command: token(b"message"),
154                            args: Some(vec![quoted_token(b"Canceled Message")]),
155                        }
156                    }
157                )))),
158                Command::CMakeLanguage(Box::new(CMakeLanguage::Defer(
159                    CMakeLanguageDefer::GetCallIds(CMakeLanguageDeferGetCallIds {
160                        directory: None,
161                        var: token(b"ids1"),
162                    })
163                ))),
164                Command::CMakeLanguage(Box::new(CMakeLanguage::Defer(
165                    CMakeLanguageDefer::GetCallIds(CMakeLanguageDeferGetCallIds {
166                        directory: Some(token(b"dir1")),
167                        var: token(b"ids1"),
168                    })
169                ))),
170                Command::CMakeLanguage(Box::new(CMakeLanguage::Defer(
171                    CMakeLanguageDefer::GetCall(CMakeLanguageDeferGetCall {
172                        directory: None,
173                        id: token(b"id1"),
174                        var: token(b"var1"),
175                    })
176                ))),
177                Command::CMakeLanguage(Box::new(CMakeLanguage::Defer(
178                    CMakeLanguageDefer::GetCall(CMakeLanguageDeferGetCall {
179                        directory: Some(token(b"dir1")),
180                        id: token(b"id1"),
181                        var: token(b"var1"),
182                    })
183                ))),
184                Command::CMakeLanguage(Box::new(CMakeLanguage::Defer(
185                    CMakeLanguageDefer::CancelCall(CMakeLanguageDeferCancelCall {
186                        directory: None,
187                        ids: tokens_vec([b"${id}"]),
188                    })
189                ))),
190                Command::CMakeLanguage(Box::new(CMakeLanguage::Defer(
191                    CMakeLanguageDefer::CancelCall(CMakeLanguageDeferCancelCall {
192                        directory: Some(token(b"dir1")),
193                        ids: tokens_vec([b"id1", b"id2"]),
194                    })
195                ))),
196                Command::CMakeLanguage(Box::new(CMakeLanguage::SetDependencyProvider(
197                    CMakeLanguageSetDependencyProvider {
198                        command: token(b"cmd1"),
199                        supported_methods: vec![
200                            SuportedMethod::FindPackage,
201                            SuportedMethod::FetchContentMakeAvailableSerial
202                        ],
203                    }
204                ))),
205                Command::CMakeLanguage(Box::new(CMakeLanguage::GetMessageLogLevel(
206                    CMakeLanguageGetMessageLogLevel {
207                        out_var: token(b"out_var1"),
208                    }
209                ))),
210            ])
211        )
212    }
213}