makefile_lossless/ast/
include.rs

1use super::makefile::MakefileItem;
2use crate::lossless::Include;
3use crate::SyntaxKind::EXPR;
4use rowan::ast::AstNode;
5
6impl Include {
7    /// Get the raw path of the include directive
8    pub fn path(&self) -> Option<String> {
9        self.syntax()
10            .children()
11            .find(|it| it.kind() == EXPR)
12            .map(|it| it.text().to_string().trim().to_string())
13    }
14
15    /// Check if this is an optional include (-include or sinclude)
16    pub fn is_optional(&self) -> bool {
17        let text = self.syntax().text();
18        text.to_string().starts_with("-include") || text.to_string().starts_with("sinclude")
19    }
20
21    /// Get the parent item of this include directive, if any
22    ///
23    /// Returns `Some(MakefileItem)` if this include has a parent that is a MakefileItem
24    /// (e.g., a Conditional), or `None` if the parent is the root Makefile node.
25    ///
26    /// # Example
27    /// ```
28    /// use makefile_lossless::Makefile;
29    ///
30    /// let makefile: Makefile = r#"ifdef DEBUG
31    /// include debug.mk
32    /// endif
33    /// "#.parse().unwrap();
34    /// let cond = makefile.conditionals().next().unwrap();
35    /// let inc = cond.if_items().next().unwrap();
36    /// // Include's parent is the conditional
37    /// assert!(matches!(inc, makefile_lossless::MakefileItem::Include(_)));
38    /// ```
39    pub fn parent(&self) -> Option<MakefileItem> {
40        self.syntax().parent().and_then(MakefileItem::cast)
41    }
42}
43
44#[cfg(test)]
45mod tests {
46
47    use crate::lossless::Makefile;
48
49    #[test]
50    fn test_include_parent() {
51        let makefile: Makefile = "include common.mk\n".parse().unwrap();
52
53        let inc = makefile.includes().next().unwrap();
54        let parent = inc.parent();
55        // Parent is ROOT node which doesn't cast to MakefileItem
56        assert!(parent.is_none());
57    }
58}