difftreelog
feat locationless stack frames
in: master
4 files changed
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth132132133#[derive(Clone, Debug)]133#[derive(Clone, Debug)]134pub struct StackTraceElement {134pub struct StackTraceElement {135 pub location: ExprLocation,135 pub location: Option<ExprLocation>,136 pub desc: String,136 pub desc: String,137}137}138#[derive(Debug, Clone)]138#[derive(Debug, Clone)]crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth132 frame_desc: impl FnOnce() -> String,132 frame_desc: impl FnOnce() -> String,133 f: impl FnOnce() -> Result<T>,133 f: impl FnOnce() -> Result<T>,134) -> Result<T> {134) -> Result<T> {135 if let Some(v) = e {136 with_state(|s| s.push(v, frame_desc, f))135 with_state(|s| s.push(e, frame_desc, f))137 } else {138 f()139 }140}136}137138pub fn push_stack_frame<T>(139 e: Option<&ExprLocation>,140 frame_desc: impl FnOnce() -> String,141 f: impl FnOnce() -> Result<T>,142 ) -> Result<T> {143 push(e, frame_desc, f)144}141145142/// Maintains stack trace and import resolution146/// Maintains stack trace and import resolution143#[derive(Default, Clone)]147#[derive(Default, Clone)]271 /// Executes code creating a new stack frame275 /// Executes code creating a new stack frame272 pub fn push<T>(276 pub fn push<T>(273 &self,277 &self,274 e: &ExprLocation,278 e: Option<&ExprLocation>,275 frame_desc: impl FnOnce() -> String,279 frame_desc: impl FnOnce() -> String,276 f: impl FnOnce() -> Result<T>,280 f: impl FnOnce() -> Result<T>,277 ) -> Result<T> {281 ) -> Result<T> {290 self.data_mut().stack_depth -= 1;294 self.data_mut().stack_depth -= 1;291 if let Err(mut err) = result {295 if let Err(mut err) = result {292 err.trace_mut().0.push(StackTraceElement {296 err.trace_mut().0.push(StackTraceElement {293 location: e.clone(),297 location: e.cloned(),294 desc: frame_desc(),298 desc: frame_desc(),295 });299 });296 return Err(err);300 return Err(err);336 pub fn with_tla(&self, val: Val) -> Result<Val> {340 pub fn with_tla(&self, val: Val) -> Result<Val> {337 self.run_in_state(|| {341 self.run_in_state(|| {338 Ok(match val {342 Ok(match val {339 Val::Func(func) => func.evaluate_map(343 Val::Func(func) => push(None, || "during TLA call".to_owned(), || Ok(func.evaluate_map(340 self.create_default_context()?,344 self.create_default_context()?,341 &self.settings().tla_vars,345 &self.settings().tla_vars,342 true,346 true,343 )?,347 )?))?,344 v => v,348 v => v,345 })349 })346 })350 })crates/jrsonnet-evaluator/src/trace/location.rsdiffbeforeafterboth37 ];37 ];38 let mut with_no_known_line_ending = vec![];38 let mut with_no_known_line_ending = vec![];39 let mut this_line_offset = 0;39 let mut this_line_offset = 0;40 for (pos, ch) in file.chars().enumerate() {40 for (pos, ch) in file.chars().enumerate().chain(std::iter::once((file.len(), ' '))) {41 column += 1;41 column += 1;42 match offset_map.last() {42 match offset_map.last() {43 Some(x) if x.0 == pos => {43 Some(x) if x.0 == pos => {crates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth118 .trace()118 .trace()119 .0119 .0120 .iter()120 .iter()121 .map(|el| {121 .map(|el| el.location.as_ref().map(|l| {122 let resolved_path = self.resolver.resolve(&el.location.0);123 // TODO: Process all trace elements first124 let location = evaluation_state125 .map_source_locations(&el.location.0, &[el.location.1, el.location.2]);126 (resolved_path, location)127 })128 .map(|(mut n, location)| {129 use std::fmt::Write;122 use std::fmt::Write;123 let mut resolved_path = self.resolver.resolve(&l.0);124 // TODO: Process all trace elements first125 let location = evaluation_state126 .map_source_locations(&l.0, &[l.1, l.2]);130 write!(n, ":").unwrap();127 write!(resolved_path, ":").unwrap();131 print_code_location(&mut n, &location[0], &location[1]).unwrap();128 print_code_location(&mut resolved_path, &location[0], &location[1]).unwrap();132 n129 resolved_path133 })130 }))134 .collect::<Vec<_>>();131 .collect::<Vec<_>>();135 let align = file_names.iter().map(|e| e.len()).max().unwrap_or(0);132 let align = file_names.iter().flatten().map(|e| e.len()).max().unwrap_or(0);136 for (i, (el, file)) in error.trace().0.iter().zip(file_names).enumerate() {133 for (i, (el, file)) in error.trace().0.iter().zip(file_names).enumerate() {137 if i != 0 {134 if i != 0 {138 writeln!(out)?;135 writeln!(out)?;141 out,138 out,142 "{:<p$}{:<w$}: {}",139 "{:<p$}{:<w$}: {}",143 "",140 "",144 file,141 file.unwrap_or_else(|| "".to_owned()),145 el.desc,142 el.desc,146 p = self.padding,143 p = self.padding,147 w = align144 w = align165 writeln!(out)?;162 writeln!(out)?;166 }163 }167 let desc = &item.desc;164 let desc = &item.desc;168 let source = item.location.clone();165 if let Some (source) = &item.location {169 let start_end = evaluation_state.map_source_locations(&source.0, &[source.1, source.2]);166 let start_end = evaluation_state.map_source_locations(&source.0, &[source.1, source.2]);170167171 write!(168 write!(176 start_end[0].line,173 start_end[0].line,177 start_end[0].column,174 start_end[0].column,178 )?;175 )?;176 } else {177 write!(178 out,179 " at {}",180 desc,181 )?;182 }179 }183 }180 Ok(())184 Ok(())181 }185 }225 let trace = &error.trace();229 let trace = &error.trace();226 for item in trace.0.iter() {230 for item in trace.0.iter() {227 let desc = &item.desc;231 let desc = &item.desc;228 let source = item.location.clone();232 if let Some(source) = &item.location {229 let start_end = evaluation_state.map_source_locations(&source.0, &[source.1, source.2]);233 let start_end = evaluation_state.map_source_locations(&source.0, &[source.1, source.2]);230231 self.print_snippet(234 self.print_snippet(236 &start_end[1],239 &start_end[1],237 desc,240 desc,238 )?;241 )?;242 } else {243 write!(out, "{}", desc)?;244 }239 }245 }240 Ok(())246 Ok(())241 }247 }