git.delta.rocks / jrsonnet / refs/commits / 8bc6498a805d

difftreelog

test import formatting test-cases from rustanka

umopspmtYaroslav Bolyukin2026-02-12parent: #fc45c6c.patch.diff
in: master

45 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -156,6 +156,16 @@
 ]
 
 [[package]]
+name = "bstr"
+version = "1.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
+dependencies = [
+ "memchr",
+ "serde",
+]
+
+[[package]]
 name = "bumpalo"
 version = "3.19.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -453,6 +463,19 @@
 ]
 
 [[package]]
+name = "globset"
+version = "0.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3"
+dependencies = [
+ "aho-corasick",
+ "bstr",
+ "log",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
 name = "hashbrown"
 version = "0.14.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -548,9 +571,11 @@
 checksum = "e82db8c87c7f1ccecb34ce0c24399b8a73081427f3c7c50a5d597925356115e4"
 dependencies = [
  "console",
+ "globset",
  "once_cell",
  "similar",
  "tempfile",
+ "walkdir",
 ]
 
 [[package]]
@@ -797,6 +822,12 @@
 checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
 
 [[package]]
+name = "log"
+version = "0.4.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
+
+[[package]]
 name = "logos"
 version = "0.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1157,6 +1188,15 @@
 checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
 
 [[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
 name = "saphyr-parser-bw"
 version = "0.0.607"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1491,6 +1531,16 @@
 ]
 
 [[package]]
+name = "walkdir"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+dependencies = [
+ "same-file",
+ "winapi-util",
+]
+
+[[package]]
 name = "wasip2"
 version = "1.0.2+wasi-0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1545,6 +1595,15 @@
 ]
 
 [[package]]
+name = "winapi-util"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
+dependencies = [
+ "windows-sys 0.59.0",
+]
+
+[[package]]
 name = "windows-link"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
modifiedCargo.tomldiffbeforeafterboth
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -38,7 +38,7 @@
 # Parsing, manifestification is implemented manually everywhere
 serde = "1.0.228"
 serde_json = "1.0.149"
-serde-saphyr = {version = "0.0.17", default-features = false}
+serde-saphyr = { version = "0.0.17", default-features = false }
 
 # Error handling
 anyhow = "1.0.101"
@@ -63,7 +63,7 @@
 
 mimallocator = "0.1.3"
 indoc = "2.0"
-insta = "1.46"
+insta = { version = "1.46", features = ["glob"] }
 tempfile = "3.24"
 pathdiff = "0.2.3"
 hashbrown = "0.16.1"
modifiedcrates/jrsonnet-formatter/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-formatter/src/lib.rs
+++ b/crates/jrsonnet-formatter/src/lib.rs
@@ -13,7 +13,7 @@
 		Arg, ArgsDesc, Assertion, BinaryOperator, Bind, CompSpec, Destruct, DestructArrayPart,
 		DestructRest, Expr, ExprBase, FieldName, ForSpec, IfSpec, ImportKind, Literal, Member,
 		Name, Number, ObjBody, ObjLocal, ParamsDesc, SliceDesc, SourceFile, Stmt, Suffix, Text,
-		UnaryOperator, Visibility,
+		TextKind, UnaryOperator, Visibility,
 	},
 	AstNode, AstToken as _, SyntaxToken,
 };
@@ -25,7 +25,6 @@
 
 mod children;
 mod comments;
-#[cfg(test)]
 mod tests;
 
 fn with_indent_eoi(cond: ConditionResolver, o: PrintItems, e: EndingComments) -> PrintItems {
@@ -200,6 +199,18 @@
 
 impl Printable for Text {
 	fn print(&self, out: &mut PrintItems) {
+		if matches!(self.kind(), TextKind::StringBlock) {
+			let text = self.text();
+
+			for (i, ele) in text.split("\n").enumerate() {
+				if i != 0 {
+					p!(out, nl);
+				}
+				// TODO: Trim and recreate whitespace
+				p!(out, string(ele.to_string()));
+			}
+			return;
+		}
 		p!(out, string(format!("{}", self)));
 	}
 }
deletedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__args.snapdiffbeforeafterboth
--- a/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__args.snap
+++ /dev/null
@@ -1,36 +0,0 @@
----
-source: crates/jrsonnet-formatter/src/tests.rs
-expression: "reformat(indoc!(\"\n\t\t\t{\n\t\t\t\tshort: aaa(1,2,3,4,5),\n\t\t\t\tlong: bbb(123123123123123123123,12312312321123123123,123123123123312123123,123123123123123123312,123123123123312321123),\n\t\t\t\tshort_in_long: bbb(aaa(1,2,3,4,5), 123123123123123123123,12312312321123123123,123123123123312123123,123123123123123123312,123123123123312321123),\n\t\t\t\tlong_in_short: aaa(1,2,3,4,5,bbb(123123123123123123123,12312312321123123123,123123123123312123123,123123123123123123312,123123123123312321123)),\n\t\t\t}\n\t\t\"))"
----
-{
-	short: aaa(1, 2, 3, 4, 5),
-	long: bbb(
-		123123123123123123123,
-		12312312321123123123,
-		123123123123312123123,
-		123123123123123123312,
-		123123123123312321123,
-	),
-	short_in_long: bbb(
-		aaa(1, 2, 3, 4, 5),
-		123123123123123123123,
-		12312312321123123123,
-		123123123123312123123,
-		123123123123123123312,
-		123123123123312321123,
-	),
-	long_in_short: aaa(
-		1,
-		2,
-		3,
-		4,
-		5,
-		bbb(
-			123123123123123123123,
-			12312312321123123123,
-			123123123123312123123,
-			123123123123123123312,
-			123123123123312321123,
-		),
-	),
-}
deletedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__asserts.snapdiffbeforeafterboth
--- a/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__asserts.snap
+++ /dev/null
@@ -1,9 +0,0 @@
----
-source: crates/jrsonnet-formatter/src/tests.rs
-expression: "reformat(indoc!(\"\n\t\t\t{\n\t\t\t\tassert 1 > 0 : 'one should be greater than zero',\n\t\t\t\tassert true,\n\t\t\t\tvalue: 42,\n\t\t\t}\n\t\t\"))"
----
-{
-	assert 1 > 0: 'one should be greater than zero',
-	assert true,
-	value: 42,
-}
deletedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__complex_comments.snapdiffbeforeafterboth
--- a/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__complex_comments.snap
+++ /dev/null
@@ -1,62 +0,0 @@
----
-source: crates/jrsonnet-formatter/src/tests.rs
-expression: "reformat(indoc!(\"{\n\t\t  comments: {\n\t\t\t_: '',\n\t\t\t//     Plain comment\n\t\t\ta: '',\n\n\t\t\t#    Plain comment with empty line before\n\t\t\tb: '',\n\t\t\t/*Single-line multiline comment\n\n\t\t\t*/\n\t\t\tc: '',\n\n\t\t\t/**Single-line multiline doc comment\n\n\t\t\t*/\n\t\t\tc: '',\n\n\t\t\t/**Multiline doc\n\t\t\tComment\n\t\t\t*/\n\t\t\tc: '',\n\n\t\t\t/*\n\n\tMulti-line\n\n\tcomment\n\t\t\t*/\n\t\t\td: '',\n\n\t\t\te: '', // Inline comment\n\n\t\t\tk: '',\n\n\t\t\t// Text after everything\n\t\t  },\n\t\t  comments2: {\n\t\t\tk: '',\n\t\t\t// Text after everything, but no newline above\n\t\t  },\n          spacing: {\n            a: '',\n\n            b: '',\n          },\n          noSpacing: {\n            a: '',\n            b: '',\n          },\n\n\t\t\t smallObjectWithEnding: {/*Ending comment*/},\n\t\t\t smallObjectWithFieldAndEnding: {a: 11/*Ending comment*/},\n\t\t\t smallObjectWithFieldAndEnding2: {/*Start*/a: 11/*Ending comment*/},\n        }\"))"
----
-{
-	comments: {
-		_: '',
-		// Plain comment
-		a: '',
-
-		# Plain comment with empty line before
-		b: '',
-		/* Single-line multiline comment */
-		c: '',
-
-		/**
-		 * Single-line multiline doc comment
-		 */
-		c: '',
-
-		/**
-		 * Multiline doc
-		 * Comment
-		 */
-		c: '',
-
-		/*
-		Multi-line
-
-		comment
-		*/
-		d: '',
-
-		e: '', // Inline comment
-
-		k: '',
-
-		// Text after everything
-	},
-	comments2: {
-		k: '',
-		// Text after everything, but no newline above
-	},
-	spacing: {
-		a: '',
-
-		b: '',
-	},
-	noSpacing: {
-		a: '',
-		b: '',
-	},
-
-	smallObjectWithEnding: {
-		/* Ending comment */
-	},
-	smallObjectWithFieldAndEnding: { a: 11 /* Ending comment */ },
-	smallObjectWithFieldAndEnding2: {
-		/* Start */
-		a: 11, /* Ending comment */
-	},
-}
deletedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__complex_nested.snapdiffbeforeafterboth
--- a/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__complex_nested.snap
+++ /dev/null
@@ -1,41 +0,0 @@
----
-source: crates/jrsonnet-formatter/src/tests.rs
-expression: "reformat(indoc!(\"\n\t\t\t{\n\t\t\t\tkubernetes: {\n\t\t\t\t deployment: {\n\t\t\t\t\tapiVersion: 'apps/v1',\n\t\t\t\t\tkind: 'Deployment',\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t  name: 'myapp',\n\t\t\t\t\t  labels: { app: 'myapp', version: 'v1' },\n\t\t\t\t\t},\n\t\t\t\t\tspec: {\n\t\t\t\t\t  replicas: 3,\n\t\t\t\t\t  selector: { matchLabels: { app: 'myapp' } },\n\t\t\t\t\t  template: {\n\t\t\t\t\t\t metadata: { labels: { app: 'myapp' } },\n\t\t\t\t\t\t spec: {\n\t\t\t\t\t\t\tcontainers: [\n\t\t\t\t\t\t\t  {\n\t\t\t\t\t\t\t\t name: 'myapp',\n\t\t\t\t\t\t\t\t image: 'myapp:latest',\n\t\t\t\t\t\t\t\t ports: [{ containerPort: 8080 }],\n\t\t\t\t\t\t\t\t env: [\n\t\t\t\t\t\t\t\t\t{ name: 'FOO', value: 'bar' },\n\t\t\t\t\t\t\t\t\t{ name: 'BAZ', valueFrom: { secretKeyRef: { name: 'mysecret', key: 'password' } } },\n\t\t\t\t\t\t\t\t ],\n\t\t\t\t\t\t\t  },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t },\n\t\t\t\t\t  },\n\t\t\t\t\t},\n\t\t\t\t },\n\t\t\t  },\n\t\t\t}\n\t\t\"))"
----
-{
-	kubernetes: {
-		deployment: {
-			apiVersion: 'apps/v1',
-			kind: 'Deployment',
-			metadata: {
-				name: 'myapp',
-				labels: { app: 'myapp', version: 'v1' },
-			},
-			spec: {
-				replicas: 3,
-				selector: { matchLabels: { app: 'myapp' } },
-				template: {
-					metadata: { labels: { app: 'myapp' } },
-					spec: {
-						containers: [
-							{
-								name: 'myapp',
-								image: 'myapp:latest',
-								ports: [
-									{ containerPort: 8080 },
-								],
-								env: [
-									{ name: 'FOO', value: 'bar' },
-									{
-										name: 'BAZ',
-										valueFrom: { secretKeyRef: { name: 'mysecret', key: 'password' } },
-									},
-								],
-							},
-						],
-					},
-				},
-			},
-		},
-	},
-}
deletedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__self_super.snapdiffbeforeafterboth
--- a/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__self_super.snap
+++ /dev/null
@@ -1,13 +0,0 @@
----
-source: crates/jrsonnet-formatter/src/tests.rs
-expression: "reformat(indoc!(\"\n\t\t\tlocal base = {\n\t\t\t  foo: 'bar',\n\t\t\t  method():: self.foo,\n\t\t\t};\n\n\t\t\tbase {\n\t\t\t  foo: super.foo + '-extended',\n\t\t\t  result: self.method(),\n\t\t\t}\n\t\t\"))"
----
-local base = {
-	foo: 'bar',
-	method(
-	):: self.foo,
-};
-base {
-	foo: super.foo + '-extended',
-	result: self.method(),
-}
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@args.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@args.jsonnet.snap
@@ -0,0 +1,37 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/args.jsonnet
+---
+{
+   short: aaa(1, 2, 3, 4, 5),
+   long: bbb(
+      123123123123123123123,
+      12312312321123123123,
+      123123123123312123123,
+      123123123123123123312,
+      123123123123312321123,
+   ),
+   short_in_long: bbb(
+      aaa(1, 2, 3, 4, 5),
+      123123123123123123123,
+      12312312321123123123,
+      123123123123312123123,
+      123123123123123123312,
+      123123123123312321123,
+   ),
+   long_in_short: aaa(
+      1,
+      2,
+      3,
+      4,
+      5,
+      bbb(
+         123123123123123123123,
+         12312312321123123123,
+         123123123123312123123,
+         123123123123123123312,
+         123123123123312321123,
+      ),
+   ),
+}
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@asserts.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@asserts.jsonnet.snap
@@ -0,0 +1,10 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/asserts.jsonnet
+---
+{
+   assert 1 > 0: 'one should be greater than zero',
+   assert true,
+   value: 42,
+}
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@basic_array.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@basic_array.jsonnet.snap
@@ -0,0 +1,12 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/basic_array.jsonnet
+---
+[
+   1,
+   2,
+   3,
+   4,
+   5,
+]
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@basic_object.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@basic_object.jsonnet.snap
@@ -0,0 +1,6 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/basic_object.jsonnet
+---
+{ foo: 'bar', baz: 'qux', nested: { a: 1, b: 2 } }
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@comments.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@comments.jsonnet.snap
@@ -0,0 +1,16 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/comments.jsonnet
+---
+// File header comment
+{
+   // Comment above field
+   foo: 'bar',
+   /* Block comment */
+   baz: 'qux',
+   nested: {
+      // Hash comment
+      value: 42,
+   },
+}
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@complex_comments.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@complex_comments.jsonnet.snap
@@ -0,0 +1,63 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/complex_comments.jsonnet
+---
+{
+   comments: {
+      _: '',
+      // Plain comment
+      a: '',
+
+      # Plain comment with empty line before
+      b: '',
+      /* Single-line multiline comment */
+      c: '',
+
+      /**
+       * Single-line multiline doc comment
+       */
+      c: '',
+
+      /**
+       * Multiline doc
+       * Comment
+       */
+      c: '',
+
+      /*
+      Multi-line
+
+      comment
+      */
+      d: '',
+
+      e: '', // Inline comment
+
+      k: '',
+
+      // Text after everything
+   },
+   comments2: {
+      k: '',
+      // Text after everything, but no newline above
+   },
+   spacing: {
+      a: '',
+
+      b: '',
+   },
+   noSpacing: {
+      a: '',
+      b: '',
+   },
+
+   smallObjectWithEnding: {
+      /* Ending comment */
+   },
+   smallObjectWithFieldAndEnding: { a: 11 /* Ending comment */ },
+   smallObjectWithFieldAndEnding2: {
+      /* Start */
+      a: 11, /* Ending comment */
+   },
+}
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@complex_nested.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@complex_nested.jsonnet.snap
@@ -0,0 +1,42 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/complex_nested.jsonnet
+---
+{
+   kubernetes: {
+      deployment: {
+         apiVersion: 'apps/v1',
+         kind: 'Deployment',
+         metadata: {
+            name: 'myapp',
+            labels: { app: 'myapp', version: 'v1' },
+         },
+         spec: {
+            replicas: 3,
+            selector: { matchLabels: { app: 'myapp' } },
+            template: {
+               metadata: { labels: { app: 'myapp' } },
+               spec: {
+                  containers: [
+                     {
+                        name: 'myapp',
+                        image: 'myapp:latest',
+                        ports: [
+                           { containerPort: 8080 },
+                        ],
+                        env: [
+                           { name: 'FOO', value: 'bar' },
+                           {
+                              name: 'BAZ',
+                              valueFrom: { secretKeyRef: { name: 'mysecret', key: 'password' } },
+                           },
+                        ],
+                     },
+                  ],
+               },
+            },
+         },
+      },
+   },
+}
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@comprehensions.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@comprehensions.jsonnet.snap
@@ -0,0 +1,29 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/comprehensions.jsonnet
+---
+{
+   arr: [x for x in [
+      1,
+      2,
+      3,
+   ]],
+   filtered: [x for x in [
+      1,
+      2,
+      3,
+      4,
+      5,
+   ] if x > 2],
+   obj: {
+      [k]: v,
+      for k in [
+         'a',
+         'b',
+      ]for v in [
+         1,
+         2,
+      ]
+   },
+}
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@conditionals.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@conditionals.jsonnet.snap
@@ -0,0 +1,9 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/conditionals.jsonnet
+---
+{
+   simple: if true then 'yes' else 'no',
+   nested: if 1 > 0 then if 2 > 1 then 'a' else 'b' else 'c',
+}
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@functions.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@functions.jsonnet.snap
@@ -0,0 +1,20 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/functions.jsonnet
+---
+{
+   simple(
+      x,
+   ):: x * 2,
+   with_default(
+      x,
+      y = 10,
+   ):: x + y,
+   multiline(
+      a,
+      b,
+      c,
+   ):: a + b + c,
+   called: self.simple(5),
+}
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@imports.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@imports.jsonnet.snap
@@ -0,0 +1,11 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/imports.jsonnet
+---
+local a = import 'a.libsonnet';
+local m = import 'm.libsonnet';
+local z = import 'z.libsonnet';
+{
+   result: a + m + z,
+}
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@local_vars.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@local_vars.jsonnet.snap
@@ -0,0 +1,12 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/local_vars.jsonnet
+---
+local x = 10;
+local y = 20;
+local sum = x + y;
+{
+   local inner = 5,
+   result: sum + inner,
+}
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@operators.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@operators.jsonnet.snap
@@ -0,0 +1,18 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/operators.jsonnet
+---
+{
+   arithmetic: 1 + 2 * 3 - 4 / 2,
+   comparison: 1 < 2 && 3 > 2 || false,
+   string_concat: 'hello' + ' ' + 'world',
+   object_concat: { a: 1 } + { b: 2 },
+   array_concat: [
+      1,
+      2,
+   ] + [
+      3,
+      4,
+   ],
+}
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@self_super.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@self_super.jsonnet.snap
@@ -0,0 +1,14 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/self_super.jsonnet
+---
+local base = {
+   foo: 'bar',
+   method(
+   ):: self.foo,
+};
+base {
+   foo: super.foo + '-extended',
+   result: self.method(),
+}
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@std_functions.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@std_functions.jsonnet.snap
@@ -0,0 +1,22 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/std_functions.jsonnet
+---
+{
+   length: std.length(
+      [
+         1,
+         2,
+         3,
+      ],
+   ),
+   type: std.type('hello'),
+   format: std.format(
+      'Hello, %s!',
+      [
+         'world',
+      ],
+   ),
+   manifest: std.manifestJsonEx({ foo: 'bar' }, '  '),
+}
addedcrates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@string_styles.jsonnet.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/snapshots/jrsonnet_formatter__tests__snapshots@string_styles.jsonnet.snap
@@ -0,0 +1,14 @@
+---
+source: crates/jrsonnet-formatter/src/tests.rs
+expression: reformat(&input)
+input_file: crates/jrsonnet-formatter/src/tests/string_styles.jsonnet
+---
+{
+   double_quote: 'hello world',
+   single_quote: 'hello world',
+   escaped: 'line1\nline2',
+   multiline: |||
+       This is a
+       multiline string
+     |||,
+}
modifiedcrates/jrsonnet-formatter/src/tests.rsdiffbeforeafterboth
--- a/crates/jrsonnet-formatter/src/tests.rs
+++ b/crates/jrsonnet-formatter/src/tests.rs
@@ -1,5 +1,10 @@
+#![cfg(test)]
+
+use std::fs;
+
 use dprint_core::formatting::{PrintItems, PrintOptions};
 use indoc::indoc;
+use insta::{assert_snapshot, glob};
 
 use crate::Printable;
 
@@ -13,155 +18,18 @@
 			out
 		},
 		PrintOptions {
-			indent_width: 2,
+			indent_width: 3,
 			max_width: 100,
-			use_tabs: true,
+			use_tabs: false,
 			new_line_text: "\n",
 		},
 	)
 }
 
 #[test]
-fn complex_comments() {
-	insta::assert_snapshot!(reformat(indoc!(
-		"{
-		  comments: {
-			_: '',
-			//     Plain comment
-			a: '',
-
-			#    Plain comment with empty line before
-			b: '',
-			/*Single-line multiline comment
-
-			*/
-			c: '',
-
-			/**Single-line multiline doc comment
-
-			*/
-			c: '',
-
-			/**Multiline doc
-			Comment
-			*/
-			c: '',
-
-			/*
-
-	Multi-line
-
-	comment
-			*/
-			d: '',
-
-			e: '', // Inline comment
-
-			k: '',
-
-			// Text after everything
-		  },
-		  comments2: {
-			k: '',
-			// Text after everything, but no newline above
-		  },
-          spacing: {
-            a: '',
-
-            b: '',
-          },
-          noSpacing: {
-            a: '',
-            b: '',
-          },
-
-			 smallObjectWithEnding: {/*Ending comment*/},
-			 smallObjectWithFieldAndEnding: {a: 11/*Ending comment*/},
-			 smallObjectWithFieldAndEnding2: {/*Start*/a: 11/*Ending comment*/},
-        }"
-	)));
-}
-
-#[test]
-fn args() {
-	insta::assert_snapshot!(reformat(indoc!(
-		"
-			{
-				short: aaa(1,2,3,4,5),
-				long: bbb(123123123123123123123,12312312321123123123,123123123123312123123,123123123123123123312,123123123123312321123),
-				short_in_long: bbb(aaa(1,2,3,4,5), 123123123123123123123,12312312321123123123,123123123123312123123,123123123123123123312,123123123123312321123),
-				long_in_short: aaa(1,2,3,4,5,bbb(123123123123123123123,12312312321123123123,123123123123312123123,123123123123123123312,123123123123312321123)),
-			}
-		"
-	)));
-}
-
-#[test]
-fn asserts() {
-	insta::assert_snapshot!(reformat(indoc!(
-		"
-			{
-				assert 1 > 0 : 'one should be greater than zero',
-				assert true,
-				value: 42,
-			}
-		"
-	)));
-}
-
-#[test]
-fn complex_nested() {
-	insta::assert_snapshot!(reformat(indoc!(
-		"
-			{
-				kubernetes: {
-				 deployment: {
-					apiVersion: 'apps/v1',
-					kind: 'Deployment',
-					metadata: {
-					  name: 'myapp',
-					  labels: { app: 'myapp', version: 'v1' },
-					},
-					spec: {
-					  replicas: 3,
-					  selector: { matchLabels: { app: 'myapp' } },
-					  template: {
-						 metadata: { labels: { app: 'myapp' } },
-						 spec: {
-							containers: [
-							  {
-								 name: 'myapp',
-								 image: 'myapp:latest',
-								 ports: [{ containerPort: 8080 }],
-								 env: [
-									{ name: 'FOO', value: 'bar' },
-									{ name: 'BAZ', valueFrom: { secretKeyRef: { name: 'mysecret', key: 'password' } } },
-								 ],
-							  },
-							],
-						 },
-					  },
-					},
-				 },
-			  },
-			}
-		"
-	)));
-}
-
-#[test]
-fn self_super() {
-	insta::assert_snapshot!(reformat(indoc!(
-		"
-			local base = {
-			  foo: 'bar',
-			  method():: self.foo,
-			};
-
-			base {
-			  foo: super.foo + '-extended',
-			  result: self.method(),
-			}
-		"
-	)));
+fn snapshots() {
+	glob!("tests/*.jsonnet", |path| {
+		let input = fs::read_to_string(path).expect("read test file");
+		assert_snapshot!(reformat(&input));
+	});
 }
addedcrates/jrsonnet-formatter/src/tests/args.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/args.jsonnet
@@ -0,0 +1,7 @@
+
+			{
+				short: aaa(1,2,3,4,5),
+				long: bbb(123123123123123123123,12312312321123123123,123123123123312123123,123123123123123123312,123123123123312321123),
+				short_in_long: bbb(aaa(1,2,3,4,5), 123123123123123123123,12312312321123123123,123123123123312123123,123123123123123123312,123123123123312321123),
+				long_in_short: aaa(1,2,3,4,5,bbb(123123123123123123123,12312312321123123123,123123123123312123123,123123123123123123312,123123123123312321123)),
+			}
addedcrates/jrsonnet-formatter/src/tests/asserts.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/asserts.jsonnet
@@ -0,0 +1,6 @@
+
+			{
+				assert 1 > 0 : 'one should be greater than zero',
+				assert true,
+				value: 42,
+			}
addedcrates/jrsonnet-formatter/src/tests/basic_array.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/basic_array.jsonnet
@@ -0,0 +1 @@
+[1, 2, 3, 4, 5]
addedcrates/jrsonnet-formatter/src/tests/basic_object.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/basic_object.jsonnet
@@ -0,0 +1 @@
+{ foo: 'bar', baz: 'qux', nested: { a: 1, b: 2 } }
addedcrates/jrsonnet-formatter/src/tests/comments.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/comments.jsonnet
@@ -0,0 +1,11 @@
+// File header comment
+{
+  // Comment above field
+  foo: 'bar',
+  /* Block comment */
+  baz: 'qux',
+  nested: {
+    // Hash comment
+    value: 42,
+  },
+}
addedcrates/jrsonnet-formatter/src/tests/complex_comments.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/complex_comments.jsonnet
@@ -0,0 +1,55 @@
+{
+		  comments: {
+			_: '',
+			//     Plain comment
+			a: '',
+
+			#    Plain comment with empty line before
+			b: '',
+			/*Single-line multiline comment
+
+			*/
+			c: '',
+
+			/**Single-line multiline doc comment
+
+			*/
+			c: '',
+
+			/**Multiline doc
+			Comment
+			*/
+			c: '',
+
+			/*
+
+	Multi-line
+
+	comment
+			*/
+			d: '',
+
+			e: '', // Inline comment
+
+			k: '',
+
+			// Text after everything
+		  },
+		  comments2: {
+			k: '',
+			// Text after everything, but no newline above
+		  },
+          spacing: {
+            a: '',
+
+            b: '',
+          },
+          noSpacing: {
+            a: '',
+            b: '',
+          },
+
+			 smallObjectWithEnding: {/*Ending comment*/},
+			 smallObjectWithFieldAndEnding: {a: 11/*Ending comment*/},
+			 smallObjectWithFieldAndEnding2: {/*Start*/a: 11/*Ending comment*/},
+        }
addedcrates/jrsonnet-formatter/src/tests/complex_nested.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/complex_nested.jsonnet
@@ -0,0 +1,33 @@
+
+			{
+				kubernetes: {
+				 deployment: {
+					apiVersion: 'apps/v1',
+					kind: 'Deployment',
+					metadata: {
+					  name: 'myapp',
+					  labels: { app: 'myapp', version: 'v1' },
+					},
+					spec: {
+					  replicas: 3,
+					  selector: { matchLabels: { app: 'myapp' } },
+					  template: {
+						 metadata: { labels: { app: 'myapp' } },
+						 spec: {
+							containers: [
+							  {
+								 name: 'myapp',
+								 image: 'myapp:latest',
+								 ports: [{ containerPort: 8080 }],
+								 env: [
+									{ name: 'FOO', value: 'bar' },
+									{ name: 'BAZ', valueFrom: { secretKeyRef: { name: 'mysecret', key: 'password' } } },
+								 ],
+							  },
+							],
+						 },
+					  },
+					},
+				 },
+			  },
+			}
addedcrates/jrsonnet-formatter/src/tests/comprehensions.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/comprehensions.jsonnet
@@ -0,0 +1,5 @@
+{
+  arr: [x for x in [1, 2, 3]],
+  filtered: [x for x in [1, 2, 3, 4, 5] if x > 2],
+  obj: { [k]: v for k in ['a', 'b'] for v in [1, 2] },
+}
addedcrates/jrsonnet-formatter/src/tests/conditionals.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/conditionals.jsonnet
@@ -0,0 +1,7 @@
+{
+  simple: if true then 'yes' else 'no',
+  nested: if 1 > 0 then
+    if 2 > 1 then 'a' else 'b'
+  else
+    'c',
+}
addedcrates/jrsonnet-formatter/src/tests/functions.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/functions.jsonnet
@@ -0,0 +1,10 @@
+{
+  simple(x):: x * 2,
+  with_default(x, y=10):: x + y,
+  multiline(
+    a,
+    b,
+    c,
+  ):: a + b + c,
+  called: self.simple(5),
+}
addedcrates/jrsonnet-formatter/src/tests/imports.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/imports.jsonnet
@@ -0,0 +1,7 @@
+local a = import 'a.libsonnet';
+local m = import 'm.libsonnet';
+local z = import 'z.libsonnet';
+
+{
+  result: a + m + z,
+}
addedcrates/jrsonnet-formatter/src/tests/local_vars.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/local_vars.jsonnet
@@ -0,0 +1,8 @@
+local x = 10;
+local y = 20;
+local sum = x + y;
+
+{
+  local inner = 5,
+  result: sum + inner,
+}
addedcrates/jrsonnet-formatter/src/tests/operators.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/operators.jsonnet
@@ -0,0 +1,7 @@
+{
+  arithmetic: 1 + 2 * 3 - 4 / 2,
+  comparison: 1 < 2 && 3 > 2 || false,
+  string_concat: 'hello' + ' ' + 'world',
+  object_concat: { a: 1 } + { b: 2 },
+  array_concat: [1, 2] + [3, 4],
+}
addedcrates/jrsonnet-formatter/src/tests/self_super.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/self_super.jsonnet
@@ -0,0 +1,9 @@
+local base = {
+  foo: 'bar',
+  method():: self.foo,
+};
+
+base {
+  foo: super.foo + '-extended',
+  result: self.method(),
+}
addedcrates/jrsonnet-formatter/src/tests/std_functions.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/std_functions.jsonnet
@@ -0,0 +1,6 @@
+{
+  length: std.length([1, 2, 3]),
+  type: std.type('hello'),
+  format: std.format('Hello, %s!', ['world']),
+  manifest: std.manifestJsonEx({ foo: 'bar' }, '  '),
+}
addedcrates/jrsonnet-formatter/src/tests/string_styles.jsonnetdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-formatter/src/tests/string_styles.jsonnet
@@ -0,0 +1,9 @@
+{
+  double_quote: 'hello world',
+  single_quote: 'hello world',
+  escaped: 'line1\nline2',
+  multiline: |||
+    This is a
+    multiline string
+  |||,
+}
modifiedcrates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__plain_call.snapdiffbeforeafterboth
--- a/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__plain_call.snap
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__plain_call.snap
@@ -5,49 +5,49 @@
 SOURCE_FILE@0..37
   EXPR@0..36
     EXPR_BINARY@0..36
-      EXPR@0..3
+      EXPR@0..31
         EXPR_VAR@0..3
           NAME@0..3
             IDENT@0..3 "std"
-      SUFFIX_INDEX@3..10
-        DOT@3..4 "."
-        NAME@4..10
-          IDENT@4..10 "substr"
-      SUFFIX_APPLY@10..31
-        ARGS_DESC@10..31
-          L_PAREN@10..11 "("
-          ARG@11..12
-            EXPR@11..12
-              EXPR_VAR@11..12
-                NAME@11..12
-                  IDENT@11..12 "a"
-          COMMA@12..13 ","
-          WHITESPACE@13..14 " "
-          ARG@14..15
-            EXPR@14..15
-              EXPR_NUMBER@14..15
-                FLOAT@14..15 "0"
-          COMMA@15..16 ","
-          WHITESPACE@16..17 " "
-          ARG@17..30
-            EXPR@17..30
-              EXPR_VAR@17..20
-                NAME@17..20
-                  IDENT@17..20 "std"
-              SUFFIX_INDEX@20..27
-                DOT@20..21 "."
-                NAME@21..27
-                  IDENT@21..27 "length"
-              SUFFIX_APPLY@27..30
-                ARGS_DESC@27..30
-                  L_PAREN@27..28 "("
-                  ARG@28..29
-                    EXPR@28..29
-                      EXPR_VAR@28..29
-                        NAME@28..29
-                          IDENT@28..29 "b"
-                  R_PAREN@29..30 ")"
-          R_PAREN@30..31 ")"
+        SUFFIX_INDEX@3..10
+          DOT@3..4 "."
+          NAME@4..10
+            IDENT@4..10 "substr"
+        SUFFIX_APPLY@10..31
+          ARGS_DESC@10..31
+            L_PAREN@10..11 "("
+            ARG@11..12
+              EXPR@11..12
+                EXPR_VAR@11..12
+                  NAME@11..12
+                    IDENT@11..12 "a"
+            COMMA@12..13 ","
+            WHITESPACE@13..14 " "
+            ARG@14..15
+              EXPR@14..15
+                EXPR_NUMBER@14..15
+                  FLOAT@14..15 "0"
+            COMMA@15..16 ","
+            WHITESPACE@16..17 " "
+            ARG@17..30
+              EXPR@17..30
+                EXPR_VAR@17..20
+                  NAME@17..20
+                    IDENT@17..20 "std"
+                SUFFIX_INDEX@20..27
+                  DOT@20..21 "."
+                  NAME@21..27
+                    IDENT@21..27 "length"
+                SUFFIX_APPLY@27..30
+                  ARGS_DESC@27..30
+                    L_PAREN@27..28 "("
+                    ARG@28..29
+                      EXPR@28..29
+                        EXPR_VAR@28..29
+                          NAME@28..29
+                            IDENT@28..29 "b"
+                    R_PAREN@29..30 ")"
+            R_PAREN@30..31 ")"
       WHITESPACE@31..32 " "
       EQ@32..34 "=="
       WHITESPACE@34..35 " "
addedcrates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__string_block_trim.snapdiffbeforeafterboth
--- /dev/null
+++ b/crates/jrsonnet-rowan-parser/src/snapshots/jrsonnet_rowan_parser__tests__string_block_trim.snap
@@ -0,0 +1,9 @@
+---
+source: crates/jrsonnet-rowan-parser/src/tests.rs
+expression: "|||-\n\tTrimmed text block\n|||\n"
+---
+SOURCE_FILE@0..29
+  EXPR@0..28
+    EXPR_STRING@0..28
+      STRING_BLOCK@0..28 "|||-\n\tTrimmed text bl ..."
+  WHITESPACE@28..29 "\n"
modifiedcrates/jrsonnet-rowan-parser/src/string_block.rsdiffbeforeafterboth
--- a/crates/jrsonnet-rowan-parser/src/string_block.rs
+++ b/crates/jrsonnet-rowan-parser/src/string_block.rs
@@ -52,6 +52,14 @@
 			self.rest().chars().next()
 		}
 
+		fn eat_if(&mut self, f: impl Fn(char) -> bool) -> usize {
+			if self.peek().map(f).unwrap_or(false) {
+				self.index += 1;
+				return 1;
+			}
+			0
+		}
+
 		fn eat_while(&mut self, f: impl Fn(char) -> bool) -> usize {
 			if self.index == self.source.len() {
 				return 0;
@@ -133,6 +141,8 @@
 		offset: lex.span().end,
 	};
 
+	ctx.eat_if(|v| v == '-');
+
 	// Skip whitespaces
 	ctx.eat_while(|r| r == ' ' || r == '\t' || r == '\r');
 
modifiedcrates/jrsonnet-rowan-parser/src/tests.rsdiffbeforeafterboth
before · crates/jrsonnet-rowan-parser/src/tests.rs
1// `never`2#![cfg(test)]34use hi_doc::{Formatting, SnippetBuilder, Text};5use thiserror::Error;67use crate::{parse, AstNode};89fn process(text: &str) -> String {10	use std::fmt::Write;11	let mut out = String::new();12	let (node, errors) = parse(text);13	write!(out, "{:#?}", node.syntax()).unwrap();14	if !errors.is_empty() && !text.is_empty() {15		writeln!(out, "===").unwrap();16		for err in &errors {17			writeln!(out, "{:?}", err).unwrap();18		}19		let mut code = text.to_string();2021		// Prettier errors at EOF position22		if code.ends_with('\n') {23			code.truncate(code.len() - 1);24			code += " ";25		}26		code += " ";2728		let mut s = SnippetBuilder::new(code);2930		for error in errors {31			s.error(Text::fragment(32				format!("{}", error.error),33				Formatting::default(),34			))35			.range(error.range.start().into()..=error.range.end().into())36			.build();37		}3839		writeln!(out, "===").unwrap();40		let ansi = hi_doc::source_to_ansi(&s.build());41		let text = strip_ansi_escapes::strip_str(&ansi);42		out.push_str(&text);43	}44	out.split('\n')45		.map(|s| s.trim_end().to_string())46		.collect::<Vec<String>>()47		.join("\n")48		.trim_end()49		.to_string()50}51macro_rules! mk_test {52		($($name:ident => $test:expr)+) => {$(53			#[test]54			fn $name() {55				let src = indoc::indoc!($test);56				let result = process(&src);57				insta::assert_snapshot!(stringify!($name), result, src);5859			}60		)+};61	}62mk_test!(63	empty => r#" "#64	function => r#"65		function(a, b = 1) a + b66	"#67	function_error_no_value => r#"68		function(a, b = ) a + b69	"#70	function_error_rparen => r#"71		function(a, b72	"#73	function_error_body => r#"74		function(a, b)75	"#76	local_novalue => r#"77		local a =78	"#79	local_no_value_recovery => r#"80		local a =81		local b = 3;82		183	"#848586	no_rhs => r#"87		a +88	"#89	no_lhs => r#"90		+ 291	"#92	no_operator => "93		2 294	"9596	named_before_positional => "97		a(1, 2, b=4, 3, 5, k = 12, 6)98	"99100	wrong_field_end => "101		{102			a: 1;103			b: 2;104		}105	"106107108	plain_call => "109		std.substr(a, 0, std.length(b)) == b110	"111112	destruct => "113		local [a, b, c] = arr;114		local [a, ...] = arr_rest;115		local [..., a] = rest_arr;116		local [...] = rest_in_arr;117		local [a, ...n] = arr_rest_n;118		local [...n, a] = rest_arr_n;119		local [...n] = rest_in_arr_n;120121		local {a, b, c} = obj;122		local {a, b, c, ...} = obj_rest;123		local {a, b, c, ...n} = obj_rest_n;124125		null126	"127128	str_block_missing_indent => "129		|||130	"131	str_block_missing_termination => "132		|||133			hello134	"135	str_block_missing_newline => "136		|||hello137	"138	str_block_missing_indent_text => "139		|||140		hello141	"142143	unexpected_destruct => "144		local * = 1;145		a146	"147	arr_compspec => r#"148		[a for a in [1, 2, 3]]149	"#150	arr_compspec_comma => "151		[a, for a in [1, 2, 3]]152	"153	arr_compspec_no_elems => "154		[for a in [1, 2, 3]]155	"156	arr_compspec_incompatible_with_multiple_elems => r#"157		[a for a in [1, 2, 3], b]158	"#159	arr_compspec_incompatible_with_multiple_elems_w => r#"160		[a, b, for a in [1, 2, 3], c]161	"#162163	obj_compspec => r#"164		{a:1 for a in [1, 2, 3]}165	"#166	obj_compspec_comma => "167		{a:1, for a in [1, 2, 3]}168	"169	obj_compspec_no_elems => "170		{for a in [1, 2, 3]}171	"172	obj_compspec_incompatible_with_multiple_elems => r#"173		{a:1 for a in [1, 2, 3], b:1}174	"#175	obj_compspec_incompatible_with_multiple_elems_w => r#"176		{a:1, b:1, for a in [1, 2, 3], c:1}177	"#178179	obj_compspec_incompatible_with_asserts => r#"180		{assert 1, a: 1 for a in [1,2,3]}181	"#182183	local_method => r#"184		local185			a(x) = x,186			a = function(x) x,187		; c188	"#189	obj_method => r#"190		{191			a(x): x,192			a: function(x) x,193		}194	"#195196	continue_after_total_failure => r#"197		local intr = $intrinsic(test);198199		local a = 1, b = 2, c = a + b;200201		[c]202	"#203204	super_nesting => r#"205		super.a + super.b206	"#207);208209#[test]210fn eval_simple() {211	let src = "local a = 1, b = 2; a + local c = 1; c";212	let (node, _errors) = parse(src);213214	dbg!(node);215}
after · crates/jrsonnet-rowan-parser/src/tests.rs
1// `never`2#![cfg(test)]34use hi_doc::{Formatting, SnippetBuilder, Text};5use thiserror::Error;67use crate::{parse, AstNode};89fn process(text: &str) -> String {10	use std::fmt::Write;11	let mut out = String::new();12	let (node, errors) = parse(text);13	write!(out, "{:#?}", node.syntax()).unwrap();14	if !errors.is_empty() && !text.is_empty() {15		writeln!(out, "===").unwrap();16		for err in &errors {17			writeln!(out, "{:?}", err).unwrap();18		}19		let mut code = text.to_string();2021		// Prettier errors at EOF position22		if code.ends_with('\n') {23			code.truncate(code.len() - 1);24			code += " ";25		}26		code += " ";2728		let mut s = SnippetBuilder::new(code);2930		for error in errors {31			s.error(Text::fragment(32				format!("{}", error.error),33				Formatting::default(),34			))35			.range(error.range.start().into()..=error.range.end().into())36			.build();37		}3839		writeln!(out, "===").unwrap();40		let ansi = hi_doc::source_to_ansi(&s.build());41		let text = strip_ansi_escapes::strip_str(&ansi);42		out.push_str(&text);43	}44	out.split('\n')45		.map(|s| s.trim_end().to_string())46		.collect::<Vec<String>>()47		.join("\n")48		.trim_end()49		.to_string()50}51macro_rules! mk_test {52		($($name:ident => $test:expr)+) => {$(53			#[test]54			fn $name() {55				let src = indoc::indoc!($test);56				let result = process(&src);57				insta::assert_snapshot!(stringify!($name), result, src);58			}59		)+};60	}61mk_test!(62	empty => r#" "#63	function => r#"64		function(a, b = 1) a + b65	"#66	function_error_no_value => r#"67		function(a, b = ) a + b68	"#69	function_error_rparen => r#"70		function(a, b71	"#72	function_error_body => r#"73		function(a, b)74	"#75	local_novalue => r#"76		local a =77	"#78	local_no_value_recovery => r#"79		local a =80		local b = 3;81		182	"#838485	no_rhs => r#"86		a +87	"#88	no_lhs => r#"89		+ 290	"#91	no_operator => "92		2 293	"9495	named_before_positional => "96		a(1, 2, b=4, 3, 5, k = 12, 6)97	"9899	wrong_field_end => "100		{101			a: 1;102			b: 2;103		}104	"105106107	plain_call => "108		std.substr(a, 0, std.length(b)) == b109	"110111	destruct => "112		local [a, b, c] = arr;113		local [a, ...] = arr_rest;114		local [..., a] = rest_arr;115		local [...] = rest_in_arr;116		local [a, ...n] = arr_rest_n;117		local [...n, a] = rest_arr_n;118		local [...n] = rest_in_arr_n;119120		local {a, b, c} = obj;121		local {a, b, c, ...} = obj_rest;122		local {a, b, c, ...n} = obj_rest_n;123124		null125	"126127	str_block_missing_indent => "128		|||129	"130	str_block_missing_termination => "131		|||132			hello133	"134	str_block_missing_newline => "135		|||hello136	"137	str_block_missing_indent_text => "138		|||139		hello140	"141142	unexpected_destruct => "143		local * = 1;144		a145	"146	arr_compspec => r#"147		[a for a in [1, 2, 3]]148	"#149	arr_compspec_comma => "150		[a, for a in [1, 2, 3]]151	"152	arr_compspec_no_elems => "153		[for a in [1, 2, 3]]154	"155	arr_compspec_incompatible_with_multiple_elems => r#"156		[a for a in [1, 2, 3], b]157	"#158	arr_compspec_incompatible_with_multiple_elems_w => r#"159		[a, b, for a in [1, 2, 3], c]160	"#161162	obj_compspec => r#"163		{a:1 for a in [1, 2, 3]}164	"#165	obj_compspec_comma => "166		{a:1, for a in [1, 2, 3]}167	"168	obj_compspec_no_elems => "169		{for a in [1, 2, 3]}170	"171	obj_compspec_incompatible_with_multiple_elems => r#"172		{a:1 for a in [1, 2, 3], b:1}173	"#174	obj_compspec_incompatible_with_multiple_elems_w => r#"175		{a:1, b:1, for a in [1, 2, 3], c:1}176	"#177178	obj_compspec_incompatible_with_asserts => r#"179		{assert 1, a: 1 for a in [1,2,3]}180	"#181182	local_method => r#"183		local184			a(x) = x,185			a = function(x) x,186		; c187	"#188	obj_method => r#"189		{190			a(x): x,191			a: function(x) x,192		}193	"#194195	continue_after_total_failure => r#"196		local intr = $intrinsic(test);197198		local a = 1, b = 2, c = a + b;199200		[c]201	"#202203	super_nesting => r#"204		super.a + super.b205	"#206207	string_block_trim => r#"208		|||-209			Trimmed text block210		|||211	"#212);213214#[test]215fn eval_simple() {216	let src = "local a = 1, b = 2; a + local c = 1; c";217	let (node, _errors) = parse(src);218219	dbg!(node);220}