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