Skip to main content

just_lsp/
recipe.rs

1use super::*;
2
3#[derive(Debug, Clone, PartialEq)]
4pub struct Recipe {
5  pub attributes: Vec<Attribute>,
6  pub content: String,
7  pub dependencies: Vec<Dependency>,
8  pub name: TextNode,
9  pub parameters: Vec<Parameter>,
10  pub range: lsp::Range,
11  pub shebang: Option<TextNode>,
12}
13
14impl Recipe {
15  #[must_use]
16  pub fn find_attribute(&self, name: &str) -> Option<&Attribute> {
17    self
18      .attributes
19      .iter()
20      .find(|attribute| attribute.name.value == name)
21  }
22
23  #[must_use]
24  pub fn groups(&self) -> HashSet<Group> {
25    let mut groups = HashSet::new();
26
27    for attribute in &self.attributes {
28      let attribute_name = attribute.name.value.as_str();
29
30      if let Some(targets) = Group::targets(attribute_name) {
31        groups.extend(targets);
32      }
33    }
34
35    if groups.is_empty() {
36      groups.insert(Group::Any);
37    }
38
39    groups
40  }
41
42  #[must_use]
43  pub fn has_attribute(&self, name: &str) -> bool {
44    self
45      .attributes
46      .iter()
47      .any(|attribute| attribute.name.value == name)
48  }
49}
50
51#[cfg(test)]
52mod tests {
53  use super::*;
54
55  #[test]
56  fn recipe_groups_no_attributes() {
57    let recipe = Recipe {
58      name: TextNode {
59        value: "test".into(),
60        range: lsp::Range::at(0, 0, 0, 4),
61      },
62      attributes: vec![],
63      dependencies: vec![],
64      shebang: None,
65      parameters: vec![],
66      content: "test:\n  echo test".to_string(),
67      range: lsp::Range::at(0, 0, 2, 0),
68    };
69
70    assert_eq!(recipe.groups(), HashSet::from([Group::Any]));
71  }
72
73  #[test]
74  fn recipe_groups_single_attribute() {
75    let recipe = Recipe {
76      name: TextNode {
77        value: "test".into(),
78        range: lsp::Range::at(1, 0, 1, 4),
79      },
80      attributes: vec![Attribute {
81        name: TextNode {
82          value: "linux".to_string(),
83          range: lsp::Range::at(0, 1, 0, 6),
84        },
85        arguments: vec![],
86        target: Some(AttributeTarget::Recipe),
87        range: lsp::Range::at(0, 0, 1, 0),
88      }],
89      dependencies: vec![],
90      shebang: None,
91      parameters: vec![],
92      content: "[linux]\ntest:\n  echo test".to_string(),
93      range: lsp::Range::at(0, 0, 3, 0),
94    };
95
96    assert_eq!(recipe.groups(), HashSet::from([Group::Linux]));
97  }
98
99  #[test]
100  fn recipe_groups_multiple_attributes() {
101    let recipe = Recipe {
102      name: TextNode {
103        value: "test".into(),
104        range: lsp::Range::at(2, 0, 2, 4),
105      },
106      attributes: vec![
107        Attribute {
108          name: TextNode {
109            value: "linux".to_string(),
110            range: lsp::Range::at(0, 1, 0, 6),
111          },
112          arguments: vec![],
113          target: Some(AttributeTarget::Recipe),
114          range: lsp::Range::at(0, 0, 1, 0),
115        },
116        Attribute {
117          name: TextNode {
118            value: "windows".to_string(),
119            range: lsp::Range::at(1, 1, 1, 8),
120          },
121          arguments: vec![],
122          target: Some(AttributeTarget::Recipe),
123          range: lsp::Range::at(1, 0, 2, 0),
124        },
125      ],
126      dependencies: vec![],
127      shebang: None,
128      parameters: vec![],
129      content: "[linux]\n[windows]\ntest:\n  echo test".to_string(),
130      range: lsp::Range::at(0, 0, 4, 0),
131    };
132
133    assert_eq!(
134      recipe.groups(),
135      HashSet::from([Group::Linux, Group::Windows])
136    );
137  }
138
139  #[test]
140  fn recipe_groups_all_attributes() {
141    let recipe = Recipe {
142      name: TextNode {
143        value: "test".into(),
144        range: lsp::Range::at(8, 0, 8, 4),
145      },
146      attributes: vec![
147        Attribute {
148          name: TextNode {
149            value: "linux".to_string(),
150            range: lsp::Range::at(0, 1, 0, 6),
151          },
152          arguments: vec![],
153          target: Some(AttributeTarget::Recipe),
154          range: lsp::Range::at(0, 0, 1, 0),
155        },
156        Attribute {
157          name: TextNode {
158            value: "windows".to_string(),
159            range: lsp::Range::at(1, 1, 1, 8),
160          },
161          arguments: vec![],
162          target: Some(AttributeTarget::Recipe),
163          range: lsp::Range::at(1, 0, 2, 0),
164        },
165        Attribute {
166          name: TextNode {
167            value: "macos".to_string(),
168            range: lsp::Range::at(2, 1, 2, 6),
169          },
170          arguments: vec![],
171          target: Some(AttributeTarget::Recipe),
172          range: lsp::Range::at(2, 0, 3, 0),
173        },
174        Attribute {
175          name: TextNode {
176            value: "unix".to_string(),
177            range: lsp::Range::at(3, 1, 3, 5),
178          },
179          arguments: vec![],
180          target: Some(AttributeTarget::Recipe),
181          range: lsp::Range::at(3, 0, 4, 0),
182        },
183        Attribute {
184          name: TextNode {
185            value: "dragonfly".to_string(),
186            range: lsp::Range::at(4, 1, 4, 10),
187          },
188          arguments: vec![],
189          target: Some(AttributeTarget::Recipe),
190          range: lsp::Range::at(4, 0, 5, 0),
191        },
192        Attribute {
193          name: TextNode {
194            value: "freebsd".to_string(),
195            range: lsp::Range::at(5, 1, 5, 8),
196          },
197          arguments: vec![],
198          target: Some(AttributeTarget::Recipe),
199          range: lsp::Range::at(5, 0, 6, 0),
200        },
201        Attribute {
202          name: TextNode {
203            value: "netbsd".to_string(),
204            range: lsp::Range::at(6, 1, 6, 7),
205          },
206          arguments: vec![],
207          target: Some(AttributeTarget::Recipe),
208          range: lsp::Range::at(6, 0, 7, 0),
209        },
210        Attribute {
211          name: TextNode {
212            value: "openbsd".to_string(),
213            range: lsp::Range::at(7, 1, 7, 8),
214          },
215          arguments: vec![],
216          target: Some(AttributeTarget::Recipe),
217          range: lsp::Range::at(7, 0, 8, 0),
218        },
219      ],
220      dependencies: vec![],
221      shebang: None,
222      parameters: vec![],
223      content:
224        "[linux]\n[windows]\n[macos]\n[unix]\n[dragonfly]\n[freebsd]\n[netbsd]\n[openbsd]\ntest:\n  echo test"
225          .to_string(),
226      range: lsp::Range::at(0, 0, 10, 0),
227    };
228
229    assert_eq!(
230      recipe.groups(),
231      HashSet::from([
232        Group::Android,
233        Group::Dragonfly,
234        Group::Freebsd,
235        Group::Linux,
236        Group::Macos,
237        Group::Netbsd,
238        Group::Openbsd,
239        Group::Windows,
240      ])
241    );
242  }
243
244  #[test]
245  fn recipe_groups_non_os_attributes() {
246    let recipe = Recipe {
247      name: TextNode {
248        value: "test".into(),
249        range: lsp::Range::at(1, 0, 1, 4),
250      },
251      attributes: vec![Attribute {
252        name: TextNode {
253          value: "private".to_string(),
254          range: lsp::Range::at(0, 1, 0, 8),
255        },
256        arguments: vec![],
257        target: Some(AttributeTarget::Recipe),
258        range: lsp::Range::at(0, 0, 1, 0),
259      }],
260      dependencies: vec![],
261      shebang: None,
262      parameters: vec![],
263      content: "[private]\ntest:\n  echo test".to_string(),
264      range: lsp::Range::at(0, 0, 3, 0),
265    };
266
267    assert_eq!(recipe.groups(), HashSet::from([Group::Any]));
268  }
269}