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 steps: Vec<TaskStepAst>,
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, ¶meter.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 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 pub range: TextRange,
112}
113
114#[derive(Debug, Clone, PartialEq, Eq)]
115pub enum TaskStepAst {
116 Command(CommandAst),
117 CommandBlock(CommandBlockAst),
118}
119
120impl TaskStepAst {
121 pub fn source(&self) -> &str {
122 match self {
123 Self::Command(command) => command.text.as_str(),
124 Self::CommandBlock(block) => block.source.as_str(),
125 }
126 }
127
128 pub fn interpolations(&self) -> &[InterpolationAst] {
129 match self {
130 Self::Command(command) => &command.interpolations,
131 Self::CommandBlock(block) => &block.interpolations,
132 }
133 }
134}
135
136#[derive(Debug, Clone, PartialEq, Eq)]
137pub struct CommandBlockAst {
138 pub source: SmolStr,
139 pub interpolations: Vec<InterpolationAst>,
140 pub range: TextRange,
141 pub line_ranges: Vec<TextRange>,
142}
143
144#[derive(Debug, Clone, PartialEq, Eq)]
145pub struct InterpolationAst {
146 pub name: SmolStr,
147 pub range: TextRange,
148}