Skip to main content

only_semantic/
ast.rs

1use smol_str::SmolStr;
2use text_size::TextRange;
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct DocumentAst {
6    pub directives: Vec<DirectiveAst>,
7    pub namespaces: Vec<NamespaceAst>,
8    pub tasks: Vec<TaskAst>,
9}
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub enum DirectiveAst {
13    Shell { shell: SmolStr, range: TextRange },
14}
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct NamespaceAst {
18    pub name: SmolStr,
19    pub doc: Option<SmolStr>,
20    pub range: TextRange,
21}
22
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub struct TaskAst {
25    pub name: SmolStr,
26    pub namespace: Option<SmolStr>,
27    pub doc: Option<SmolStr>,
28    pub params: Vec<ParamAst>,
29    pub guard: Option<GuardAst>,
30    pub dependencies: Vec<DependencyAst>,
31    pub shell: Option<SmolStr>,
32    pub shell_fallback: bool,
33    pub commands: Vec<CommandAst>,
34    pub range: TextRange,
35}
36
37impl TaskAst {
38    pub fn qualified_name(&self) -> SmolStr {
39        match &self.namespace {
40            Some(namespace) => SmolStr::from(format!("{namespace}.{}", self.name)),
41            None => self.name.clone(),
42        }
43    }
44
45    pub fn signature(&self) -> SmolStr {
46        let mut signature = self.name.to_string();
47        signature.push('(');
48        signature.push_str(
49            &self
50                .params
51                .iter()
52                .map(
53                    |parameter| match (parameter.is_slice, &parameter.default_value) {
54                        (true, Some(default)) => format!("{}..=\"{default}\"", parameter.name),
55                        (true, None) => format!("{}..", parameter.name),
56                        (false, Some(default)) => format!("{}=\"{default}\"", parameter.name),
57                        (false, None) => parameter.name.to_string(),
58                    },
59                )
60                .collect::<Vec<_>>()
61                .join(", "),
62        );
63        signature.push(')');
64        SmolStr::from(signature)
65    }
66
67    /// Returns whether the task is a helper task hidden from normal CLI listings.
68    ///
69    /// Args:
70    /// None.
71    ///
72    /// Returns:
73    /// `true` when the task name starts with `_`.
74    pub fn is_helper(&self) -> bool {
75        self.name.starts_with('_')
76    }
77}
78
79#[derive(Debug, Clone, PartialEq, Eq)]
80pub struct ParamAst {
81    pub name: SmolStr,
82    pub default_value: Option<SmolStr>,
83    pub is_slice: bool,
84}
85
86#[derive(Debug, Clone, PartialEq, Eq)]
87pub struct GuardAst {
88    pub kind: SmolStr,
89    pub argument: SmolStr,
90}
91
92#[derive(Debug, Clone, PartialEq, Eq)]
93pub struct DependencyAst {
94    pub name: SmolStr,
95    pub range: TextRange,
96    pub stage: usize,
97}
98
99#[derive(Debug, Clone, PartialEq, Eq)]
100pub struct CommandAst {
101    pub text: SmolStr,
102    pub interpolations: Vec<InterpolationAst>,
103}
104
105#[derive(Debug, Clone, PartialEq, Eq)]
106pub struct InterpolationAst {
107    pub name: SmolStr,
108    pub range: TextRange,
109}