difftreelog
refactor remove trace format from state
in: master
5 files changed
cmds/jrsonnet/src/main.rsdiffbeforeafterboth1use std::{2 fs::{create_dir_all, File},3 io::{Read, Write},4};56use clap::{CommandFactory, Parser};7use clap_complete::Shell;8use jrsonnet_cli::{ConfigureState, GeneralOpts, ManifestOpts, OutputOpts, TraceOpts};9use jrsonnet_evaluator::{apply_tla, error::LocError, throw, ResultExt, State, Val};1011#[cfg(feature = "mimalloc")]12#[global_allocator]13static GLOBAL: mimallocator::Mimalloc = mimallocator::Mimalloc;1415#[derive(Parser)]16enum SubOpts {17 /// Generate completions for specified shell18 Generate {19 /// Target shell name20 shell: Shell,21 },22}2324#[derive(Parser)]25#[clap(next_help_heading = "DEBUG")]26struct DebugOpts {27 /// Required OS stack size.28 /// This shouldn't be changed unless jrsonnet is failing with stack overflow error.29 #[clap(long, name = "size")]30 pub os_stack: Option<usize>,31}3233#[derive(Parser)]34#[clap(next_help_heading = "INPUT")]35struct InputOpts {36 /// Treat input as code, evaluate them instead of reading file37 #[clap(long, short = 'e')]38 pub exec: bool,3940 /// Path to the file to be compiled if `--evaluate` is unset, otherwise code itself41 pub input: Option<String>,42}4344#[derive(Parser)]45#[clap(args_conflicts_with_subcommands = true, disable_version_flag = true)]46struct Opts {47 #[clap(subcommand)]48 sub: Option<SubOpts>,4950 #[clap(flatten)]51 input: InputOpts,52 #[clap(flatten)]53 general: GeneralOpts,54 #[clap(flatten)]55 manifest: ManifestOpts,56 #[clap(flatten)]57 output: OutputOpts,58 #[clap(flatten)]59 debug: DebugOpts,60}6162fn main() {63 let opts: Opts = Opts::parse();6465 if let Some(sub) = opts.sub {66 match sub {67 SubOpts::Generate { shell } => {68 use clap_complete::generate;69 let app = &mut Opts::command();70 let buf = &mut std::io::stdout();71 generate(shell, app, "jrsonnet", buf);72 std::process::exit(0)73 }74 }75 }7677 let success = if let Some(size) = opts.debug.os_stack {78 std::thread::Builder::new()79 .stack_size(size * 1024 * 1024)80 .spawn(|| main_catch(opts))81 .expect("new thread spawned")82 .join()83 .expect("thread finished successfully")84 } else {85 main_catch(opts)86 };87 if !success {88 std::process::exit(1);89 }90}9192#[derive(thiserror::Error, Debug)]93enum Error {94 // Handled differently95 #[error("evaluation error")]96 Evaluation(LocError),97 #[error("io error")]98 Io(#[from] std::io::Error),99 #[error("input is not utf8 encoded")]100 Utf8(#[from] std::str::Utf8Error),101 #[error("missing input argument")]102 MissingInputArgument,103}104impl From<LocError> for Error {105 fn from(e: LocError) -> Self {106 Self::Evaluation(e)107 }108}109impl From<jrsonnet_evaluator::error::Error> for Error {110 fn from(e: jrsonnet_evaluator::error::Error) -> Self {111 Self::from(LocError::from(e))112 }113}114115fn main_catch(opts: Opts) -> bool {116 let s = State::default();117 if let Err(e) = main_real(&s, opts) {118 if let Error::Evaluation(e) = e {119 eprintln!("{}", s.stringify_err(&e));120 } else {121 eprintln!("{}", e);122 }123 return false;124 }125 true126}127128fn main_real(s: &State, opts: Opts) -> Result<(), Error> {129 let (_stack_guard, tla, _gc_guard) = opts.general.configure(s)?;130 let manifest_format = opts.manifest.configure(s)?;131132 let input = opts.input.input.ok_or(Error::MissingInputArgument)?;133 let val = if opts.input.exec {134 s.evaluate_snippet("<cmdline>".to_owned(), &input as &str)?135 } else if input == "-" {136 let mut input = Vec::new();137 std::io::stdin().read_to_end(&mut input)?;138 let input_str = std::str::from_utf8(&input)?;139 s.evaluate_snippet("<stdin>".to_owned(), input_str)?140 } else {141 s.import(&input)?142 };143144 let val = apply_tla(s.clone(), &tla, val)?;145146 if let Some(multi) = opts.output.multi {147 if opts.output.create_output_dirs {148 let mut dir = multi.clone();149 dir.pop();150 create_dir_all(dir)?;151 }152 let Val::Obj(obj) = val else {153 throw!("value should be object for --multi manifest, got {}", val.value_type())154 };155 for (field, data) in obj.iter(156 #[cfg(feature = "exp-preserve-order")]157 opts.manifest.preserve_order,158 ) {159 let data = data.with_description(|| format!("getting field {field} for manifest"))?;160161 let mut path = multi.clone();162 path.push(&field as &str);163 if opts.output.create_output_dirs {164 let mut dir = path.clone();165 dir.pop();166 create_dir_all(dir)?;167 }168 println!("{}", path.to_str().expect("path"));169 let mut file = File::create(path)?;170 writeln!(171 file,172 "{}",173 data.manifest(&manifest_format)174 .with_description(|| format!("manifesting {field}"))?175 )?;176 }177 } else if let Some(path) = opts.output.output_file {178 if opts.output.create_output_dirs {179 let mut dir = path.clone();180 dir.pop();181 create_dir_all(dir)?;182 }183 let mut file = File::create(path)?;184 writeln!(file, "{}", val.manifest(manifest_format)?)?;185 } else {186 let output = val.manifest(manifest_format)?;187 if !output.is_empty() {188 println!("{}", output);189 }190 }191192 Ok(())193}1use std::{2 fs::{create_dir_all, File},3 io::{Read, Write},4};56use clap::{CommandFactory, Parser};7use clap_complete::Shell;8use jrsonnet_cli::{ConfigureState, GeneralOpts, ManifestOpts, OutputOpts, TraceOpts};9use jrsonnet_evaluator::{apply_tla, error::LocError, throw, ResultExt, State, Val};1011#[cfg(feature = "mimalloc")]12#[global_allocator]13static GLOBAL: mimallocator::Mimalloc = mimallocator::Mimalloc;1415#[derive(Parser)]16enum SubOpts {17 /// Generate completions for specified shell18 Generate {19 /// Target shell name20 shell: Shell,21 },22}2324#[derive(Parser)]25#[clap(next_help_heading = "DEBUG")]26struct DebugOpts {27 /// Required OS stack size.28 /// This shouldn't be changed unless jrsonnet is failing with stack overflow error.29 #[clap(long, name = "size")]30 pub os_stack: Option<usize>,31}3233#[derive(Parser)]34#[clap(next_help_heading = "INPUT")]35struct InputOpts {36 /// Treat input as code, evaluate them instead of reading file37 #[clap(long, short = 'e')]38 pub exec: bool,3940 /// Path to the file to be compiled if `--evaluate` is unset, otherwise code itself41 pub input: Option<String>,42}4344#[derive(Parser)]45#[clap(args_conflicts_with_subcommands = true, disable_version_flag = true)]46struct Opts {47 #[clap(subcommand)]48 sub: Option<SubOpts>,4950 #[clap(flatten)]51 input: InputOpts,52 #[clap(flatten)]53 general: GeneralOpts,5455 #[clap(flatten)]56 trace: TraceOpts,57 #[clap(flatten)]58 manifest: ManifestOpts,59 #[clap(flatten)]60 output: OutputOpts,61 #[clap(flatten)]62 debug: DebugOpts,63}6465fn main() {66 let opts: Opts = Opts::parse();6768 if let Some(sub) = opts.sub {69 match sub {70 SubOpts::Generate { shell } => {71 use clap_complete::generate;72 let app = &mut Opts::command();73 let buf = &mut std::io::stdout();74 generate(shell, app, "jrsonnet", buf);75 std::process::exit(0)76 }77 }78 }7980 let success = if let Some(size) = opts.debug.os_stack {81 std::thread::Builder::new()82 .stack_size(size * 1024 * 1024)83 .spawn(|| main_catch(opts))84 .expect("new thread spawned")85 .join()86 .expect("thread finished successfully")87 } else {88 main_catch(opts)89 };90 if !success {91 std::process::exit(1);92 }93}9495#[derive(thiserror::Error, Debug)]96enum Error {97 // Handled differently98 #[error("evaluation error")]99 Evaluation(LocError),100 #[error("io error")]101 Io(#[from] std::io::Error),102 #[error("input is not utf8 encoded")]103 Utf8(#[from] std::str::Utf8Error),104 #[error("missing input argument")]105 MissingInputArgument,106}107impl From<LocError> for Error {108 fn from(e: LocError) -> Self {109 Self::Evaluation(e)110 }111}112impl From<jrsonnet_evaluator::error::Error> for Error {113 fn from(e: jrsonnet_evaluator::error::Error) -> Self {114 Self::from(LocError::from(e))115 }116}117118fn main_catch(opts: Opts) -> bool {119 let s = State::default();120 let trace = opts121 .trace122 .configure(&s)123 .expect("this configurator doesn't fail");124 if let Err(e) = main_real(&s, opts) {125 if let Error::Evaluation(e) = e {126 let mut out = String::new();127 trace.write_trace(&mut out, &e).expect("format error");128 eprintln!("{out}")129 } else {130 eprintln!("{}", e);131 }132 return false;133 }134 true135}136137fn main_real(s: &State, opts: Opts) -> Result<(), Error> {138 let (_stack_guard, tla, _gc_guard) = opts.general.configure(s)?;139 let manifest_format = opts.manifest.configure(s)?;140141 let input = opts.input.input.ok_or(Error::MissingInputArgument)?;142 let val = if opts.input.exec {143 s.evaluate_snippet("<cmdline>".to_owned(), &input as &str)?144 } else if input == "-" {145 let mut input = Vec::new();146 std::io::stdin().read_to_end(&mut input)?;147 let input_str = std::str::from_utf8(&input)?;148 s.evaluate_snippet("<stdin>".to_owned(), input_str)?149 } else {150 s.import(&input)?151 };152153 let val = apply_tla(s.clone(), &tla, val)?;154155 if let Some(multi) = opts.output.multi {156 if opts.output.create_output_dirs {157 let mut dir = multi.clone();158 dir.pop();159 create_dir_all(dir)?;160 }161 let Val::Obj(obj) = val else {162 throw!("value should be object for --multi manifest, got {}", val.value_type())163 };164 for (field, data) in obj.iter(165 #[cfg(feature = "exp-preserve-order")]166 opts.manifest.preserve_order,167 ) {168 let data = data.with_description(|| format!("getting field {field} for manifest"))?;169170 let mut path = multi.clone();171 path.push(&field as &str);172 if opts.output.create_output_dirs {173 let mut dir = path.clone();174 dir.pop();175 create_dir_all(dir)?;176 }177 println!("{}", path.to_str().expect("path"));178 let mut file = File::create(path)?;179 writeln!(180 file,181 "{}",182 data.manifest(&manifest_format)183 .with_description(|| format!("manifesting {field}"))?184 )?;185 }186 } else if let Some(path) = opts.output.output_file {187 if opts.output.create_output_dirs {188 let mut dir = path.clone();189 dir.pop();190 create_dir_all(dir)?;191 }192 let mut file = File::create(path)?;193 writeln!(file, "{}", val.manifest(manifest_format)?)?;194 } else {195 let output = val.manifest(manifest_format)?;196 if !output.is_empty() {197 println!("{}", output);198 }199 }200201 Ok(())202}crates/jrsonnet-cli/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-cli/src/lib.rs
+++ b/crates/jrsonnet-cli/src/lib.rs
@@ -76,9 +76,6 @@
std: StdOpts,
#[clap(flatten)]
- trace: TraceOpts,
-
- #[clap(flatten)]
gc: GcOpts,
}
@@ -90,7 +87,6 @@
);
fn configure(&self, s: &State) -> Result<Self::Guards> {
// Configure trace first, because tla-code/ext-code can throw
- self.trace.configure(s)?;
let misc_guards = self.misc.configure(s)?;
let tla_guards = self.tla.configure(s)?;
self.std.configure(s)?;
crates/jrsonnet-cli/src/trace.rsdiffbeforeafterboth--- a/crates/jrsonnet-cli/src/trace.rs
+++ b/crates/jrsonnet-cli/src/trace.rs
@@ -1,7 +1,7 @@
use clap::{Parser, ValueEnum};
use jrsonnet_evaluator::{
error::Result,
- trace::{CompactFormat, ExplainingFormat, PathResolver},
+ trace::{CompactFormat, ExplainingFormat, PathResolver, TraceFormat},
State,
};
@@ -27,21 +27,25 @@
max_trace: usize,
}
impl ConfigureState for TraceOpts {
- type Guards = ();
- fn configure(&self, s: &State) -> Result<()> {
+ type Guards = Box<dyn TraceFormat>;
+ fn configure(&self, _s: &State) -> Result<Self::Guards> {
let resolver = PathResolver::new_cwd_fallback();
- match self
+ let max_trace = self.max_trace;
+ let format: Box<dyn TraceFormat> = match self
.trace_format
.as_ref()
.unwrap_or(&TraceFormatName::Compact)
{
- TraceFormatName::Compact => s.set_trace_format(CompactFormat {
+ TraceFormatName::Compact => Box::new(CompactFormat {
resolver,
padding: 4,
+ max_trace,
}),
- TraceFormatName::Explaining => s.set_trace_format(ExplainingFormat { resolver }),
- }
- s.set_max_trace(self.max_trace);
- Ok(())
+ TraceFormatName::Explaining => Box::new(ExplainingFormat {
+ resolver,
+ max_trace,
+ }),
+ };
+ Ok(format)
}
}
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/error.rs
+++ b/crates/jrsonnet-evaluator/src/error.rs
@@ -262,7 +262,6 @@
write!(f, "\t{}", el.desc)?;
if let Some(loc) = &el.location {
write!(f, "at {}", loc.0 .0 .0)?;
- // loc.0
loc.0.map_source_locations(&[loc.1, loc.2]);
}
writeln!(f)?;
crates/jrsonnet-evaluator/src/trace/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/trace/mod.rs
+++ b/crates/jrsonnet-evaluator/src/trace/mod.rs
@@ -1,9 +1,12 @@
-use std::path::{Path, PathBuf};
+use std::{
+ any::Any,
+ path::{Path, PathBuf},
+};
use jrsonnet_gcmodule::Trace;
use jrsonnet_parser::{CodeLocation, Source};
-use crate::{error::Error, LocError, State};
+use crate::{error::Error, LocError};
/// The way paths should be displayed
#[derive(Clone, Trace)]
@@ -48,9 +51,15 @@
fn write_trace(
&self,
out: &mut dyn std::fmt::Write,
- s: &State,
error: &LocError,
) -> Result<(), std::fmt::Error>;
+ fn format(&self, error: &LocError) -> Result<String, std::fmt::Error> {
+ let mut out = String::new();
+ self.write_trace(&mut out, error)?;
+ Ok(out)
+ }
+ fn as_any(&self) -> &dyn Any;
+ fn as_any_mut(&mut self) -> &mut dyn Any;
}
fn print_code_location(
@@ -81,14 +90,23 @@
#[derive(Trace)]
pub struct CompactFormat {
pub resolver: PathResolver,
+ pub max_trace: usize,
pub padding: usize,
}
+impl Default for CompactFormat {
+ fn default() -> Self {
+ Self {
+ resolver: PathResolver::Absolute,
+ max_trace: 20,
+ padding: 4,
+ }
+ }
+}
impl TraceFormat for CompactFormat {
fn write_trace(
&self,
out: &mut dyn std::fmt::Write,
- _s: &State,
error: &LocError,
) -> Result<(), std::fmt::Error> {
write!(out, "{}", error.error())?;
@@ -168,15 +186,24 @@
}
Ok(())
}
+
+ fn as_any(&self) -> &dyn Any {
+ self
+ }
+
+ fn as_any_mut(&mut self) -> &mut dyn Any {
+ self
+ }
}
#[derive(Trace)]
-pub struct JsFormat;
+pub struct JsFormat {
+ pub max_trace: usize,
+}
impl TraceFormat for JsFormat {
fn write_trace(
&self,
out: &mut dyn std::fmt::Write,
- _s: &State,
error: &LocError,
) -> Result<(), std::fmt::Error> {
write!(out, "{}", error.error())?;
@@ -201,6 +228,14 @@
}
Ok(())
}
+
+ fn as_any(&self) -> &dyn Any {
+ self
+ }
+
+ fn as_any_mut(&mut self) -> &mut dyn Any {
+ self
+ }
}
/// rustc-like trace displaying
@@ -208,13 +243,13 @@
#[derive(Trace)]
pub struct ExplainingFormat {
pub resolver: PathResolver,
+ pub max_trace: usize,
}
#[cfg(feature = "explaining-traces")]
impl TraceFormat for ExplainingFormat {
fn write_trace(
&self,
out: &mut dyn std::fmt::Write,
- _s: &State,
error: &LocError,
) -> Result<(), std::fmt::Error> {
write!(out, "{}", error.error())?;
@@ -258,6 +293,14 @@
}
Ok(())
}
+
+ fn as_any(&self) -> &dyn Any {
+ self
+ }
+
+ fn as_any_mut(&mut self) -> &mut dyn Any {
+ self
+ }
}
impl ExplainingFormat {