cratestack_parser/
directive_targets.rs1use crate::line_helpers::collect_lines_at;
9use crate::parse::{directive_keyword, parse_path_directive};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum DirectiveKind {
14 Part,
16 PartOf,
18 Import,
20}
21
22pub fn directive_targets(source: &str) -> Vec<(DirectiveKind, String)> {
26 collect_lines_at(source, 0)
27 .iter()
28 .filter_map(|line| {
29 let keyword = directive_keyword(line.trimmed)?;
30 let directive = parse_path_directive(line, keyword).ok()?;
31 let kind = match keyword {
32 "part of" => DirectiveKind::PartOf,
33 "part" => DirectiveKind::Part,
34 _ => DirectiveKind::Import,
35 };
36 Some((kind, directive.path))
37 })
38 .collect()
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn collects_targets_in_order_and_ignores_comments_and_malformed_lines() {
47 let source = "// import \"no.cstack\"\npart of \"main.cstack\"\n import \"a/b.cstack\"\n\
48 part \"p.cstack\"\nimport nothing\npartial \"x.cstack\"\nmodel M {\n}\n";
49 assert_eq!(
50 directive_targets(source),
51 vec![
52 (DirectiveKind::PartOf, "main.cstack".to_owned()),
53 (DirectiveKind::Import, "a/b.cstack".to_owned()),
54 (DirectiveKind::Part, "p.cstack".to_owned()),
55 ]
56 );
57 }
58}