1use crate::{DeclId, Type};
2use serde::{Deserialize, Serialize};
3use std::fmt::Display;
4
5#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub enum SyntaxShape {
14 Any,
16
17 Binary,
19
20 Block,
22
23 Boolean,
25
26 CellPath,
28
29 Closure(Option<Vec<SyntaxShape>>),
31
32 CompleterWrapper(Box<SyntaxShape>, DeclId),
34
35 DateTime,
37
38 Directory,
40
41 Duration,
43
44 Error,
46
47 Expression,
49
50 ExternalArgument,
55
56 Filepath,
58
59 Filesize,
61
62 Float,
64
65 FullCellPath,
69
70 GlobPattern,
72
73 Int,
75
76 ImportPattern,
78
79 Keyword(Vec<u8>, Box<SyntaxShape>),
81
82 List(Box<SyntaxShape>),
84
85 MathExpression,
87
88 MatchBlock,
90
91 Nothing,
93
94 Number,
96
97 OneOf(Vec<SyntaxShape>),
99
100 Operator,
102
103 Range,
105
106 Record(Vec<(String, SyntaxShape)>),
108
109 RowCondition,
112
113 Signature,
115
116 String,
118
119 Table(Vec<(String, SyntaxShape)>),
121
122 VarWithOptType,
124}
125
126impl SyntaxShape {
127 pub fn to_type(&self) -> Type {
138 let mk_ty = |tys: &[(String, SyntaxShape)]| {
139 tys.iter()
140 .map(|(key, val)| (key.clone(), val.to_type()))
141 .collect()
142 };
143
144 match self {
145 SyntaxShape::Any => Type::Any,
146 SyntaxShape::Block => Type::Any,
147 SyntaxShape::Closure(_) => Type::Closure,
148 SyntaxShape::Binary => Type::Binary,
149 SyntaxShape::CellPath => Type::Any,
150 SyntaxShape::CompleterWrapper(inner, _) => inner.to_type(),
151 SyntaxShape::DateTime => Type::Date,
152 SyntaxShape::Duration => Type::Duration,
153 SyntaxShape::Expression => Type::Any,
154 SyntaxShape::ExternalArgument => Type::Any,
155 SyntaxShape::Filepath => Type::String,
156 SyntaxShape::Directory => Type::String,
157 SyntaxShape::Float => Type::Float,
158 SyntaxShape::Filesize => Type::Filesize,
159 SyntaxShape::FullCellPath => Type::Any,
160 SyntaxShape::GlobPattern => Type::Glob,
161 SyntaxShape::Error => Type::Error,
162 SyntaxShape::ImportPattern => Type::Any,
163 SyntaxShape::Int => Type::Int,
164 SyntaxShape::List(x) => {
165 let contents = x.to_type();
166 Type::List(Box::new(contents))
167 }
168 SyntaxShape::Keyword(_, expr) => expr.to_type(),
169 SyntaxShape::MatchBlock => Type::Any,
170 SyntaxShape::MathExpression => Type::Any,
171 SyntaxShape::Nothing => Type::Nothing,
172 SyntaxShape::Number => Type::Number,
173 SyntaxShape::OneOf(_) => Type::Any,
174 SyntaxShape::Operator => Type::Any,
175 SyntaxShape::Range => Type::Range,
176 SyntaxShape::Record(entries) => Type::Record(mk_ty(entries)),
177 SyntaxShape::RowCondition => Type::Bool,
178 SyntaxShape::Boolean => Type::Bool,
179 SyntaxShape::Signature => Type::Any,
180 SyntaxShape::String => Type::String,
181 SyntaxShape::Table(columns) => Type::Table(mk_ty(columns)),
182 SyntaxShape::VarWithOptType => Type::Any,
183 }
184 }
185}
186
187impl Display for SyntaxShape {
188 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
189 let mk_fmt = |tys: &[(String, SyntaxShape)]| -> String {
190 tys.iter()
191 .map(|(x, y)| format!("{x}: {y}"))
192 .collect::<Vec<String>>()
193 .join(", ")
194 };
195
196 match self {
197 SyntaxShape::Keyword(kw, shape) => {
198 write!(f, "\"{}\" {}", String::from_utf8_lossy(kw), shape)
199 }
200 SyntaxShape::Any => write!(f, "any"),
201 SyntaxShape::String => write!(f, "string"),
202 SyntaxShape::CellPath => write!(f, "cell-path"),
203 SyntaxShape::FullCellPath => write!(f, "cell-path"),
204 SyntaxShape::Number => write!(f, "number"),
205 SyntaxShape::Range => write!(f, "range"),
206 SyntaxShape::Int => write!(f, "int"),
207 SyntaxShape::Float => write!(f, "float"),
208 SyntaxShape::Filepath => write!(f, "path"),
209 SyntaxShape::Directory => write!(f, "directory"),
210 SyntaxShape::GlobPattern => write!(f, "glob"),
211 SyntaxShape::ImportPattern => write!(f, "import"),
212 SyntaxShape::Block => write!(f, "block"),
213 SyntaxShape::Closure(args) => {
214 if let Some(args) = args {
215 let arg_vec: Vec<_> = args.iter().map(|x| x.to_string()).collect();
216 let arg_string = arg_vec.join(", ");
217 write!(f, "closure({arg_string})")
218 } else {
219 write!(f, "closure()")
220 }
221 }
222 SyntaxShape::Binary => write!(f, "binary"),
223 SyntaxShape::List(x) => write!(f, "list<{x}>"),
224 SyntaxShape::Table(columns) => {
225 if columns.is_empty() {
226 write!(f, "table")
227 } else {
228 write!(f, "table<{}>", mk_fmt(columns))
229 }
230 }
231 SyntaxShape::Record(entries) => {
232 if entries.is_empty() {
233 write!(f, "record")
234 } else {
235 write!(f, "record<{}>", mk_fmt(entries))
236 }
237 }
238 SyntaxShape::Filesize => write!(f, "filesize"),
239 SyntaxShape::Duration => write!(f, "duration"),
240 SyntaxShape::DateTime => write!(f, "datetime"),
241 SyntaxShape::Operator => write!(f, "operator"),
242 SyntaxShape::RowCondition => write!(f, "condition"),
243 SyntaxShape::MathExpression => write!(f, "variable"),
244 SyntaxShape::VarWithOptType => write!(f, "vardecl"),
245 SyntaxShape::Signature => write!(f, "signature"),
246 SyntaxShape::MatchBlock => write!(f, "match-block"),
247 SyntaxShape::Expression => write!(f, "expression"),
248 SyntaxShape::ExternalArgument => write!(f, "external-argument"),
249 SyntaxShape::Boolean => write!(f, "bool"),
250 SyntaxShape::Error => write!(f, "error"),
251 SyntaxShape::CompleterWrapper(x, _) => write!(f, "completable<{x}>"),
252 SyntaxShape::OneOf(list) => {
253 write!(f, "oneof<")?;
254 if let Some((last, rest)) = list.split_last() {
255 for ty in rest {
256 write!(f, "{ty}, ")?;
257 }
258 write!(f, "{last}")?;
259 }
260 write!(f, ">")
261 }
262 SyntaxShape::Nothing => write!(f, "nothing"),
263 }
264 }
265}