Add associative map constraints and range refinement
This commit is contained in:
@@ -169,6 +169,11 @@ impl<'a> Formatter<'a> {
|
||||
self.write_expr(out, *item, indent, 0);
|
||||
out.push(']');
|
||||
}
|
||||
Expr::MapConstraint { value } => {
|
||||
out.push_str("{...");
|
||||
self.write_expr(out, *value, indent, 0);
|
||||
out.push('}');
|
||||
}
|
||||
Expr::Let { bindings, body } => self.write_let(out, node.span, bindings, *body, indent),
|
||||
Expr::Import(_) => {
|
||||
out.push_str("import ");
|
||||
@@ -219,6 +224,11 @@ impl<'a> Formatter<'a> {
|
||||
out.push_str(" default ");
|
||||
self.write_expr(out, *fallback, indent, precedence + 1);
|
||||
}
|
||||
Expr::As { narrower, wider } => {
|
||||
self.write_expr(out, *narrower, indent, precedence);
|
||||
out.push_str(" as ");
|
||||
self.write_expr(out, *wider, indent, precedence + 1);
|
||||
}
|
||||
Expr::CompareConstraint { op, value } => {
|
||||
out.push_str(compare_operator(*op));
|
||||
out.push(' ');
|
||||
@@ -461,6 +471,7 @@ impl<'a> Formatter<'a> {
|
||||
|
||||
fn precedence(&self, id: ExprId) -> u8 {
|
||||
match &self.ast.get(id).expr {
|
||||
Expr::As { .. } => 0,
|
||||
Expr::Default { .. } => 1,
|
||||
Expr::Binary { op, .. } => match op {
|
||||
BinaryOp::Patch => 3,
|
||||
@@ -508,7 +519,11 @@ impl<'a> Formatter<'a> {
|
||||
}
|
||||
Expr::Array(items) => items.iter().all(|item| self.is_inline_expr(*item)),
|
||||
Expr::ArrayConstraint { item } => self.is_inline_expr(*item),
|
||||
Expr::MapConstraint { value } => self.is_inline_expr(*value),
|
||||
Expr::Parenthesized { expr } => self.is_inline_expr(*expr),
|
||||
Expr::As { narrower, wider } => {
|
||||
self.is_inline_expr(*narrower) && self.is_inline_expr(*wider)
|
||||
}
|
||||
Expr::Object(_) | Expr::Let { .. } | Expr::Function { .. } | Expr::Match { .. } => {
|
||||
false
|
||||
}
|
||||
@@ -670,6 +685,18 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formats_map_constraints_and_range_ascription() {
|
||||
let source =
|
||||
"config={service={port=8080;};}as{service={port=Int;};};labels={a=1;b=2;}as{...Int};";
|
||||
let formatted = format_source(source).unwrap();
|
||||
assert_eq!(
|
||||
formatted,
|
||||
"config = {\n service = {\n port = 8080;\n };\n} as {\n service = {\n port = Int;\n };\n};\nlabels = {\n a = 1;\n b = 2;\n} as {...Int};\n"
|
||||
);
|
||||
assert_eq!(format_source(&formatted).unwrap(), formatted);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formats_let_functions_and_precedence_from_the_canonical_ast() {
|
||||
let source = "value=let x=1+2*3;in(a:Int)=>{result=(x+a)*2;};";
|
||||
@@ -743,6 +770,10 @@ mod tests {
|
||||
include_str!("../../../examples/import/schema.dcdl"),
|
||||
),
|
||||
("logical", include_str!("../../../examples/logical.dcdl")),
|
||||
(
|
||||
"map-ascription",
|
||||
include_str!("../../../examples/map-ascription.dcdl"),
|
||||
),
|
||||
(
|
||||
"regex/main",
|
||||
include_str!("../../../examples/regex/main.dcdl"),
|
||||
|
||||
Reference in New Issue
Block a user