diff --git a/Cargo.toml b/Cargo.toml index bbe7f760..a1450a2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -150,6 +150,9 @@ mutable_key_type = "allow" redundant_pub_crate = "allow" # Sometimes code is fancier without that manual_let_else = "allow" +# Something is broken about that lint, can't be allowed for +# codegenerated-stdlib block +similar_names = "allow" #[profile.test] #opt-level = 1 diff --git a/cmds/jrsonnet-fmt/src/tests.rs b/cmds/jrsonnet-fmt/src/tests.rs index 4364dd9a..992d2353 100644 --- a/cmds/jrsonnet-fmt/src/tests.rs +++ b/cmds/jrsonnet-fmt/src/tests.rs @@ -1,4 +1,4 @@ -use dprint_core::formatting::{PrintOptions, PrintItems}; +use dprint_core::formatting::{PrintItems, PrintOptions}; use indoc::indoc; use crate::Printable; diff --git a/cmds/jrsonnet/src/main.rs b/cmds/jrsonnet/src/main.rs index dcca03ca..00e506e5 100644 --- a/cmds/jrsonnet/src/main.rs +++ b/cmds/jrsonnet/src/main.rs @@ -153,7 +153,7 @@ fn main_catch(opts: Opts) -> bool { if let Error::Evaluation(e) = e { let mut out = String::new(); trace.write_trace(&mut out, &e).expect("format error"); - eprintln!("{out}") + eprintln!("{out}"); } else { eprintln!("{e}"); } diff --git a/crates/jrsonnet-cli/src/lib.rs b/crates/jrsonnet-cli/src/lib.rs index 3bcf19a8..fb5cd52d 100644 --- a/crates/jrsonnet-cli/src/lib.rs +++ b/crates/jrsonnet-cli/src/lib.rs @@ -10,7 +10,7 @@ use jrsonnet_evaluator::{ stack::{limit_stack_depth, StackDepthLimitOverrideGuard}, FileImportResolver, }; -use jrsonnet_gcmodule::with_thread_object_space; +use jrsonnet_gcmodule::{with_thread_object_space, ObjectSpace}; pub use manifest::*; pub use stdlib::*; pub use tla::*; @@ -88,7 +88,7 @@ pub struct LeakSpace(PhantomData<()>); impl Drop for LeakSpace { fn drop(&mut self) { - with_thread_object_space(|s| s.leak()) + with_thread_object_space(ObjectSpace::leak); } } @@ -102,6 +102,6 @@ impl Drop for GcStatsPrinter { let collected = jrsonnet_gcmodule::collect_thread_cycles(); eprintln!("Collected: {collected}"); } - eprintln!("Tracked: {}", jrsonnet_gcmodule::count_thread_tracked()) + eprintln!("Tracked: {}", jrsonnet_gcmodule::count_thread_tracked()); } } diff --git a/crates/jrsonnet-cli/src/stdlib.rs b/crates/jrsonnet-cli/src/stdlib.rs index 004d7917..903b8993 100644 --- a/crates/jrsonnet-cli/src/stdlib.rs +++ b/crates/jrsonnet-cli/src/stdlib.rs @@ -39,11 +39,11 @@ impl FromStr for ExtStr { fn from_str(s: &str) -> std::result::Result { match s.find('=') { - Some(idx) => Ok(ExtStr { + Some(idx) => Ok(Self { name: s[..idx].to_owned(), value: s[idx + 1..].to_owned(), }), - None => Ok(ExtStr { + None => Ok(Self { name: s.to_owned(), value: std::env::var(s).or(Err("missing env var"))?, }), @@ -109,16 +109,16 @@ impl StdOpts { return Ok(None); } let ctx = ContextInitializer::new(s.clone(), PathResolver::new_cwd_fallback()); - for ext in self.ext_str.iter() { + for ext in &self.ext_str { ctx.add_ext_str((&ext.name as &str).into(), (&ext.value as &str).into()); } - for ext in self.ext_str_file.iter() { + for ext in &self.ext_str_file { ctx.add_ext_str((&ext.name as &str).into(), (&ext.value as &str).into()); } - for ext in self.ext_code.iter() { + for ext in &self.ext_code { ctx.add_ext_code(&ext.name as &str, &ext.value as &str)?; } - for ext in self.ext_code_file.iter() { + for ext in &self.ext_code_file { ctx.add_ext_code(&ext.name as &str, &ext.value as &str)?; } Ok(Some(ctx)) diff --git a/crates/jrsonnet-evaluator/src/arr/mod.rs b/crates/jrsonnet-evaluator/src/arr/mod.rs index 0c685d7a..b83f85c8 100644 --- a/crates/jrsonnet-evaluator/src/arr/mod.rs +++ b/crates/jrsonnet-evaluator/src/arr/mod.rs @@ -42,7 +42,7 @@ impl ArrValue { Self::new(EagerArray(values)) } - pub fn repeated(data: ArrValue, repeats: usize) -> Option { + pub fn repeated(data: Self, repeats: usize) -> Option { Some(Self::new(RepeatedArray::new(data, repeats)?)) } @@ -70,7 +70,7 @@ impl ArrValue { Ok(Self::eager(out)) } - pub fn extended(a: ArrValue, b: ArrValue) -> Self { + pub fn extended(a: Self, b: Self) -> Self { // TODO: benchmark for an optimal value, currently just a arbitrary choice const ARR_EXTEND_THRESHOLD: usize = 100; diff --git a/crates/jrsonnet-evaluator/src/function/arglike.rs b/crates/jrsonnet-evaluator/src/function/arglike.rs index a102169d..48eb786a 100644 --- a/crates/jrsonnet-evaluator/src/function/arglike.rs +++ b/crates/jrsonnet-evaluator/src/function/arglike.rs @@ -61,8 +61,8 @@ pub enum TlaArg { impl ArgLike for TlaArg { fn evaluate_arg(&self, ctx: Context, tailstrict: bool) -> Result> { match self { - TlaArg::String(s) => Ok(Thunk::evaluated(Val::string(s.clone()))), - TlaArg::Code(code) => Ok(if tailstrict { + Self::String(s) => Ok(Thunk::evaluated(Val::string(s.clone()))), + Self::Code(code) => Ok(if tailstrict { Thunk::evaluated(evaluate(ctx, code)?) } else { Thunk::new(EvaluateThunk { @@ -70,8 +70,8 @@ impl ArgLike for TlaArg { expr: code.clone(), }) }), - TlaArg::Val(val) => Ok(Thunk::evaluated(val.clone())), - TlaArg::Lazy(lazy) => Ok(lazy.clone()), + Self::Val(val) => Ok(Thunk::evaluated(val.clone())), + Self::Lazy(lazy) => Ok(lazy.clone()), } } } diff --git a/crates/jrsonnet-evaluator/src/function/mod.rs b/crates/jrsonnet-evaluator/src/function/mod.rs index 1a8732e5..c26fdbc5 100644 --- a/crates/jrsonnet-evaluator/src/function/mod.rs +++ b/crates/jrsonnet-evaluator/src/function/mod.rs @@ -237,7 +237,7 @@ impl FuncVal { pub fn evaluate_trivial(&self) -> Option { match self { - FuncVal::Normal(n) => n.evaluate_trivial(), + Self::Normal(n) => n.evaluate_trivial(), _ => None, } } diff --git a/crates/jrsonnet-evaluator/src/import.rs b/crates/jrsonnet-evaluator/src/import.rs index d32a02df..3cc0a1d5 100644 --- a/crates/jrsonnet-evaluator/src/import.rs +++ b/crates/jrsonnet-evaluator/src/import.rs @@ -10,7 +10,7 @@ use std::{ use fs::File; use jrsonnet_gcmodule::Trace; use jrsonnet_interner::IBytes; -use jrsonnet_parser::{SourceDirectory, SourceFile, SourcePath, SourceFifo}; +use jrsonnet_parser::{SourceDirectory, SourceFifo, SourceFile, SourcePath}; use crate::{ bail, diff --git a/crates/jrsonnet-evaluator/src/integrations/serde.rs b/crates/jrsonnet-evaluator/src/integrations/serde.rs index 4b14ba14..4fc20b9e 100644 --- a/crates/jrsonnet-evaluator/src/integrations/serde.rs +++ b/crates/jrsonnet-evaluator/src/integrations/serde.rs @@ -15,7 +15,7 @@ use crate::{ }; impl<'de> Deserialize<'de> for Val { - fn deserialize(deserializer: D) -> Result + fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { @@ -155,10 +155,10 @@ impl Serialize for Val { S: serde::Serializer, { match self { - Val::Bool(v) => serializer.serialize_bool(*v), - Val::Null => serializer.serialize_none(), - Val::Str(s) => serializer.serialize_str(&s.clone().into_flat()), - Val::Num(n) => { + Self::Bool(v) => serializer.serialize_bool(*v), + Self::Null => serializer.serialize_none(), + Self::Str(s) => serializer.serialize_str(&s.clone().into_flat()), + Self::Num(n) => { if n.fract() == 0.0 { let n = *n as i64; serializer.serialize_i64(n) @@ -167,8 +167,8 @@ impl Serialize for Val { } } #[cfg(feature = "exp-bigint")] - Val::BigInt(b) => b.serialize(serializer), - Val::Arr(arr) => { + Self::BigInt(b) => b.serialize(serializer), + Self::Arr(arr) => { let mut seq = serializer.serialize_seq(Some(arr.len()))?; for (i, element) in arr.iter().enumerate() { let mut serde_error = None; @@ -190,7 +190,7 @@ impl Serialize for Val { } seq.end() } - Val::Obj(obj) => { + Self::Obj(obj) => { let mut map = serializer.serialize_map(Some(obj.len()))?; for (field, value) in obj.iter( #[cfg(feature = "exp-preserve-order")] @@ -215,7 +215,7 @@ impl Serialize for Val { } map.end() } - Val::Func(_) => Err(S::Error::custom("tried to manifest function")), + Self::Func(_) => Err(S::Error::custom("tried to manifest function")), } } } @@ -248,9 +248,9 @@ impl SerializeSeq for IntoVecValSerializer { type Ok = Val; type Error = JrError; - fn serialize_element(&mut self, value: &T) -> Result<()> + fn serialize_element(&mut self, value: &T) -> Result<()> where - T: Serialize, + T: ?Sized + Serialize, { let value = value.serialize(IntoValSerializer)?; self.data.push(value); @@ -272,9 +272,9 @@ impl SerializeTuple for IntoVecValSerializer { type Ok = Val; type Error = JrError; - fn serialize_element(&mut self, value: &T) -> Result<()> + fn serialize_element(&mut self, value: &T) -> Result<()> where - T: Serialize, + T: ?Sized + Serialize, { SerializeSeq::serialize_element(self, value) } @@ -287,9 +287,9 @@ impl SerializeTupleVariant for IntoVecValSerializer { type Ok = Val; type Error = JrError; - fn serialize_field(&mut self, value: &T) -> Result<()> + fn serialize_field(&mut self, value: &T) -> Result<()> where - T: Serialize, + T: ?Sized + Serialize, { SerializeSeq::serialize_element(self, value) } @@ -302,9 +302,9 @@ impl SerializeTupleStruct for IntoVecValSerializer { type Ok = Val; type Error = JrError; - fn serialize_field(&mut self, value: &T) -> Result<()> + fn serialize_field(&mut self, value: &T) -> Result<()> where - T: Serialize, + T: ?Sized + Serialize, { SerializeSeq::serialize_element(self, value) } @@ -607,7 +607,7 @@ impl Serializer for IntoValSerializer { } impl Val { - pub fn from_serde(v: impl Serialize) -> Result { + pub fn from_serde(v: impl Serialize) -> Result { v.serialize(IntoValSerializer) } } diff --git a/crates/jrsonnet-evaluator/src/lib.rs b/crates/jrsonnet-evaluator/src/lib.rs index 1ea53153..76c4d161 100644 --- a/crates/jrsonnet-evaluator/src/lib.rs +++ b/crates/jrsonnet-evaluator/src/lib.rs @@ -45,7 +45,7 @@ pub use jrsonnet_interner::{IBytes, IStr}; #[doc(hidden)] pub use jrsonnet_macros; pub use jrsonnet_parser as parser; -use jrsonnet_parser::*; +use jrsonnet_parser::{ExprLocation, LocExpr, ParserSettings, Source, SourcePath}; pub use obj::*; use stack::check_depth; pub use tla::apply_tla; diff --git a/crates/jrsonnet-evaluator/src/stack.rs b/crates/jrsonnet-evaluator/src/stack.rs index 26ab07e4..22dfbffe 100644 --- a/crates/jrsonnet-evaluator/src/stack.rs +++ b/crates/jrsonnet-evaluator/src/stack.rs @@ -24,7 +24,7 @@ thread_local! { pub struct StackOverflowError; impl From for ErrorKind { fn from(_: StackOverflowError) -> Self { - ErrorKind::StackOverflow + Self::StackOverflow } } impl From for Error { diff --git a/crates/jrsonnet-evaluator/src/typed/conversions.rs b/crates/jrsonnet-evaluator/src/typed/conversions.rs index 17ff8643..f5c51de3 100644 --- a/crates/jrsonnet-evaluator/src/typed/conversions.rs +++ b/crates/jrsonnet-evaluator/src/typed/conversions.rs @@ -358,7 +358,7 @@ where }; a.iter() .map(|r| r.and_then(T::from_untyped)) - .collect::>>() + .collect::>() } } @@ -381,7 +381,7 @@ impl Typed for BTreeMap { Self::TYPE.check(&value)?; let obj = value.as_obj().expect("typecheck should fail"); - let mut out = BTreeMap::new(); + let mut out = Self::new(); if V::wants_lazy() { for key in obj.fields_ex( false, @@ -623,8 +623,8 @@ impl Typed for IndexableVal { fn into_untyped(value: Self) -> Result { match value { - IndexableVal::Str(s) => Ok(Val::string(s)), - IndexableVal::Arr(a) => Ok(Val::Arr(a)), + Self::Str(s) => Ok(Val::string(s)), + Self::Arr(a) => Ok(Val::Arr(a)), } } diff --git a/crates/jrsonnet-evaluator/src/val.rs b/crates/jrsonnet-evaluator/src/val.rs index f9e0071f..daea1c4a 100644 --- a/crates/jrsonnet-evaluator/src/val.rs +++ b/crates/jrsonnet-evaluator/src/val.rs @@ -147,7 +147,7 @@ where T: ThunkValue, { fn from(value: T) -> Self { - Thunk::new(value) + Self::new(value) } } @@ -221,8 +221,8 @@ pub enum IndexableVal { impl IndexableVal { pub fn to_array(self) -> ArrValue { match self { - IndexableVal::Str(s) => ArrValue::chars(s.chars()), - IndexableVal::Arr(arr) => arr, + Self::Str(s) => ArrValue::chars(s.chars()), + Self::Arr(arr) => arr, } } /// Slice the value. @@ -239,7 +239,7 @@ impl IndexableVal { step: Option>, ) -> Result { match &self { - IndexableVal::Str(s) => { + Self::Str(s) => { let mut computed_len = None; let mut get_len = || { computed_len.map_or_else( @@ -277,7 +277,7 @@ impl IndexableVal { .into(), )) } - IndexableVal::Arr(arr) => { + Self::Arr(arr) => { let get_idx = |pos: Option, len: usize, default| match pos { Some(v) if v < 0 => len.saturating_sub((-v) as usize), Some(v) => (v as usize).min(len), @@ -307,7 +307,7 @@ pub enum StrValue { Tree(Rc<(StrValue, StrValue, usize)>), } impl StrValue { - pub fn concat(a: StrValue, b: StrValue) -> Self { + pub fn concat(a: Self, b: Self) -> Self { // TODO: benchmark for an optimal value, currently just a arbitrary choice const STRING_EXTEND_THRESHOLD: usize = 100; @@ -334,8 +334,8 @@ impl StrValue { } } match self { - StrValue::Flat(f) => f, - StrValue::Tree(_) => { + Self::Flat(f) => f, + Self::Tree(_) => { let mut buf = String::with_capacity(self.len()); write_buf(&self, &mut buf); buf.into() @@ -344,8 +344,8 @@ impl StrValue { } pub fn len(&self) -> usize { match self { - StrValue::Flat(v) => v.len(), - StrValue::Tree(t) => t.2, + Self::Flat(v) => v.len(), + Self::Tree(t) => t.2, } } pub fn is_empty(&self) -> bool { @@ -367,8 +367,8 @@ where impl Display for StrValue { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - StrValue::Flat(v) => write!(f, "{v}"), - StrValue::Tree(t) => { + Self::Flat(v) => write!(f, "{v}"), + Self::Tree(t) => { write!(f, "{}", t.0)?; write!(f, "{}", t.1) } @@ -522,8 +522,8 @@ impl Val { pub fn into_indexable(self) -> Result { Ok(match self { - Val::Str(s) => IndexableVal::Str(s.into_flat()), - Val::Arr(arr) => IndexableVal::Arr(arr), + Self::Str(s) => IndexableVal::Str(s.into_flat()), + Self::Arr(arr) => IndexableVal::Arr(arr), _ => bail!(ValueIsNotIndexable(self.value_type())), }) } diff --git a/crates/jrsonnet-macros/src/lib.rs b/crates/jrsonnet-macros/src/lib.rs index b5add051..0880bf6f 100644 --- a/crates/jrsonnet-macros/src/lib.rs +++ b/crates/jrsonnet-macros/src/lib.rs @@ -1,3 +1,5 @@ +use std::string::String; + use proc_macro2::TokenStream; use quote::quote; use syn::{ @@ -205,6 +207,7 @@ pub fn builtin( } } +#[allow(clippy::too_many_lines)] fn builtin_inner( attr: BuiltinAttrs, fun: ItemFn, @@ -225,7 +228,7 @@ fn builtin_inner( .map(|arg| ArgInfo::parse(&name, arg)) .collect::>>()?; - let params_desc = args.iter().flat_map(|a| match a { + let params_desc = args.iter().filter_map(|a| match a { ArgInfo::Normal { is_option, name, @@ -234,8 +237,7 @@ fn builtin_inner( } => { let name = name .as_ref() - .map(|n| quote! {ParamName::new_static(#n)}) - .unwrap_or_else(|| quote! {None}); + .map_or_else(|| quote! {None}, |n| quote! {ParamName::new_static(#n)}); Some(quote! { #(#cfg_attrs)* BuiltinParam::new(#name, #is_option), @@ -244,15 +246,12 @@ fn builtin_inner( ArgInfo::Lazy { is_option, name } => { let name = name .as_ref() - .map(|n| quote! {ParamName::new_static(#n)}) - .unwrap_or_else(|| quote! {None}); + .map_or_else(|| quote! {None}, |n| quote! {ParamName::new_static(#n)}); Some(quote! { BuiltinParam::new(#name, #is_option), }) } - ArgInfo::Context => None, - ArgInfo::Location => None, - ArgInfo::This => None, + ArgInfo::Context | ArgInfo::Location | ArgInfo::This => None, }); let mut id = 0usize; @@ -275,7 +274,7 @@ fn builtin_inner( name, cfg_attrs, } => { - let name = name.as_ref().map(|v| v.as_str()).unwrap_or(""); + let name = name.as_ref().map_or("", String::as_str); let eval = quote! {jrsonnet_evaluator::State::push_description( || format!("argument <{}> evaluation", #name), || <#ty>::from_untyped(value.evaluate()?), @@ -390,6 +389,7 @@ fn builtin_inner( } #[derive(Default)] +#[allow(clippy::struct_excessive_bools)] struct TypedAttr { rename: Option, flatten: bool, @@ -467,11 +467,8 @@ impl TypedField { "this field should appear in output object, but it has no visible name", )); }; - let (is_option, ty) = if let Some(ty) = extract_type_from_option(&field.ty)? { - (true, ty.clone()) - } else { - (false, field.ty.clone()) - }; + let (is_option, ty) = extract_type_from_option(&field.ty)? + .map_or_else(|| (false, field.ty.clone()), |ty| (true, ty.clone())); if is_option && attr.flatten { if !attr.flatten_ok { return Err(Error::new( @@ -551,48 +548,53 @@ impl TypedField { #ident: #value, } } - fn expand_serialize(&self) -> Result { + fn expand_serialize(&self) -> TokenStream { let ident = &self.ident; let ty = &self.ty; - Ok(if let Some(name) = self.name() { - let hide = if self.attr.hide { - quote! {.hide()} - } else { - quote! {} - }; - let add = if self.attr.add { - quote! {.add()} - } else { - quote! {} - }; - if self.is_option { - quote! { - if let Some(value) = self.#ident { + self.name().map_or_else( + || { + if self.is_option { + quote! { + if let Some(value) = self.#ident { + <#ty as TypedObj>::serialize(value, out)?; + } + } + } else { + quote! { + <#ty as TypedObj>::serialize(self.#ident, out)?; + } + } + }, + |name| { + let hide = if self.attr.hide { + quote! {.hide()} + } else { + quote! {} + }; + let add = if self.attr.add { + quote! {.add()} + } else { + quote! {} + }; + if self.is_option { + quote! { + if let Some(value) = self.#ident { + out.field(#name) + #hide + #add + .try_value(<#ty as Typed>::into_untyped(value)?)?; + } + } + } else { + quote! { out.field(#name) #hide #add - .try_value(<#ty as Typed>::into_untyped(value)?)?; + .try_value(<#ty as Typed>::into_untyped(self.#ident)?)?; } } - } else { - quote! { - out.field(#name) - #hide - #add - .try_value(<#ty as Typed>::into_untyped(self.#ident)?)?; - } - } - } else if self.is_option { - quote! { - if let Some(value) = self.#ident { - <#ty as TypedObj>::serialize(value, out)?; - } - } - } else { - quote! { - <#ty as TypedObj>::serialize(self.#ident, out)?; - } - }) + }, + ) } } @@ -623,7 +625,7 @@ fn derive_typed_inner(input: DeriveInput) -> Result { let typed = { let fields = fields .iter() - .flat_map(TypedField::expand_field) + .filter_map(TypedField::expand_field) .collect::>(); quote! { impl #impl_generics Typed for #ident #ty_generics #where_clause { @@ -650,7 +652,7 @@ fn derive_typed_inner(input: DeriveInput) -> Result { let fields_serialize = fields .iter() .map(TypedField::expand_serialize) - .collect::>>()?; + .collect::>(); Ok(quote! { const _: () = { @@ -767,7 +769,7 @@ impl FormatInput { } } -/// IStr formatting helper +/// `IStr` formatting helper /// /// Using `format!("literal with no codes").into()` is slower than just `"literal with no codes".into()` /// This macro looks for formatting codes in the input string, and uses diff --git a/crates/jrsonnet-rowan-parser/src/parser.rs b/crates/jrsonnet-rowan-parser/src/parser.rs index f9c370c3..afb64b74 100644 --- a/crates/jrsonnet-rowan-parser/src/parser.rs +++ b/crates/jrsonnet-rowan-parser/src/parser.rs @@ -758,10 +758,10 @@ fn destruct(p: &mut Parser) -> CompletedMarker { } else if p.at(T![...]) { // let m_err = p.start_ranger(); destruct_rest(p); - // if had_rest { - // p.custom_error(m_err.finish(p), "only one rest can be present in array"); - // } - // had_rest = true; + // if had_rest { + // p.custom_error(m_err.finish(p), "only one rest can be present in array"); + // } + // had_rest = true; } else { destruct(p); } diff --git a/crates/jrsonnet-stdlib/build.rs b/crates/jrsonnet-stdlib/build.rs index 74bbe3da..7830f79d 100644 --- a/crates/jrsonnet-stdlib/build.rs +++ b/crates/jrsonnet-stdlib/build.rs @@ -26,7 +26,9 @@ fn main() { let dest_path = Path::new(&out_dir).join("stdlib.rs"); let mut f = File::create(dest_path).unwrap(); f.write_all( - ("#[allow(clippy::redundant_clone)]".to_owned() + &v.to_string()).as_bytes(), + ("#[allow(clippy::redundant_clone, clippy::similar_names)]".to_owned() + + &v.to_string()) + .as_bytes(), ) .unwrap(); } diff --git a/crates/jrsonnet-stdlib/src/arrays.rs b/crates/jrsonnet-stdlib/src/arrays.rs index 9a5d2623..543fe1d3 100644 --- a/crates/jrsonnet-stdlib/src/arrays.rs +++ b/crates/jrsonnet-stdlib/src/arrays.rs @@ -9,7 +9,7 @@ use jrsonnet_evaluator::{ Either, IStr, ObjValueBuilder, Result, ResultExt, Thunk, Val, }; -pub(crate) fn eval_on_empty(on_empty: Option>) -> Result { +pub fn eval_on_empty(on_empty: Option>) -> Result { if let Some(on_empty) = on_empty { on_empty.evaluate() } else { @@ -270,8 +270,8 @@ pub fn builtin_remove_at(arr: ArrValue, at: usize) -> Result { let newArrRight = arr.slice(Some(at + 1), None, None); Ok(ArrValue::extended( - newArrLeft.unwrap_or(ArrValue::empty()), - newArrRight.unwrap_or(ArrValue::empty()), + newArrLeft.unwrap_or_else(ArrValue::empty), + newArrRight.unwrap_or_else(ArrValue::empty), )) } diff --git a/crates/jrsonnet-stdlib/src/lib.rs b/crates/jrsonnet-stdlib/src/lib.rs index c7470ef3..70655833 100644 --- a/crates/jrsonnet-stdlib/src/lib.rs +++ b/crates/jrsonnet-stdlib/src/lib.rs @@ -313,10 +313,10 @@ pub struct ContextInitializer { settings: Rc>, } impl ContextInitializer { - pub fn new(_s: State, resolver: PathResolver) -> Self { + pub fn new(s: State, resolver: PathResolver) -> Self { let settings = Settings { - ext_vars: Default::default(), - ext_natives: Default::default(), + ext_vars: HashMap::new(), + ext_natives: HashMap::new(), trace_printer: Box::new(StdTracePrinter::new(resolver.clone())), path_resolver: resolver, }; @@ -324,10 +324,12 @@ impl ContextInitializer { let stdlib_obj = stdlib_uncached(settings.clone()); #[cfg(not(feature = "legacy-this-file"))] let stdlib_thunk = Thunk::evaluated(Val::Obj(stdlib_obj)); + #[cfg(feature = "legacy-this-file")] + let _ = s; Self { #[cfg(not(feature = "legacy-this-file"))] context: { - let mut context = ContextBuilder::with_capacity(_s, 1); + let mut context = ContextBuilder::with_capacity(s, 1); context.bind("std", stdlib_thunk.clone()); context.build() }, diff --git a/crates/jrsonnet-stdlib/src/manifest/toml.rs b/crates/jrsonnet-stdlib/src/manifest/toml.rs index 2bc9e4c0..f878fd5c 100644 --- a/crates/jrsonnet-stdlib/src/manifest/toml.rs +++ b/crates/jrsonnet-stdlib/src/manifest/toml.rs @@ -180,7 +180,9 @@ fn manifest_table_internal( options.preserve_order, ) { let value = value?; - if !is_section(&value)? { + if is_section(&value)? { + sections.push((key, value)); + } else { if !first { buf.push('\n'); } @@ -189,8 +191,6 @@ fn manifest_table_internal( escape_key_toml_buf(&key, buf); buf.push_str(" = "); manifest_value(&value, false, buf, cur_padding, options)?; - } else { - sections.push((key, value)); } } for (k, v) in sections { diff --git a/crates/jrsonnet-stdlib/src/math.rs b/crates/jrsonnet-stdlib/src/math.rs index d124cd3c..ac8bffa9 100644 --- a/crates/jrsonnet-stdlib/src/math.rs +++ b/crates/jrsonnet-stdlib/src/math.rs @@ -131,16 +131,19 @@ pub fn builtin_is_even(x: f64) -> bool { } #[builtin] +#[allow(clippy::float_cmp)] pub fn builtin_is_odd(x: f64) -> bool { builtin_round(x) % 2.0 == 1.0 } #[builtin] +#[allow(clippy::float_cmp)] pub fn builtin_is_integer(x: f64) -> bool { builtin_round(x) == x } #[builtin] +#[allow(clippy::float_cmp)] pub fn builtin_is_decimal(x: f64) -> bool { builtin_round(x) != x } diff --git a/crates/jrsonnet-stdlib/src/misc.rs b/crates/jrsonnet-stdlib/src/misc.rs index d5460442..2933258e 100644 --- a/crates/jrsonnet-stdlib/src/misc.rs +++ b/crates/jrsonnet-stdlib/src/misc.rs @@ -67,11 +67,7 @@ pub fn builtin_trace( v => v.manifest(JsonFormat::debug())?.into(), }, ); - if let Some(rest) = rest { - rest.evaluate() - } else { - Ok(str) - } + rest.map_or_else(|| Ok(str), |rest| rest.evaluate()) } #[allow(clippy::comparison_chain)] @@ -84,16 +80,15 @@ pub fn builtin_starts_with(a: Either![IStr, ArrValue], b: Either![IStr, ArrValue return Ok(false); } else if b.len() == a.len() { return equals(&Val::Arr(a), &Val::Arr(b)); - } else { - for (a, b) in a.iter().take(b.len()).zip(b.iter()) { - let a = a?; - let b = b?; - if !equals(&a, &b)? { - return Ok(false); - } + } + for (a, b) in a.iter().take(b.len()).zip(b.iter()) { + let a = a?; + let b = b?; + if !equals(&a, &b)? { + return Ok(false); } - true } + true } _ => bail!("both arguments should be of the same type"), }) @@ -109,17 +104,16 @@ pub fn builtin_ends_with(a: Either![IStr, ArrValue], b: Either![IStr, ArrValue]) return Ok(false); } else if b.len() == a.len() { return equals(&Val::Arr(a), &Val::Arr(b)); - } else { - let a_len = a.len(); - for (a, b) in a.iter().skip(a_len - b.len()).zip(b.iter()) { - let a = a?; - let b = b?; - if !equals(&a, &b)? { - return Ok(false); - } + } + let a_len = a.len(); + for (a, b) in a.iter().skip(a_len - b.len()).zip(b.iter()) { + let a = a?; + let b = b?; + if !equals(&a, &b)? { + return Ok(false); } - true } + true } _ => bail!("both arguments should be of the same type"), }) diff --git a/crates/jrsonnet-stdlib/src/objects.rs b/crates/jrsonnet-stdlib/src/objects.rs index 64a3a5c6..1f36bf20 100644 --- a/crates/jrsonnet-stdlib/src/objects.rs +++ b/crates/jrsonnet-stdlib/src/objects.rs @@ -155,7 +155,7 @@ pub fn builtin_object_remove_key( if k == key { continue; } - new_obj.field(k).value(v.unwrap()) + new_obj.field(k).value(v.unwrap()); } new_obj.build() diff --git a/crates/jrsonnet-stdlib/src/sort.rs b/crates/jrsonnet-stdlib/src/sort.rs index 023b506b..18de08ad 100644 --- a/crates/jrsonnet-stdlib/src/sort.rs +++ b/crates/jrsonnet-stdlib/src/sort.rs @@ -36,7 +36,7 @@ impl Ord for NonNaNf64 { fn get_sort_type(values: &[T], key_getter: impl Fn(&T) -> &Val) -> Result { let mut sort_type = SortKeyType::Unknown; - for i in values.iter() { + for i in values { let i = key_getter(i); match (i, sort_type) { (Val::Str(_), SortKeyType::Unknown) => sort_type = SortKeyType::String, diff --git a/crates/jrsonnet-stdlib/src/strings.rs b/crates/jrsonnet-stdlib/src/strings.rs index 5211a495..8c8654d5 100644 --- a/crates/jrsonnet-stdlib/src/strings.rs +++ b/crates/jrsonnet-stdlib/src/strings.rs @@ -75,7 +75,7 @@ pub fn builtin_find_substr(pat: IStr, str: IStr) -> ArrValue { .enumerate() { if &strb[i..i + pat.len()] == pat { - out.push(Val::Num(ch_idx as f64)) + out.push(Val::Num(ch_idx as f64)); } } out.into() @@ -117,11 +117,6 @@ pub fn builtin_parse_hex(str: IStr) -> Result { } fn parse_nat(raw: &str) -> Result { - debug_assert!( - 1 <= BASE && BASE <= 16, - "integer base should be between 1 and 16" - ); - const ZERO_CODE: u32 = '0' as u32; const UPPER_A_CODE: u32 = 'A' as u32; const LOWER_A_CODE: u32 = 'a' as u32; @@ -135,10 +130,17 @@ fn parse_nat(raw: &str) -> Result { } } - let base = BASE as f64; + debug_assert!( + 1 <= BASE && BASE <= 16, + "integer base should be between 1 and 16" + ); + + let base = f64::from(BASE); raw.chars().try_fold(0f64, |aggregate, digit| { let digit = digit as u32; + // if-let-else looks better here than Option combinators + #[allow(clippy::option_if_let_else)] let digit = if let Some(digit) = checked_sub_if(BASE > 10, digit, LOWER_A_CODE) { digit + 10 } else if let Some(digit) = checked_sub_if(BASE > 10, digit, UPPER_A_CODE) { @@ -148,7 +150,7 @@ fn parse_nat(raw: &str) -> Result { }; if digit < BASE { - Ok(base * aggregate + digit as f64) + Ok(base.mul_add(aggregate, f64::from(digit))) } else { bail!("{raw:?} is not a base {BASE} integer"); } diff --git a/crates/jrsonnet-types/src/lib.rs b/crates/jrsonnet-types/src/lib.rs index 0518ce5a..08dc821b 100644 --- a/crates/jrsonnet-types/src/lib.rs +++ b/crates/jrsonnet-types/src/lib.rs @@ -166,9 +166,9 @@ fn write_union<'i>( fn print_array(a: &ComplexValType, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if *a == ComplexValType::Any { - write!(f, "array")? + write!(f, "array")?; } else { - write!(f, "Array<{a}>")? + write!(f, "Array<{a}>")?; } Ok(()) } @@ -176,18 +176,20 @@ fn print_array(a: &ComplexValType, f: &mut std::fmt::Formatter<'_>) -> std::fmt: impl Display for ComplexValType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - ComplexValType::Any => write!(f, "any")?, - ComplexValType::Simple(s) => write!(f, "{s}")?, - ComplexValType::Char => write!(f, "char")?, - ComplexValType::BoundedNumber(a, b) => write!( + Self::Any => write!(f, "any")?, + Self::Simple(s) => write!(f, "{s}")?, + Self::Char => write!(f, "char")?, + Self::BoundedNumber(a, b) => write!( f, "BoundedNumber<{}, {}>", - a.map(|e| e.to_string()).unwrap_or_else(|| "".into()), - b.map(|e| e.to_string()).unwrap_or_else(|| "".into()) + a.map(|e| e.to_string()) + .unwrap_or_else(|| "open".to_owned()), + b.map(|e| e.to_string()) + .unwrap_or_else(|| "open".to_owned()) )?, - ComplexValType::ArrayRef(a) => print_array(a, f)?, - ComplexValType::Array(a) => print_array(a, f)?, - ComplexValType::ObjectRef(fields) => { + Self::ArrayRef(a) => print_array(a, f)?, + Self::Array(a) => print_array(a, f)?, + Self::ObjectRef(fields) => { write!(f, "{{")?; for (i, (k, v)) in fields.iter().enumerate() { if i != 0 { @@ -197,18 +199,18 @@ impl Display for ComplexValType { } write!(f, "}}")?; } - ComplexValType::AttrsOf(a) => { - if matches!(a, ComplexValType::Any) { + Self::AttrsOf(a) => { + if matches!(a, Self::Any) { write!(f, "object")?; } else { write!(f, "AttrsOf<{a}>")?; } } - ComplexValType::Union(v) => write_union(f, true, v.iter())?, - ComplexValType::UnionRef(v) => write_union(f, true, v.iter().copied())?, - ComplexValType::Sum(v) => write_union(f, false, v.iter())?, - ComplexValType::SumRef(v) => write_union(f, false, v.iter().copied())?, - ComplexValType::Lazy(lazy) => write!(f, "Lazy<{lazy}>")?, + Self::Union(v) => write_union(f, true, v.iter())?, + Self::UnionRef(v) => write_union(f, true, v.iter().copied())?, + Self::Sum(v) => write_union(f, false, v.iter())?, + Self::SumRef(v) => write_union(f, false, v.iter().copied())?, + Self::Lazy(lazy) => write!(f, "Lazy<{lazy}>")?, }; Ok(()) } diff --git a/tests/suite/std_param_names.jsonnet b/tests/suite/std_param_names.jsonnet index 5e969bb6..b7765ffd 100644 --- a/tests/suite/std_param_names.jsonnet +++ b/tests/suite/std_param_names.jsonnet @@ -49,6 +49,7 @@ local names = { min: ['a', 'b'], clamp: ['x', 'minVal', 'maxVal'], flattenArrays: ['arrs'], + flattenDeepArray: ['value'], manifestIni: ['ini'], manifestToml: ['value'], manifestTomlEx: ['value', 'indent'],