git.delta.rocks / jrsonnet / refs/commits / cc55b2dd2d98

difftreelog

feat add description stacktrace frames for all formats

Yaroslav Bolyukin2024-06-18parent: #912ece7.patch.diff
in: master

5 files changed

modifiedcrates/jrsonnet-evaluator/src/manifest.rsdiffbeforeafterboth
183 cur_padding: &mut String,183 cur_padding: &mut String,
184 options: &JsonFormat<'_>,184 options: &JsonFormat<'_>,
185) -> Result<()> {185) -> Result<()> {
186 use JsonFormatting::*;
187
186 let mtype = options.mtype;188 let mtype = options.mtype;
187 match val {189 match val {
218 }220 }
219 Val::Arr(items) => {221 Val::Arr(items) => {
220 buf.push('[');222 buf.push('[');
221 if !items.is_empty() {
222 if mtype != JsonFormatting::ToString && mtype != JsonFormatting::Minify {
223 buf.push_str(options.newline);
224 }
225223
226 let old_len = cur_padding.len();224 let old_len = cur_padding.len();
227 cur_padding.push_str(&options.padding);225 cur_padding.push_str(&options.padding);
226
227 let mut had_items = false;
228 for (i, item) in items.iter().enumerate() {228 for (i, item) in items.iter().enumerate() {
229 had_items = true;
230 let item = item.with_description(|| format!("elem <{i}> evaluation"))?;
231
229 if i != 0 {232 if i != 0 {
233 buf.push(',');
234 }
235 match mtype {
236 Manifest | Std => {
230 buf.push(',');237 buf.push_str(options.newline);
231 if mtype == JsonFormatting::ToString {238 buf.push_str(cur_padding);
239 }
232 buf.push(' ');240 ToString => buf.push(' '),
233 } else if mtype != JsonFormatting::Minify {241 Minify => {}
234 buf.push_str(options.newline);
235 }
236 }242 };
243
237 buf.push_str(cur_padding);244 buf.push_str(cur_padding);
238 manifest_json_ex_buf(&item?, buf, cur_padding, options)
239 .with_description(|| format!("elem <{i}> manifestification"))?;245 State::push_description(
246 || format!("elem <{i}> manifestification"),
247 || manifest_json_ex_buf(&item, buf, cur_padding, options),
248 )?;
240 }249 }
250
241 cur_padding.truncate(old_len);251 cur_padding.truncate(old_len);
242252
253 match mtype {
254 Manifest | ToString if !had_items => {
255 // Empty array as "[ ]"
256 buf.push(' ');
257 }
243 if mtype != JsonFormatting::ToString && mtype != JsonFormatting::Minify {258 Manifest => {
244 buf.push_str(options.newline);259 buf.push_str(options.newline);
245 buf.push_str(cur_padding);260 buf.push_str(cur_padding);
246 }261 }
247 } else if mtype == JsonFormatting::Std {262 Std => {
263 if !had_items {
264 // Stdlib formats empty array as "[\n\n]"
248 buf.push_str(options.newline);265 buf.push_str(options.newline);
266 }
249 buf.push_str(options.newline);267 buf.push_str(options.newline);
250 buf.push_str(cur_padding);268 buf.push_str(cur_padding);
251 } else if mtype == JsonFormatting::ToString || mtype == JsonFormatting::Manifest {269 }
252 buf.push(' ');270 Minify | ToString => {}
253 }271 }
272
254 buf.push(']');273 buf.push(']');
255 }274 }
256 Val::Obj(obj) => {275 Val::Obj(obj) => {
257 obj.run_assertions()?;276 obj.run_assertions()?;
258 buf.push('{');277 buf.push('{');
259 let fields = obj.fields(
260 #[cfg(feature = "exp-preserve-order")]
261 options.preserve_order,
262 );
263 if !fields.is_empty() {
264 if mtype != JsonFormatting::ToString && mtype != JsonFormatting::Minify {
265 buf.push_str(options.newline);
266 }
267278
268 let old_len = cur_padding.len();279 let old_len = cur_padding.len();
269 cur_padding.push_str(&options.padding);280 cur_padding.push_str(&options.padding);
281
282 let mut had_fields = false;
270 for (i, field) in fields.into_iter().enumerate() {283 for (i, (key, value)) in obj
284 .iter(
285 #[cfg(feature = "exp-preserve-order")]
286 options.preserve_order,
287 )
288 .enumerate()
289 {
290 had_fields = true;
291 let value = value.with_description(|| format!("field <{key}> evaluation"))?;
292
271 if i != 0 {293 if i != 0 {
272 buf.push(',');294 buf.push(',');
273 if mtype == JsonFormatting::ToString {
274 buf.push(' ');
275 } else if mtype != JsonFormatting::Minify {
276 buf.push_str(options.newline);
277 }
278 }295 }
296 match mtype {
297 Manifest | Std => {
298 buf.push_str(options.newline);
279 buf.push_str(cur_padding);299 buf.push_str(cur_padding);
300 }
301 ToString => buf.push(' '),
302 Minify => {}
303 }
304
280 escape_string_json_buf(&field, buf);305 escape_string_json_buf(&key, buf);
281 buf.push_str(options.key_val_sep);306 buf.push_str(options.key_val_sep);
282 State::push_description(307 State::push_description(
283 || format!("field <{}> manifestification", field.clone()),308 || format!("field <{key}> manifestification"),
284 || {309 || manifest_json_ex_buf(&value, buf, cur_padding, options),
285 let value = obj.get(field.clone())?.unwrap();
286 manifest_json_ex_buf(&value, buf, cur_padding, options)?;
287 Ok(())
288 },
289 )?;310 )?;
290 }311 }
312
291 cur_padding.truncate(old_len);313 cur_padding.truncate(old_len);
292314
315 match mtype {
316 Manifest | ToString if !had_fields => {
317 // Empty object as "{ }"
318 buf.push(' ');
319 }
293 if mtype != JsonFormatting::ToString && mtype != JsonFormatting::Minify {320 Manifest => {
294 buf.push_str(options.newline);321 buf.push_str(options.newline);
295 buf.push_str(cur_padding);322 buf.push_str(cur_padding);
296 }323 }
297 } else if mtype == JsonFormatting::Std {324 Std => {
325 if !had_fields {
326 // Stdlib formats empty object as "{\n\n}"
298 buf.push_str(options.newline);327 buf.push_str(options.newline);
328 }
299 buf.push_str(options.newline);329 buf.push_str(options.newline);
300 buf.push_str(cur_padding);330 buf.push_str(cur_padding);
301 } else if mtype == JsonFormatting::ToString || mtype == JsonFormatting::Manifest {331 }
302 buf.push(' ');332 Minify | ToString => {}
303 }333 }
334
304 buf.push('}');335 buf.push('}');
305 }336 }
350 Self {381 Self {
351 inner,382 inner,
352 c_document_end,383 c_document_end,
353 // Stdlib format always inserts newline at the end384 // Stdlib format always inserts useless newline at the end
354 end_newline: true,385 end_newline: true,
355 }386 }
356 }387 }
371 )402 )
372 };403 };
373 if !arr.is_empty() {404 if !arr.is_empty() {
374 for v in arr.iter() {405 for (i, v) in arr.iter().enumerate() {
375 let v = v?;406 let v = v.with_description(|| format!("elem <{i}> evaluation"))?;
376 out.push_str("---\n");407 out.push_str("---\n");
408 State::push_description(
409 || format!("elem <{i}> manifestification"),
377 self.inner.manifest_buf(v, out)?;410 || self.inner.manifest_buf(v, out),
411 )?;
378 out.push('\n');412 out.push('\n');
379 }413 }
380 }414 }
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
11 function::{native::NativeDesc, FuncDesc, FuncVal},11 function::{native::NativeDesc, FuncDesc, FuncVal},
12 typed::CheckType,12 typed::CheckType,
13 val::{IndexableVal, StrValue, ThunkMapper},13 val::{IndexableVal, StrValue, ThunkMapper},
14 ObjValue, ObjValueBuilder, Result, Thunk, Val,14 ObjValue, ObjValueBuilder, Result, ResultExt, Thunk, Val,
15};15};
1616
17#[derive(Trace)]17#[derive(Trace)]
359 unreachable!("typecheck should fail")359 unreachable!("typecheck should fail")
360 };360 };
361 a.iter()361 a.iter()
362 .enumerate()
362 .map(|r| r.and_then(T::from_untyped))363 .map(|(i, r)| {
364 r.and_then(|t| {
365 T::from_untyped(t).with_description(|| format!("parsing elem <{i}>"))
366 })
367 })
363 .collect::<Result<Self>>()368 .collect::<Result<Self>>()
364 }369 }
365}370}
modifiedcrates/jrsonnet-stdlib/src/manifest/toml.rsdiffbeforeafterboth
4 bail,4 bail,
5 manifest::{escape_string_json_buf, ManifestFormat},5 manifest::{escape_string_json_buf, ManifestFormat},
6 val::ArrValue,6 val::ArrValue,
7 IStr, ObjValue, Result, Val,7 IStr, ObjValue, Result, ResultExt, Val, State,
8};8};
99
10pub struct TomlFormat<'s> {10pub struct TomlFormat<'s> {
106 #[cfg(feature = "exp-bigint")]106 #[cfg(feature = "exp-bigint")]
107 Val::BigInt(n) => write!(buf, "{n}").unwrap(),107 Val::BigInt(n) => write!(buf, "{n}").unwrap(),
108 Val::Arr(a) => {108 Val::Arr(a) => {
109 if a.is_empty() {
110 buf.push_str("[]");109 buf.push('[');
111 return Ok(());110
112 }111 let mut had_items = false;
113 for (i, e) in a.iter().enumerate() {112 for (i, e) in a.iter().enumerate() {
113 had_items = true;
114 let e = e?;114 let e = e.with_description(|| format!("elem <{i}> evaluation"))?;
115
115 if i != 0 {116 if i != 0 {
116 buf.push(',');117 buf.push(',');
117 } else {118 }
118 buf.push('[');
119 }
120 if inline {119 if inline {
121 buf.push(' ');120 buf.push(' ');
122 } else {121 } else {
125 buf.push_str(&options.padding);124 buf.push_str(&options.padding);
126 }125 }
126
127 State::push_description(
128 || format!("elem <{i}> manifestification"),
127 manifest_value(&e, true, buf, "", options)?;129 || manifest_value(&e, true, buf, "", options),
130 )?;
128 }131 }
132
133 if !had_items {
129 if inline {134 } else if inline {
130 buf.push(' ');135 buf.push(' ');
131 } else {136 } else {
132 buf.push('\n');137 buf.push('\n');
135 buf.push(']');140 buf.push(']');
136 }141 }
137 Val::Obj(o) => {142 Val::Obj(o) => {
138 if o.is_empty() {143 o.run_assertions()?;
139 buf.push_str("{}");
140 }
141 buf.push_str("{ ");144 buf.push('{');
145
146 let mut had_fields = false;
142 for (i, (k, v)) in o147 for (i, (k, v)) in o
143 .iter(148 .iter(
144 #[cfg(feature = "exp-preserve-order")]149 #[cfg(feature = "exp-preserve-order")]
145 options.preserve_order,150 options.preserve_order,
146 )151 )
147 .enumerate()152 .enumerate()
148 {153 {
154 had_fields = true;
149 let v = v?;155 let v = v.with_description(|| format!("field <{k}> evaluation"))?;
156
150 if i != 0 {157 if i != 0 {
151 buf.push_str(", ");158 buf.push(',');
152 }159 }
160 buf.push(' ');
161
153 escape_key_toml_buf(&k, buf);162 escape_key_toml_buf(&k, buf);
154 buf.push_str(" = ");163 buf.push_str(" = ");
164 State::push_description(
165 || format!("field <{k}> manifestification"),
155 manifest_value(&v, true, buf, "", options)?;166 || manifest_value(&v, true, buf, "", options),
167 )?;
156 }168 }
169
170 if had_fields {
171 buf.push(' ');
172 }
173
157 buf.push_str(" }");174 buf.push('}');
158 }175 }
159 Val::Null => {176 Val::Null => {
160 bail!("tried to manifest null")177 bail!("tried to manifest null")
modifiedcrates/jrsonnet-stdlib/src/manifest/xml.rsdiffbeforeafterboth
1use jrsonnet_evaluator::{1use jrsonnet_evaluator::{
2 bail,2 bail,
3 manifest::{ManifestFormat, ToStringFormat},3 manifest::{ManifestFormat, ToStringFormat},
4 typed::{ComplexValType, Either4, Typed, ValType},4 typed::{ComplexValType, Either2, Either4, Typed, ValType},
5 val::{ArrValue, IndexableVal},5 val::{ArrValue, IndexableVal},
6 Either, ObjValue, Result, ResultExt, Val,6 Either, ObjValue, Result, ResultExt, Val, State,
7};7};
88
9pub struct XmlJsonmlFormat {9pub struct XmlJsonmlFormat {
38 }38 }
3939
40 fn from_untyped(untyped: Val) -> Result<Self> {40 fn from_untyped(untyped: Val) -> Result<Self> {
41 let val = <Either![ArrValue, String]>::from_untyped(untyped)
42 .with_description(|| format!("parsing JSONML value (an array or string)"))?;
41 let Val::Arr(arr) = untyped else {43 let arr = match val {
44 Either2::A(a) => a,
42 if let Val::Str(s) = untyped {45 Either2::B(s) => return Ok(Self::String(s)),
43 return Ok(Self::String(s.to_string()));
44 };
45 bail!("expected JSONML value (an array or string)");
46 };46 };
47 if arr.len() < 1 {47 if arr.len() < 1 {
48 bail!("JSONML value should have tag");48 bail!("JSONML value should have tag (array length should be >=1)");
49 };49 };
50 let tag = String::from_untyped(50 let tag = String::from_untyped(
51 arr.get(0)51 arr.get(0)
52 .with_description(|| "getting JSONML tag")?52 .with_description(|| "getting JSONML tag")?
53 .expect("length checked"),53 .expect("length checked"),
54 )?;54 )
55 .with_description(|| format!("parsing JSONML tag"))?;
56
55 let (has_attrs, attrs) = if arr.len() >= 2 {57 let (has_attrs, attrs) = if arr.len() >= 2 {
56 let maybe_attrs = arr58 let maybe_attrs = arr
68 Ok(Self::Tag {70 Ok(Self::Tag {
69 tag,71 tag,
70 attrs,72 attrs,
71 children: Typed::from_untyped(Val::Arr(arr.slice(73 children: State::push_description(
74 || format!("parsing children"),
75 || {
76 Typed::from_untyped(Val::Arr(arr.slice(
72 Some(if has_attrs { 2 } else { 1 }),77 Some(if has_attrs { 2 } else { 1 }),
73 None,78 None,
74 None,79 None,
75 )))?,80 )))
81 },
82 )?,
76 })83 })
77 }84 }
78}85}
modifiedcrates/jrsonnet-stdlib/src/manifest/yaml.rsdiffbeforeafterboth
3use jrsonnet_evaluator::{3use jrsonnet_evaluator::{
4 bail,4 bail,
5 manifest::{escape_string_json_buf, ManifestFormat},5 manifest::{escape_string_json_buf, ManifestFormat},
6 Result, Val,6 Result, ResultExt, State, Val,
7};7};
88
9pub struct YamlFormat<'s> {9pub struct YamlFormat<'s> {
152 #[cfg(feature = "exp-bigint")]152 #[cfg(feature = "exp-bigint")]
153 Val::BigInt(n) => write!(buf, "{}", *n).unwrap(),153 Val::BigInt(n) => write!(buf, "{}", *n).unwrap(),
154 Val::Arr(a) => {154 Val::Arr(a) => {
155 if a.is_empty() {
156 buf.push_str("[]");155 let mut had_items = false;
157 } else {
158 for (i, item) in a.iter().enumerate() {156 for (i, item) in a.iter().enumerate() {
157 had_items = true;
158 let item = item.with_description(|| format!("elem <{i}> evaluation"))?;
159 if i != 0 {159 if i != 0 {
160 buf.push('\n');160 buf.push('\n');
161 buf.push_str(cur_padding);161 buf.push_str(cur_padding);
162 }162 }
163 let item = item?;
164 buf.push('-');163 buf.push('-');
165 match &item {164 match &item {
166 Val::Arr(a) if !a.is_empty() => {165 Val::Arr(a) if !a.is_empty() => {
179 if extra_padding {178 if extra_padding {
180 cur_padding.push_str(&options.padding);179 cur_padding.push_str(&options.padding);
181 }180 }
181 State::push_description(
182 || format!("elem <{i}> manifestification"),
182 manifest_yaml_ex_buf(&item, buf, cur_padding, options)?;183 || manifest_yaml_ex_buf(&item, buf, cur_padding, options),
184 )?;
183 cur_padding.truncate(prev_len);185 cur_padding.truncate(prev_len);
184 }186 }
185 }187 if !had_items {
188 buf.push_str("[]");
189 }
186 }190 }
187 Val::Obj(o) => {191 Val::Obj(o) => {
188 if o.is_empty() {
189 buf.push_str("{}");192 let mut had_fields = false;
190 } else {
191 for (i, key) in o193 for (i, (key, value)) in o
192 .fields(194 .iter(
193 #[cfg(feature = "exp-preserve-order")]195 #[cfg(feature = "exp-preserve-order")]
194 options.preserve_order,196 options.preserve_order,
195 )197 )
196 .iter()
197 .enumerate()198 .enumerate()
198 {199 {
200 had_fields = true;
201 let value = value.with_description(|| format!("field <{key}> evaluation"))?;
199 if i != 0 {202 if i != 0 {
200 buf.push('\n');203 buf.push('\n');
201 buf.push_str(cur_padding);204 buf.push_str(cur_padding);
202 }205 }
203 if !options.quote_keys && !yaml_needs_quotes(key) {206 if !options.quote_keys && !yaml_needs_quotes(&key) {
204 buf.push_str(key);207 buf.push_str(&key);
205 } else {208 } else {
206 escape_string_json_buf(key, buf);209 escape_string_json_buf(&key, buf);
207 }210 }
208 buf.push(':');211 buf.push(':');
209 let prev_len = cur_padding.len();212 let prev_len = cur_padding.len();
210 let item = o.get(key.clone())?.expect("field exists");
211 match &item {213 match &value {
212 Val::Arr(a) if !a.is_empty() => {214 Val::Arr(a) if !a.is_empty() => {
213 buf.push('\n');215 buf.push('\n');
214 buf.push_str(cur_padding);216 buf.push_str(cur_padding);
223 }225 }
224 _ => buf.push(' '),226 _ => buf.push(' '),
225 }227 }
228 State::push_description(
229 || format!("field <{key}> manifestification"),
226 manifest_yaml_ex_buf(&item, buf, cur_padding, options)?;230 || manifest_yaml_ex_buf(&value, buf, cur_padding, options),
231 )?;
227 cur_padding.truncate(prev_len);232 cur_padding.truncate(prev_len);
228 }233 }
229 }234 if !had_fields {
235 buf.push_str("{}");
236 }
230 }237 }
231 Val::Func(_) => bail!("tried to manifest function"),238 Val::Func(_) => bail!("tried to manifest function"),
232 }239 }