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

difftreelog

style fix clippy warnings

Yaroslav Bolyukin2024-05-19parent: #e3e6483.patch.diff
in: master

19 files changed

modifiedbindings/jsonnet/src/import.rsdiffbeforeafterboth
--- a/bindings/jsonnet/src/import.rs
+++ b/bindings/jsonnet/src/import.rs
@@ -64,7 +64,7 @@
 				self.ctx,
 				base.as_ptr(),
 				rel.as_ptr(),
-				&mut (found_here as *const _),
+				&mut found_here.cast_const(),
 				&mut buf,
 				&mut buf_len,
 			)
@@ -121,7 +121,7 @@
 		cb,
 		ctx,
 		out: RefCell::new(HashMap::new()),
-	})
+	});
 }
 
 /// # Safety
modifiedbindings/jsonnet/src/lib.rsdiffbeforeafterboth
--- a/bindings/jsonnet/src/lib.rs
+++ b/bindings/jsonnet/src/lib.rs
@@ -86,7 +86,6 @@
 	let state = State::default();
 	state.settings_mut().import_resolver = tb!(FileImportResolver::default());
 	state.settings_mut().context_initializer = tb!(jrsonnet_stdlib::ContextInitializer::new(
-		state.clone(),
 		PathResolver::new_cwd_fallback(),
 	));
 	Box::into_raw(Box::new(VM {
@@ -107,7 +106,7 @@
 /// Set the maximum stack depth.
 #[no_mangle]
 pub extern "C" fn jsonnet_max_stack(_vm: &VM, v: c_uint) {
-	set_stack_depth_limit(v as usize)
+	set_stack_depth_limit(v as usize);
 }
 
 /// Set the number of objects required before a garbage collection cycle is allowed.
@@ -175,7 +174,7 @@
 #[no_mangle]
 pub extern "C" fn jsonnet_max_trace(vm: &mut VM, v: c_uint) {
 	if let Some(format) = vm.trace_format.as_any_mut().downcast_mut::<CompactFormat>() {
-		format.max_trace = v as usize
+		format.max_trace = v as usize;
 	} else {
 		panic!("max_trace is not supported by current tracing format")
 	}
@@ -183,7 +182,7 @@
 
 /// Evaluate a file containing Jsonnet code, return a JSON string.
 ///
-/// The returned string should be cleaned up with jsonnet_realloc.
+/// The returned string should be cleaned up with `jsonnet_realloc`.
 ///
 /// # Safety
 ///
@@ -216,7 +215,7 @@
 
 /// Evaluate a string containing Jsonnet code, return a JSON string.
 ///
-/// The returned string should be cleaned up with jsonnet_realloc.
+/// The returned string should be cleaned up with `jsonnet_realloc`.
 ///
 /// # Safety
 ///
@@ -359,7 +358,7 @@
 	out.push(0);
 	let v = out.as_ptr();
 	std::mem::forget(out);
-	v as *const c_char
+	v.cast::<c_char>()
 }
 
 /// # Safety
modifiedbindings/jsonnet/src/val_extract.rsdiffbeforeafterboth
--- a/bindings/jsonnet/src/val_extract.rs
+++ b/bindings/jsonnet/src/val_extract.rs
@@ -26,7 +26,7 @@
 pub extern "C" fn jsonnet_json_extract_number(_vm: &VM, v: &Val, out: &mut c_double) -> c_int {
 	match v {
 		Val::Num(n) => {
-			*out = *n;
+			*out = n.get();
 			1
 		}
 		_ => 0,
modifiedbindings/jsonnet/src/val_make.rsdiffbeforeafterboth
--- a/bindings/jsonnet/src/val_make.rs
+++ b/bindings/jsonnet/src/val_make.rs
@@ -5,7 +5,10 @@
 	os::raw::{c_char, c_double, c_int},
 };
 
-use jrsonnet_evaluator::{val::ArrValue, ObjValue, Val};
+use jrsonnet_evaluator::{
+	val::{ArrValue, NumValue},
+	ObjValue, Val,
+};
 
 use crate::VM;
 
@@ -24,7 +27,9 @@
 /// Convert the given double to a `JsonnetJsonValue`.
 #[no_mangle]
 pub extern "C" fn jsonnet_json_make_number(_vm: &VM, v: c_double) -> *mut Val {
-	Box::into_raw(Box::new(Val::Num(v)))
+	Box::into_raw(Box::new(Val::Num(
+		NumValue::new(v).expect("jsonnet numbers are finite"),
+	)))
 }
 
 /// Convert the given `bool` (`1` or `0`) to a `JsonnetJsonValue`.
modifiedbindings/jsonnet/src/val_modify.rsdiffbeforeafterboth
--- a/bindings/jsonnet/src/val_modify.rs
+++ b/bindings/jsonnet/src/val_modify.rs
@@ -12,7 +12,7 @@
 ///
 /// # Safety
 ///
-/// `arr` should be a pointer to array value allocated by make_array, or returned by other library call
+/// `arr` should be a pointer to array value allocated by `make_array`, or returned by other library call
 /// `val` should be a pointer to value allocated using this library
 #[no_mangle]
 pub unsafe extern "C" fn jsonnet_json_array_append(_vm: &VM, arr: &mut Val, val: &Val) {
modifiedbindings/jsonnet/src/vars_tlas.rsdiffbeforeafterboth
--- a/bindings/jsonnet/src/vars_tlas.rs
+++ b/bindings/jsonnet/src/vars_tlas.rs
@@ -27,7 +27,7 @@
 		.add_ext_str(
 			name.to_str().expect("name is not utf-8").into(),
 			value.to_str().expect("value is not utf-8").into(),
-		)
+		);
 }
 
 /// Binds a Jsonnet external variable to the given code.
@@ -51,7 +51,7 @@
 			name.to_str().expect("name is not utf-8"),
 			code.to_str().expect("code is not utf-8"),
 		)
-		.expect("can't parse ext code")
+		.expect("can't parse ext code");
 }
 
 /// Binds a top-level string argument for a top-level parameter.
modifiedcmds/jrsonnet-fmt/src/children.rsdiffbeforeafterboth
--- a/cmds/jrsonnet-fmt/src/children.rs
+++ b/cmds/jrsonnet-fmt/src/children.rs
@@ -28,7 +28,7 @@
 				TS![, ;].contains(item.kind()),
 				"silently eaten token: {:?}",
 				item.kind()
-			)
+			);
 		}
 	}
 	out
@@ -48,13 +48,13 @@
 		if let Some(trivia) = item.as_token().cloned().and_then(Trivia::cast) {
 			out.push(Ok(trivia));
 		} else if CustomError::can_cast(item.kind()) {
-			out.push(Err(item.to_string()))
+			out.push(Err(item.to_string()));
 		} else {
 			assert!(
 				TS![, ;].contains(item.kind()),
 				"silently eaten token: {:?}",
 				item.kind()
-			)
+			);
 		}
 	}
 	out
@@ -115,11 +115,7 @@
 				TriviaKind::Whitespace => {
 					nl_count += t.text().bytes().filter(|b| *b == b'\n').count();
 				}
-				TriviaKind::SingleLineHashComment => {
-					nl_count += 1;
-					break;
-				}
-				TriviaKind::SingleLineSlashComment => {
+				TriviaKind::SingleLineHashComment | TriviaKind::SingleLineSlashComment => {
 					nl_count += 1;
 					break;
 				}
@@ -163,7 +159,7 @@
 				inline_trivia: Vec::new(),
 			});
 			if let Some(last_child) = last_child {
-				out.push(last_child)
+				out.push(last_child);
 			}
 			had_some = true;
 			started_next = false;
@@ -188,7 +184,7 @@
 			}
 			had_some = true;
 		} else if CustomError::can_cast(item.kind()) {
-			next.push(Err(item.to_string()))
+			next.push(Err(item.to_string()));
 		} else if loose {
 			if had_some {
 				break;
@@ -199,7 +195,7 @@
 				TS![, ;].contains(item.kind()),
 				"silently eaten token: {:?}",
 				item.kind()
-			)
+			);
 		}
 	}
 
modifiedcmds/jrsonnet-fmt/src/comments.rsdiffbeforeafterboth
--- a/cmds/jrsonnet-fmt/src/comments.rs
+++ b/cmds/jrsonnet-fmt/src/comments.rs
@@ -1,3 +1,5 @@
+use std::string::String;
+
 use dprint_core::formatting::PrintItems;
 use jrsonnet_rowan_parser::{nodes::TriviaKind, AstToken};
 
@@ -12,6 +14,7 @@
 	EndOfItems,
 }
 
+#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
 pub fn format_comments(comments: &ChildTrivia, loc: CommentLocation, out: &mut PrintItems) {
 	for c in comments {
 		let Ok(c) = c else {
@@ -62,14 +65,14 @@
 						}
 					})
 					.collect::<Vec<_>>();
-				while lines.last().map(|l| l.is_empty()).unwrap_or(false) {
+				while lines.last().is_some_and(String::is_empty) {
 					lines.pop();
 				}
 				if lines.len() == 1 && !doc {
 					if matches!(loc, CommentLocation::ItemInline) {
 						p!(out, str(" "));
 					}
-					p!(out, str("/* ") string(lines[0].trim().to_string()) str(" */") nl)
+					p!(out, str("/* ") string(lines[0].trim().to_string()) str(" */") nl);
 				} else if !lines.is_empty() {
 					fn common_ws_prefix<'a>(a: &'a str, b: &str) -> &'a str {
 						let offset = a
@@ -95,7 +98,7 @@
 					}
 					for line in lines
 						.iter_mut()
-						.skip(if immediate_start { 1 } else { 0 })
+						.skip(usize::from(immediate_start))
 						.filter(|l| !l.is_empty())
 					{
 						*line = line
@@ -127,13 +130,13 @@
 								}
 								line = new_line.to_string();
 							}
-							p!(out, string(line.to_string()) nl)
+							p!(out, string(line.to_string()) nl);
 						}
 					}
 					if doc {
 						p!(out, str(" "));
 					}
-					p!(out, str("*/") nl)
+					p!(out, str("*/") nl);
 				}
 			}
 			// TODO: Keep common padding for multiple continous lines of single-line comments
@@ -154,20 +157,20 @@
 			// ```
 			TriviaKind::SingleLineHashComment => {
 				if matches!(loc, CommentLocation::ItemInline) {
-					p!(out, str(" "))
+					p!(out, str(" "));
 				}
 				p!(out, str("# ") string(c.text().strip_prefix('#').expect("hash comment starts with #").trim().to_string()));
 				if !matches!(loc, CommentLocation::ItemInline) {
-					p!(out, nl)
+					p!(out, nl);
 				}
 			}
 			TriviaKind::SingleLineSlashComment => {
 				if matches!(loc, CommentLocation::ItemInline) {
-					p!(out, str(" "))
+					p!(out, str(" "));
 				}
 				p!(out, str("// ") string(c.text().strip_prefix("//").expect("comment starts with //").trim().to_string()));
 				if !matches!(loc, CommentLocation::ItemInline) {
-					p!(out, nl)
+					p!(out, nl);
 				}
 			}
 			// Garbage in - garbage out
modifiedcmds/jrsonnet-fmt/src/main.rsdiffbeforeafterboth
before · cmds/jrsonnet-fmt/src/main.rs
1use std::{2	any::type_name,3	fs,4	io::{self, Write},5	path::PathBuf,6	process,7	rc::Rc,8};910use children::{children_between, trivia_before};11use clap::Parser;12use dprint_core::formatting::{13	condition_helpers::is_multiple_lines, condition_resolvers::true_resolver,14	ConditionResolverContext, LineNumber, PrintItems, PrintOptions,15};16use jrsonnet_rowan_parser::{17	nodes::{18		Arg, ArgsDesc, Assertion, BinaryOperator, Bind, CompSpec, Destruct, DestructArrayPart,19		DestructRest, Expr, ExprBase, FieldName, ForSpec, IfSpec, ImportKind, Literal, Member,20		Name, Number, ObjBody, ObjLocal, ParamsDesc, SliceDesc, SourceFile, Stmt, Suffix, Text,21		UnaryOperator, Visibility,22	},23	AstNode, AstToken as _, SyntaxToken,24};2526use crate::{27	children::trivia_after,28	comments::{format_comments, CommentLocation},29};3031mod children;32mod comments;33#[cfg(test)]34mod tests;3536pub trait Printable {37	fn print(&self, out: &mut PrintItems);38}3940macro_rules! pi {41	(@i; $($t:tt)*) => {{42		#[allow(unused_mut)]43		let mut o = dprint_core::formatting::PrintItems::new();44		pi!(@s; o: $($t)*);45		o46	}};47	(@s; $o:ident: str($e:expr $(,)?) $($t:tt)*) => {{48		$o.push_str($e);49		pi!(@s; $o: $($t)*);50	}};51	(@s; $o:ident: string($e:expr $(,)?) $($t:tt)*) => {{52		$o.push_string($e);53		pi!(@s; $o: $($t)*);54	}};55	(@s; $o:ident: nl $($t:tt)*) => {{56		$o.push_signal(dprint_core::formatting::Signal::NewLine);57		pi!(@s; $o: $($t)*);58	}};59	(@s; $o:ident: tab $($t:tt)*) => {{60		$o.push_signal(dprint_core::formatting::Signal::Tab);61		pi!(@s; $o: $($t)*);62	}};63	(@s; $o:ident: >i $($t:tt)*) => {{64		$o.push_signal(dprint_core::formatting::Signal::StartIndent);65		pi!(@s; $o: $($t)*);66	}};67	(@s; $o:ident: <i $($t:tt)*) => {{68		$o.push_signal(dprint_core::formatting::Signal::FinishIndent);69		pi!(@s; $o: $($t)*);70	}};71	(@s; $o:ident: info($v:expr) $($t:tt)*) => {{72		$o.push_info($v);73		pi!(@s; $o: $($t)*);74	}};75	(@s; $o:ident: if($s:literal, $cond:expr, $($i:tt)*) $($t:tt)*) => {{76		$o.push_condition(dprint_core::formatting::conditions::if_true(77			$s,78			$cond.clone(),79			{80				let mut o = PrintItems::new();81				p!(o, $($i)*);82				o83			},84		));85		pi!(@s; $o: $($t)*);86	}};87	(@s; $o:ident: if_else($s:literal, $cond:expr, $($i:tt)*)($($e:tt)+) $($t:tt)*) => {{88		$o.push_condition(dprint_core::formatting::conditions::if_true_or(89			$s,90			$cond.clone(),91			{92				let mut o = PrintItems::new();93				p!(o, $($i)*);94				o95			},96			{97				let mut o = PrintItems::new();98				p!(o, $($e)*);99				o100			},101		));102		pi!(@s; $o: $($t)*);103	}};104	(@s; $o:ident: if_not($s:literal, $cond:expr, $($e:tt)*) $($t:tt)*) => {{105		$o.push_condition(dprint_core::formatting::conditions::if_true_or(106			$s,107			$cond.clone(),108			{109				let o = PrintItems::new();110				o111			},112			{113				let mut o = PrintItems::new();114				p!(o, $($e)*);115				o116			},117		));118		pi!(@s; $o: $($t)*);119	}};120	(@s; $o:ident: {$expr:expr} $($t:tt)*) => {{121		$expr.print($o);122		pi!(@s; $o: $($t)*);123	}};124	(@s; $o:ident: items($expr:expr) $($t:tt)*) => {{125		$o.extend($expr);126		pi!(@s; $o: $($t)*);127	}};128	(@s; $o:ident: if ($e:expr)($($then:tt)*) $($t:tt)*) => {{129		if $e {130			pi!(@s; $o: $($then)*);131		}132		pi!(@s; $o: $($t)*);133	}};134	(@s; $o:ident: ifelse ($e:expr)($($then:tt)*)($($else:tt)*) $($t:tt)*) => {{135		if $e {136			pi!(@s; $o: $($then)*);137		} else {138			pi!(@s; $o: $($else)*);139		}140		pi!(@s; $o: $($t)*);141	}};142	(@s; $i:ident:) => {}143}144macro_rules! p {145	($o:ident, $($t:tt)*) => {146		pi!(@s; $o: $($t)*)147	};148}149pub(crate) use p;150pub(crate) use pi;151152impl<P> Printable for Option<P>153where154	P: Printable,155{156	fn print(&self, out: &mut PrintItems) {157		if let Some(v) = self {158			v.print(out)159		} else {160			p!(161				out,162				string(format!(163					"/*missing {}*/",164					type_name::<P>().replace("jrsonnet_rowan_parser::generated::nodes::", "")165				),)166			)167		}168	}169}170171impl Printable for SyntaxToken {172	fn print(&self, out: &mut PrintItems) {173		p!(out, string(self.to_string()))174	}175}176177impl Printable for Text {178	fn print(&self, out: &mut PrintItems) {179		p!(out, string(format!("{}", self)))180	}181}182impl Printable for Number {183	fn print(&self, out: &mut PrintItems) {184		p!(out, string(format!("{}", self)))185	}186}187188impl Printable for Name {189	fn print(&self, out: &mut PrintItems) {190		p!(out, { self.ident_lit() })191	}192}193194impl Printable for DestructRest {195	fn print(&self, out: &mut PrintItems) {196		p!(out, str("..."));197		if let Some(name) = self.into() {198			p!(out, { name });199		}200	}201}202203impl Printable for Destruct {204	fn print(&self, out: &mut PrintItems) {205		match self {206			Destruct::DestructFull(f) => {207				p!(out, { f.name() })208			}209			Destruct::DestructSkip(_) => p!(out, str("?")),210			Destruct::DestructArray(a) => {211				p!(out, str("[") >i nl);212				for el in a.destruct_array_parts() {213					match el {214						DestructArrayPart::DestructArrayElement(e) => {215							p!(out, {e.destruct()} str(",") nl)216						}217						DestructArrayPart::DestructRest(d) => {218							p!(out, {d} str(",") nl)219						}220					}221				}222				p!(out, <i str("]"));223			}224			Destruct::DestructObject(o) => {225				p!(out, str("{") >i nl);226				for item in o.destruct_object_fields() {227					p!(out, { item.field() });228					if let Some(des) = item.destruct() {229						p!(out, str(": ") {des})230					}231					if let Some(def) = item.expr() {232						p!(out, str(" = ") {def});233					}234					p!(out, str(",") nl);235				}236				if let Some(rest) = o.destruct_rest() {237					p!(out, {rest} nl)238				}239				p!(out, <i str("}"));240			}241		}242	}243}244245impl Printable for FieldName {246	fn print(&self, out: &mut PrintItems) {247		match self {248			FieldName::FieldNameFixed(f) => {249				if let Some(id) = f.id() {250					p!(out, { id })251				} else if let Some(str) = f.text() {252					p!(out, { str })253				} else {254					p!(out, str("/*missing FieldName*/"))255				}256			}257			FieldName::FieldNameDynamic(d) => {258				p!(out, str("[") {d.expr()} str("]"))259			}260		}261	}262}263264impl Printable for Visibility {265	fn print(&self, out: &mut PrintItems) {266		p!(out, string(self.to_string()))267	}268}269270impl Printable for ObjLocal {271	fn print(&self, out: &mut PrintItems) {272		p!(out, str("local ") {self.bind()})273	}274}275276impl Printable for Assertion {277	fn print(&self, out: &mut PrintItems) {278		p!(out, str("assert ") {self.condition()});279		if self.colon_token().is_some() || self.message().is_some() {280			p!(out, str(": ") {self.message()})281		}282	}283}284285impl Printable for ParamsDesc {286	fn print(&self, out: &mut PrintItems) {287		p!(out, str("(") >i nl);288		for param in self.params() {289			p!(out, { param.destruct() });290			if param.assign_token().is_some() || param.expr().is_some() {291				p!(out, str(" = ") {param.expr()})292			}293			p!(out, str(",") nl)294		}295		p!(out, <i str(")"));296	}297}298impl Printable for ArgsDesc {299	fn print(&self, out: &mut PrintItems) {300		let start = LineNumber::new("start");301		let end = LineNumber::new("end");302		let multi_line = Rc::new(move |condition_context: &mut ConditionResolverContext| {303			is_multiple_lines(condition_context, start, end).map(|v| !v)304		});305		p!(out, str("(") info(start) if("start args", multi_line, >i nl));306		let (children, end_comments) = children_between::<Arg>(307			self.syntax().clone(),308			self.l_paren_token().map(Into::into).as_ref(),309			self.r_paren_token().map(Into::into).as_ref(),310			None,311		);312		let mut args = children.into_iter().peekable();313		while let Some(ele) = args.next() {314			if ele.should_start_with_newline {315				p!(out, nl);316			}317			format_comments(&ele.before_trivia, CommentLocation::AboveItem, out);318			let arg = ele.value;319			if arg.name().is_some() || arg.assign_token().is_some() {320				p!(out, {arg.name()} str(" = "));321			}322			let comma_between = if args.peek().is_some() {323				true_resolver()324			} else {325				multi_line.clone()326			};327			p!(out, {arg.expr()} if("arg comma", comma_between, str(",") if_not("between args", multi_line, str(" "))));328			format_comments(&ele.inline_trivia, CommentLocation::ItemInline, out);329			p!(out, if("between args", multi_line, nl));330		}331		if end_comments.should_start_with_newline {332			p!(out, nl);333		}334		format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);335		p!(out, if("end args", multi_line, <i info(end)) str(")"));336	}337}338impl Printable for SliceDesc {339	fn print(&self, out: &mut PrintItems) {340		p!(out, str("["));341		if self.from().is_some() {342			p!(out, { self.from() });343		}344		p!(out, str(":"));345		if self.end().is_some() {346			p!(out, { self.end().map(|e| e.expr()) })347		}348		// Keep only one : in case if we don't need step349		if self.step().is_some() {350			p!(out, str(":") {self.step().map(|e|e.expr())});351		}352		p!(out, str("]"));353	}354}355356impl Printable for Member {357	fn print(&self, out: &mut PrintItems) {358		match self {359			Self::MemberBindStmt(b) => {360				p!(out, { b.obj_local() })361			}362			Self::MemberAssertStmt(ass) => {363				p!(out, { ass.assertion() })364			}365			Self::MemberFieldNormal(n) => {366				p!(out, {n.field_name()} if(n.plus_token().is_some())({n.plus_token()}) {n.visibility()} str(" ") {n.expr()})367			}368			Self::MemberFieldMethod(m) => {369				p!(out, {m.field_name()} {m.params_desc()} {m.visibility()} str(" ") {m.expr()})370			}371		}372	}373}374375impl Printable for ObjBody {376	fn print(&self, out: &mut PrintItems) {377		match self {378			ObjBody::ObjBodyComp(l) => {379				let (children, mut end_comments) = children_between::<Member>(380					l.syntax().clone(),381					l.l_brace_token().map(Into::into).as_ref(),382					Some(383						&(l.comp_specs()384							.next()385							.expect("at least one spec is defined")386							.syntax()387							.clone())388						.into(),389					),390					None,391				);392				let trailing_for_comp = end_comments.extract_trailing();393				p!(out, str("{") >i nl);394				for mem in children.into_iter() {395					if mem.should_start_with_newline {396						p!(out, nl);397					}398					format_comments(&mem.before_trivia, CommentLocation::AboveItem, out);399					p!(out, {mem.value} str(","));400					format_comments(&mem.inline_trivia, CommentLocation::ItemInline, out);401					p!(out, nl)402				}403404				if end_comments.should_start_with_newline {405					p!(out, nl);406				}407				format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);408409				let (compspecs, end_comments) = children_between::<CompSpec>(410					l.syntax().clone(),411					l.member_comps()412						.last()413						.map(|m| m.syntax().clone())414						.map(Into::into)415						.or_else(|| l.l_brace_token().map(Into::into))416						.as_ref(),417					l.r_brace_token().map(Into::into).as_ref(),418					Some(trailing_for_comp),419				);420				for mem in compspecs.into_iter() {421					if mem.should_start_with_newline {422						p!(out, nl);423					}424					format_comments(&mem.before_trivia, CommentLocation::AboveItem, out);425					p!(out, { mem.value });426					format_comments(&mem.inline_trivia, CommentLocation::ItemInline, out);427				}428				if end_comments.should_start_with_newline {429					p!(out, nl);430				}431				format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);432433				p!(out, nl <i str("}"));434			}435			ObjBody::ObjBodyMemberList(l) => {436				let (children, end_comments) = children_between::<Member>(437					l.syntax().clone(),438					l.l_brace_token().map(Into::into).as_ref(),439					l.r_brace_token().map(Into::into).as_ref(),440					None,441				);442				if children.is_empty() && end_comments.is_empty() {443					p!(out, str("{ }"));444					return;445				}446				p!(out, str("{") >i nl);447				for (i, mem) in children.into_iter().enumerate() {448					if mem.should_start_with_newline && i != 0 {449						p!(out, nl);450					}451					format_comments(&mem.before_trivia, CommentLocation::AboveItem, out);452					p!(out, {mem.value} str(","));453					format_comments(&mem.inline_trivia, CommentLocation::ItemInline, out);454					p!(out, nl)455				}456457				if end_comments.should_start_with_newline {458					p!(out, nl);459				}460				format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);461				p!(out, <i str("}"));462			}463		}464	}465}466impl Printable for UnaryOperator {467	fn print(&self, out: &mut PrintItems) {468		p!(out, string(self.text().to_string()))469	}470}471impl Printable for BinaryOperator {472	fn print(&self, out: &mut PrintItems) {473		p!(out, string(self.text().to_string()))474	}475}476impl Printable for Bind {477	fn print(&self, out: &mut PrintItems) {478		match self {479			Bind::BindDestruct(d) => {480				p!(out, {d.into()} str(" = ") {d.value()})481			}482			Bind::BindFunction(f) => {483				p!(out, {f.name()} {f.params()} str(" = ") {f.value()})484			}485		}486	}487}488impl Printable for Literal {489	fn print(&self, out: &mut PrintItems) {490		p!(out, string(self.syntax().to_string()))491	}492}493impl Printable for ImportKind {494	fn print(&self, out: &mut PrintItems) {495		p!(out, string(self.syntax().to_string()))496	}497}498impl Printable for ForSpec {499	fn print(&self, out: &mut PrintItems) {500		p!(out, str("for ") {self.bind()} str(" in ") {self.expr()})501	}502}503impl Printable for IfSpec {504	fn print(&self, out: &mut PrintItems) {505		p!(out, str("if ") {self.expr()})506	}507}508impl Printable for CompSpec {509	fn print(&self, out: &mut PrintItems) {510		match self {511			CompSpec::ForSpec(f) => f.print(out),512			CompSpec::IfSpec(i) => i.print(out),513		}514	}515}516impl Printable for Expr {517	fn print(&self, out: &mut PrintItems) {518		let (stmts, _ending) = children_between::<Stmt>(519			self.syntax().clone(),520			None,521			self.expr_base()522				.as_ref()523				.map(ExprBase::syntax)524				.cloned()525				.map(Into::into)526				.as_ref(),527			None,528		);529		for stmt in stmts {530			p!(out, { stmt.value });531		}532		p!(out, { self.expr_base() });533		let (suffixes, _ending) = children_between::<Suffix>(534			self.syntax().clone(),535			self.expr_base()536				.as_ref()537				.map(ExprBase::syntax)538				.cloned()539				.map(Into::into)540				.as_ref(),541			None,542			None,543		);544		for suffix in suffixes {545			p!(out, { suffix.value });546		}547	}548}549impl Printable for Suffix {550	fn print(&self, out: &mut PrintItems) {551		match self {552			Suffix::SuffixIndex(i) => {553				if i.question_mark_token().is_some() {554					p!(out, str("?"));555				}556				p!(out, str(".") {i.index()});557			}558			Suffix::SuffixIndexExpr(e) => {559				if e.question_mark_token().is_some() {560					p!(out, str(".?"));561				}562				p!(out, str("[") {e.index()} str("]"))563			}564			Suffix::SuffixSlice(d) => {565				p!(out, { d.slice_desc() })566			}567			Suffix::SuffixApply(a) => {568				p!(out, { a.args_desc() })569			}570		}571	}572}573impl Printable for Stmt {574	fn print(&self, out: &mut PrintItems) {575		match self {576			Stmt::StmtLocal(l) => {577				let (binds, end_comments) = children_between::<Bind>(578					l.syntax().clone(),579					l.local_kw_token().map(Into::into).as_ref(),580					l.semi_token().map(Into::into).as_ref(),581					None,582				);583				if binds.len() == 1 {584					let bind = &binds[0];585					format_comments(&bind.before_trivia, CommentLocation::AboveItem, out);586					p!(out, str("local ") {bind.value});587				// TODO: keep end_comments, child.inline_trivia somehow, force multiple locals formatting in case of presence?588				} else {589					p!(out,str("local") >i nl);590					for bind in binds {591						if bind.should_start_with_newline {592							p!(out, nl);593						}594						format_comments(&bind.before_trivia, CommentLocation::AboveItem, out);595						p!(out, {bind.value} str(","));596						format_comments(&bind.inline_trivia, CommentLocation::ItemInline, out);597						p!(out, nl)598					}599					if end_comments.should_start_with_newline {600						p!(out, nl)601					}602					format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);603					p!(out,<i);604				}605				p!(out,str(";") nl);606			}607			Stmt::StmtAssert(a) => {608				p!(out, {a.assertion()} str(";") nl)609			}610		}611	}612}613impl Printable for ExprBase {614	fn print(&self, out: &mut PrintItems) {615		match self {616			Self::ExprBinary(b) => {617				p!(out, {b.lhs_work()} str(" ") {b.binary_operator()} str(" ") {b.rhs_work()})618			}619			Self::ExprUnary(u) => p!(out, {u.unary_operator()} {u.rhs()}),620			// Self::ExprSlice(s) => {621			// 	p!(new: {s.expr()} {s.slice_desc()})622			// }623			// Self::ExprIndex(i) => {624			// 	p!(new: {i.expr()} str(".") {i.index()})625			// }626			// Self::ExprIndexExpr(i) => p!(new: {i.base()} str("[") {i.index()} str("]")),627			// Self::ExprApply(a) => {628			// 	let mut pi = p!(new: {a.expr()} {a.args_desc()});629			// 	if a.tailstrict_kw_token().is_some() {630			// 		p!(out,str(" tailstrict"));631			// 	}632			// 	pi633			// }634			Self::ExprObjExtend(ex) => {635				p!(out, {ex.lhs_work()} str(" ") {ex.rhs_work()})636			}637			Self::ExprParened(p) => {638				p!(out, str("(") {p.expr()} str(")"))639			}640			Self::ExprString(s) => p!(out, { s.text() }),641			Self::ExprNumber(n) => p!(out, { n.number() }),642			Self::ExprArray(a) => {643				p!(out, str("[") >i nl);644				for el in a.exprs() {645					p!(out, {el} str(",") nl);646				}647				p!(out, <i str("]"));648			}649			Self::ExprObject(obj) => {650				p!(out, { obj.obj_body() })651			}652			Self::ExprArrayComp(arr) => {653				p!(out, str("[") {arr.expr()});654				for spec in arr.comp_specs() {655					p!(out, str(" ") {spec});656				}657				p!(out, str("]"));658			}659			Self::ExprImport(v) => {660				p!(out, {v.import_kind()} str(" ") {v.text()})661			}662			Self::ExprVar(n) => p!(out, { n.name() }),663			// Self::ExprLocal(l) => {664			// }665			Self::ExprIfThenElse(ite) => {666				p!(out, str("if ") {ite.cond()} str(" then ") {ite.then().map(|t| t.expr())});667				if ite.else_kw_token().is_some() || ite.else_().is_some() {668					p!(out, str(" else ") {ite.else_().map(|t| t.expr())})669				}670			}671			Self::ExprFunction(f) => p!(out, str("function") {f.params_desc()} nl {f.expr()}),672			// Self::ExprAssert(a) => p!(new: {a.assertion()} str("; ") {a.expr()}),673			Self::ExprError(e) => p!(out, str("error ") {e.expr()}),674			Self::ExprLiteral(l) => {675				p!(out, { l.literal() })676			}677		}678	}679}680681impl Printable for SourceFile {682	fn print(&self, out: &mut PrintItems) {683		let before = trivia_before(684			self.syntax().clone(),685			self.expr()686				.map(|e| e.syntax().clone())687				.map(Into::into)688				.as_ref(),689		);690		let after = trivia_after(691			self.syntax().clone(),692			self.expr()693				.map(|e| e.syntax().clone())694				.map(Into::into)695				.as_ref(),696		);697		format_comments(&before, CommentLocation::AboveItem, out);698		p!(out, {self.expr()} nl);699		format_comments(&after, CommentLocation::EndOfItems, out)700	}701}702703struct FormatOptions {704	// 0 for hard tabs705	indent: u8,706}707fn format(input: &str, opts: &FormatOptions) -> Option<String> {708	let (parsed, errors) = jrsonnet_rowan_parser::parse(input);709	if !errors.is_empty() {710		let mut builder = hi_doc::SnippetBuilder::new(input);711		for error in errors {712			builder713				.error(hi_doc::Text::single(714					format!("{:?}", error.error).chars(),715					Default::default(),716				))717				.range(718					error.range.start().into()719						..=(usize::from(error.range.end()) - 1).max(error.range.start().into()),720				)721				.build();722		}723		let snippet = builder.build();724		let ansi = hi_doc::source_to_ansi(&snippet);725		eprintln!("{ansi}");726		// It is possible to recover from this failure, but the output may be broken, as formatter is free to skip727		// ERROR rowan nodes.728		// Recovery needs to be enabled for LSP, though.729		//730		// TODO: Verify how formatter interacts in cases of missing positional values, i.e `if cond then /*missing Expr*/ else residual`.731		return None;732	}733	Some(dprint_core::formatting::format(734		|| {735			let mut out = PrintItems::new();736			parsed.print(&mut out);737			out738		},739		PrintOptions {740			indent_width: if opts.indent == 0 {741				// Reasonable max length for both 2 and 4 space sized tabs.742				3743			} else {744				opts.indent745			},746			max_width: 100,747			use_tabs: opts.indent == 0,748			new_line_text: "\n",749		},750	))751}752753#[derive(Parser)]754struct Opts {755	/// Treat input as code, reformat it instead of reading file.756	#[clap(long, short = 'e')]757	exec: bool,758	/// Path to be reformatted if `--exec` if unset, otherwise code itself.759	input: String,760	/// Replace code with formatted in-place, instead of printing it to stdout.761	/// Only applicable if `--exec` is unset.762	#[clap(long, short = 'i')]763	in_place: bool,764765	/// Exit with error if formatted does not match input766	#[arg(long)]767	test: bool,768	/// Number of spaces to indent with769	///770	/// 0 for guess from input (default), and use hard tabs if unable to guess.771	#[arg(long, default_value = "0")]772	indent: u8,773	/// Force hard tab for indentation774	#[arg(long)]775	hard_tabs: bool,776777	/// Debug option: how many times to call reformatting in case of unstable dprint output resolution.778	///779	/// 0 for not retrying to reformat.780	#[arg(long, default_value = "0")]781	conv_limit: usize,782}783784#[derive(thiserror::Error, Debug)]785enum Error {786	#[error("--in-place is incompatible with --exec")]787	InPlaceExec,788	#[error("io: {0}")]789	Io(#[from] io::Error),790	#[error("persist: {0}")]791	Persist(#[from] tempfile::PersistError),792	#[error("parsing failed, refusing to reformat corrupted input")]793	Parse,794}795796fn main_result() -> Result<(), Error> {797	eprintln!("jrsonnet-fmt is a prototype of a jsonnet code formatter, do not expect it to produce meaningful results right now.");798	eprintln!("It is not expected for its output to match other implementations, it will be completly separate implementation with maybe different name.");799	let mut opts = Opts::parse();800	let input = if opts.exec {801		if opts.in_place {802			return Err(Error::InPlaceExec);803		}804		opts.input.clone()805	} else {806		fs::read_to_string(&opts.input)?807	};808809	if opts.indent == 0 {810		// Sane default.811		// TODO: Implement actual guessing.812		opts.hard_tabs = true;813	}814815	let mut iteration = 0;816	let mut formatted = input.clone();817	let mut tmp;818	// https://github.com/dprint/dprint/pull/423819	loop {820		let Some(reformatted) = format(821			&formatted,822			&FormatOptions {823				indent: if opts.indent == 0 || opts.hard_tabs {824					0825				} else {826					opts.indent827				},828			},829		) else {830			return Err(Error::Parse);831		};832		tmp = reformatted.trim().to_owned();833		if formatted == tmp {834			break;835		}836		formatted = tmp;837		if opts.conv_limit == 0 {838			break;839		}840		iteration += 1;841		if iteration > opts.conv_limit {842			panic!("formatting not converged");843		}844	}845	formatted.push('\n');846	if opts.test && formatted != input {847		process::exit(1);848	}849	if opts.in_place {850		let path = PathBuf::from(opts.input);851		let mut temp = tempfile::NamedTempFile::new_in(path.parent().expect(852			"not failed during read, this path is not a directory, and there is a parent",853		))?;854		temp.write_all(formatted.as_bytes())?;855		temp.flush()?;856		temp.persist(&path)?;857	} else {858		print!("{formatted}")859	}860	Ok(())861}862863fn main() {864	if let Err(e) = main_result() {865		eprintln!("{e}");866		process::exit(1);867	}868}
modifiedcrates/jrsonnet-rowan-parser/src/lex.rsdiffbeforeafterboth
--- a/crates/jrsonnet-rowan-parser/src/lex.rs
+++ b/crates/jrsonnet-rowan-parser/src/lex.rs
@@ -37,9 +37,10 @@
 			// In kinds, string blocks is parsed at least as `|||`
 			lexer.bump(3);
 			let res = lex_str_block(&mut lexer);
-			debug_assert!(lexer.next().is_none(), "str_block is lexed");
+			let next = lexer.next();
+			assert!(next.is_none(), "str_block is lexed");
 			match res {
-				Ok(_) => {}
+				Ok(()) => {}
 				Err(e) => {
 					kind = Ok(match e {
 						StringBlockError::UnexpectedEnd => ERROR_STRING_BLOCK_UNEXPECTED_END,
@@ -48,7 +49,7 @@
 							ERROR_STRING_BLOCK_MISSING_TERMINATION
 						}
 						StringBlockError::MissingIndent => ERROR_STRING_BLOCK_MISSING_INDENT,
-					})
+					});
 				}
 			}
 		}
modifiedcrates/jrsonnet-rowan-parser/src/marker.rsdiffbeforeafterboth
--- a/crates/jrsonnet-rowan-parser/src/marker.rs
+++ b/crates/jrsonnet-rowan-parser/src/marker.rs
@@ -146,7 +146,7 @@
 		p: &mut Parser,
 		kind: SyntaxKind,
 		error: Option<SyntaxError>,
-	) -> CompletedMarker {
+	) -> Self {
 		let new_m = p.start();
 		match &mut p.events[self.start_event_idx] {
 			Event::Start { forward_parent, .. } => {
@@ -173,10 +173,10 @@
 		}
 		completed
 	}
-	pub fn wrap(self, p: &mut Parser, kind: SyntaxKind) -> CompletedMarker {
+	pub fn wrap(self, p: &mut Parser, kind: SyntaxKind) -> Self {
 		self.wrap_raw(p, kind, None)
 	}
-	pub fn wrap_error(self, p: &mut Parser, msg: impl AsRef<str>) -> CompletedMarker {
+	pub fn wrap_error(self, p: &mut Parser, msg: impl AsRef<str>) -> Self {
 		self.wrap_raw(
 			p,
 			SyntaxKind::ERROR_CUSTOM,
modifiedcrates/jrsonnet-rowan-parser/src/parser.rsdiffbeforeafterboth
--- a/crates/jrsonnet-rowan-parser/src/parser.rs
+++ b/crates/jrsonnet-rowan-parser/src/parser.rs
@@ -72,9 +72,9 @@
 			.rev()
 			.take_while(|h| h.0 > self.entered)
 			.count();
-		self.hints.truncate(self.hints.len() - amount)
+		self.hints.truncate(self.hints.len() - amount);
 	}
-	fn clear_expected_syntaxes(&mut self) {
+	fn clear_expected_syntaxes(&self) {
 		self.expected_syntax_tracking_state
 			.set(ExpectedSyntax::Unnamed(TS![]));
 	}
@@ -104,7 +104,7 @@
 	}
 
 	pub(crate) fn expect(&mut self, kind: SyntaxKind) {
-		self.expect_with_recovery_set(kind, TS![])
+		self.expect_with_recovery_set(kind, TS![]);
 	}
 
 	pub(crate) fn expect_with_recovery_set(
@@ -153,7 +153,7 @@
 		m
 	}
 	fn bump_assert(&mut self, kind: SyntaxKind) {
-		assert!(self.at(kind), "expected {:?}", kind);
+		assert!(self.at(kind), "expected {kind:?}");
 		self.bump_remap(self.current());
 	}
 	fn bump(&mut self) {
@@ -168,11 +168,11 @@
 	fn step(&self) {
 		use std::fmt::Write;
 		let steps = self.steps.get();
-		if steps >= 15000000 {
+		if steps >= 15_000_000 {
 			let mut out = "seems like parsing is stuck".to_owned();
 			{
 				let last = 20;
-				write!(out, "\n\nLast {} events:", last).unwrap();
+				write!(out, "\n\nLast {last} events:").unwrap();
 				for (i, event) in self
 					.events
 					.iter()
@@ -205,38 +205,38 @@
 		self.nth(0)
 	}
 	#[must_use]
-	pub(crate) fn expected_syntax_name(&mut self, name: &'static str) -> ExpectedSyntaxGuard {
+	pub(crate) fn expected_syntax_name(&self, name: &'static str) -> ExpectedSyntaxGuard {
 		self.expected_syntax_tracking_state
 			.set(ExpectedSyntax::Named(name));
 
 		ExpectedSyntaxGuard::new(Rc::clone(&self.expected_syntax_tracking_state))
 	}
-	pub fn at(&mut self, kind: SyntaxKind) -> bool {
+	pub fn at(&self, kind: SyntaxKind) -> bool {
 		self.nth_at(0, kind)
 	}
-	pub fn nth_at(&mut self, n: usize, kind: SyntaxKind) -> bool {
+	pub fn nth_at(&self, n: usize, kind: SyntaxKind) -> bool {
 		if n == 0 {
 			if let ExpectedSyntax::Unnamed(kinds) = self.expected_syntax_tracking_state.get() {
 				let kinds = kinds.with(kind);
 				self.expected_syntax_tracking_state
-					.set(ExpectedSyntax::Unnamed(kinds))
+					.set(ExpectedSyntax::Unnamed(kinds));
 			}
 		}
 		self.nth(n) == kind
 	}
-	pub fn at_ts(&mut self, set: SyntaxKindSet) -> bool {
+	pub fn at_ts(&self, set: SyntaxKindSet) -> bool {
 		if let ExpectedSyntax::Unnamed(kinds) = self.expected_syntax_tracking_state.get() {
 			let kinds = kinds.union(set);
 			self.expected_syntax_tracking_state
-				.set(ExpectedSyntax::Unnamed(kinds))
+				.set(ExpectedSyntax::Unnamed(kinds));
 		}
 		set.contains(self.current())
 	}
-	pub fn at_end(&mut self) -> bool {
+	pub fn at_end(&self) -> bool {
 		self.at(EOF)
 	}
 }
-pub(crate) struct ExpectedSyntaxGuard {
+pub struct ExpectedSyntaxGuard {
 	expected_syntax_tracking_state: Rc<Cell<ExpectedSyntax>>,
 }
 
@@ -263,8 +263,8 @@
 impl fmt::Display for ExpectedSyntax {
 	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 		match self {
-			ExpectedSyntax::Named(name) => write!(f, "{name}"),
-			ExpectedSyntax::Unnamed(set) => write!(f, "{set}"),
+			Self::Named(name) => write!(f, "{name}"),
+			Self::Unnamed(set) => write!(f, "{set}"),
 		}
 	}
 }
@@ -298,8 +298,7 @@
 		}
 	}
 	match expr_binding_power(p, 0) {
-		Ok(m) => m,
-		Err(m) => m,
+		Ok(m) | Err(m) => m,
 	};
 	m.complete(p, EXPR)
 }
@@ -399,7 +398,7 @@
 }
 fn visibility(p: &mut Parser) {
 	if p.at_ts(TS![: :: :::]) {
-		p.bump()
+		p.bump();
 	} else {
 		p.error_with_recovery_set(TS![=]);
 	}
@@ -556,7 +555,7 @@
 			expr(p);
 			let arg = m.complete(p, ARG);
 			if started_named.get() {
-				unnamed_after_named.push(arg)
+				unnamed_after_named.push(arg);
 			}
 		}
 		if comma(p) {
@@ -566,7 +565,7 @@
 	}
 	p.expect(T![')']);
 	if p.at(T![tailstrict]) {
-		p.bump()
+		p.bump();
 	}
 
 	for errored in unnamed_after_named {
@@ -719,7 +718,7 @@
 	let m = p.start();
 	p.bump_assert(T![...]);
 	if p.at(IDENT) {
-		p.bump()
+		p.bump();
 	}
 	m.complete(p, DESTRUCT_REST);
 }
modifiedcrates/jrsonnet-rowan-parser/src/precedence.rsdiffbeforeafterboth
--- a/crates/jrsonnet-rowan-parser/src/precedence.rs
+++ b/crates/jrsonnet-rowan-parser/src/precedence.rs
@@ -13,8 +13,7 @@
 			Self::BitXor => (8, 9),
 			Self::BitOr => (6, 7),
 			Self::And => (4, 5),
-			Self::NullCoaelse => (2, 3),
-			Self::Or => (2, 3),
+			Self::NullCoaelse | Self::Or => (2, 3),
 			Self::ErrorNoOperator => (0, 1),
 		}
 	}
@@ -23,9 +22,7 @@
 impl UnaryOperatorKind {
 	pub fn binding_power(&self) -> ((), u8) {
 		match self {
-			Self::Minus => ((), 20),
-			Self::Not => ((), 20),
-			Self::BitNot => ((), 20),
+			Self::Minus | Self::Not | Self::BitNot => ((), 20),
 		}
 	}
 }
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
@@ -17,6 +17,7 @@
 	let _ = lex_str_block(lex);
 }
 
+#[allow(clippy::too_many_lines)]
 pub fn lex_str_block(lex: &mut Lexer<SyntaxKind>) -> Result<(), StringBlockError> {
 	struct Context<'a> {
 		source: &'a str,
@@ -78,6 +79,7 @@
 			};
 		}
 
+		#[allow(clippy::range_plus_one)]
 		fn pos(&self) -> Range<usize> {
 			if self.index == self.source.len() {
 				self.offset + self.index..self.offset + self.index
@@ -120,8 +122,7 @@
 		let end_index = ctx
 			.rest()
 			.find("|||")
-			.map(|v| v + 3)
-			.unwrap_or_else(|| ctx.rest().len());
+			.map_or_else(|| ctx.rest().len(), |v| v + 3);
 		lex.bump(ctx.index + end_index);
 	}
 
@@ -150,7 +151,7 @@
 	}
 
 	// Process leading blank lines before calculating string block indent
-	while let Some('\n') = ctx.peek() {
+	while ctx.peek() == Some('\n') {
 		ctx.next();
 	}
 
@@ -179,7 +180,7 @@
 		}
 
 		// Skip any blank lines
-		while let Some('\n') = ctx.peek() {
+		while ctx.peek() == Some('\n') {
 			ctx.next();
 		}
 
@@ -187,9 +188,11 @@
 		num_whitespace = check_whitespace(str_block_indent, ctx.rest());
 		if num_whitespace == 0 {
 			// End of the text block
-			let mut term_indent = String::with_capacity(num_whitespace);
+			// let mut term_indent = String::with_capacity(num_whitespace);
 			while let Some(' ' | '\t') = ctx.peek() {
-				term_indent.push(ctx.next().unwrap());
+				// term_indent.push(
+				ctx.next().unwrap();
+				// );
 			}
 
 			if !ctx.rest().starts_with("|||") {
modifiedcrates/jrsonnet-rowan-parser/src/token_set.rsdiffbeforeafterboth
--- a/crates/jrsonnet-rowan-parser/src/token_set.rs
+++ b/crates/jrsonnet-rowan-parser/src/token_set.rs
@@ -10,21 +10,23 @@
 	pub const EMPTY: Self = Self(0);
 	pub const ALL: Self = Self(u128::MAX);
 
-	pub const fn new(kinds: &[SyntaxKind]) -> SyntaxKindSet {
+	pub const fn new(kinds: &[SyntaxKind]) -> Self {
 		let mut res = 0u128;
 		let mut i = 0;
 		while i < kinds.len() {
 			res |= mask(kinds[i]);
-			i += 1
+			i += 1;
 		}
-		SyntaxKindSet(res)
+		Self(res)
 	}
 
-	pub const fn union(self, other: SyntaxKindSet) -> SyntaxKindSet {
-		SyntaxKindSet(self.0 | other.0)
+	#[must_use]
+	pub const fn union(self, other: Self) -> Self {
+		Self(self.0 | other.0)
 	}
-	pub const fn with(self, kind: SyntaxKind) -> SyntaxKindSet {
-		SyntaxKindSet(self.0 | mask(kind))
+	#[must_use]
+	pub const fn with(self, kind: SyntaxKind) -> Self {
+		Self(self.0 | mask(kind))
 	}
 
 	pub fn contains(&self, kind: SyntaxKind) -> bool {
@@ -40,7 +42,7 @@
 		let mut variants = <Vec<SyntaxKind>>::new();
 		for i in 0..128 {
 			if v & 1 == 1 {
-				variants.push(SyntaxKind::from_raw(i))
+				variants.push(SyntaxKind::from_raw(i));
 			}
 			v >>= 1;
 			if v == 0 {
@@ -65,7 +67,7 @@
 		let mut variants = <Vec<SyntaxKind>>::new();
 		for i in 0..128 {
 			if v & 1 == 1 {
-				variants.push(SyntaxKind::from_raw(i))
+				variants.push(SyntaxKind::from_raw(i));
 			}
 			v >>= 1;
 			if v == 0 {
@@ -77,9 +79,7 @@
 }
 
 const fn mask(kind: SyntaxKind) -> u128 {
-	if kind as u32 > 128 {
-		panic!("mask for not a token kind")
-	}
+	assert!(kind as u32 <= 128, "mask for not a token kind");
 	1u128 << (kind as u128)
 }
 
modifiedxtask/src/sourcegen/ast.rsdiffbeforeafterboth
--- a/xtask/src/sourcegen/ast.rs
+++ b/xtask/src/sourcegen/ast.rs
@@ -72,7 +72,7 @@
 	pub fn is_many(&self) -> bool {
 		matches!(
 			self,
-			Field::Node {
+			Self::Node {
 				cardinality: Cardinality::Many,
 				..
 			}
@@ -81,44 +81,41 @@
 
 	pub fn token_name(&self) -> Option<String> {
 		match self {
-			Field::Token(token) => Some(token.clone()),
-			_ => None,
+			Self::Token(token) => Some(token.clone()),
+			Self::Node { .. } => None,
 		}
 	}
 	pub fn token_kind(&self, kinds: &KindsSrc) -> Option<TokenStream> {
 		match self {
-			Field::Token(token) => Some(kinds.token(token).expect("token exists").reference()),
-			_ => None,
+			Self::Token(token) => Some(kinds.token(token).expect("token exists").reference()),
+			Self::Node { .. } => None,
 		}
 	}
 	pub fn is_token_enum(&self, grammar: &AstSrc) -> bool {
 		match self {
-			Field::Node { ty, .. } => grammar.token_enums.iter().any(|e| &e.name == ty),
-			_ => false,
+			Self::Node { ty, .. } => grammar.token_enums.iter().any(|e| &e.name == ty),
+			Self::Token(_) => false,
 		}
 	}
 
 	pub fn method_name(&self, kinds: &KindsSrc) -> proc_macro2::Ident {
 		match self {
-			Field::Token(name) => kinds.token(name).expect("token exists").method_name(),
-			Field::Node { name, .. } => {
+			Self::Token(name) => kinds.token(name).expect("token exists").method_name(),
+			Self::Node { name, .. } => {
 				format_ident!("{}", name)
 			}
 		}
 	}
 	pub fn ty(&self) -> proc_macro2::Ident {
 		match self {
-			Field::Token(_) => format_ident!("SyntaxToken"),
-			Field::Node { ty, .. } => format_ident!("{}", ty),
+			Self::Token(_) => format_ident!("SyntaxToken"),
+			Self::Node { ty, .. } => format_ident!("{}", ty),
 		}
 	}
 }
 
 pub fn lower(kinds: &KindsSrc, grammar: &Grammar) -> AstSrc {
-	let mut res = AstSrc {
-		// tokens,
-		..Default::default()
-	};
+	let mut res = AstSrc::default();
 
 	let nodes = grammar.iter().collect::<Vec<_>>();
 
@@ -135,16 +132,15 @@
 				};
 				res.enums.push(enum_src);
 			}
-			None => match lower_token_enum(grammar, rule) {
-				Some(variants) => {
+			None => {
+				if let Some(variants) = lower_token_enum(grammar, rule) {
 					let tokens_enum_src = AstTokenEnumSrc {
 						doc: Vec::new(),
 						name,
 						variants,
 					};
 					res.token_enums.push(tokens_enum_src);
-				}
-				None => {
+				} else {
 					let mut fields = Vec::new();
 					lower_rule(&mut fields, grammar, None, rule, false);
 					let mut types = HashMap::new();
@@ -173,7 +169,7 @@
 						fields,
 					});
 				}
-			},
+			}
 		}
 	}
 
@@ -240,7 +236,7 @@
 			acc.push(field);
 		}
 		Rule::Token(token) => {
-			assert!(label.is_none(), "uexpected label: {:?}", label);
+			assert!(label.is_none(), "uexpected label: {label:?}");
 			let name = grammar[*token].name.clone();
 			let field = Field::Token(name);
 			acc.push(field);
@@ -267,7 +263,7 @@
 		}
 		Rule::Seq(rules) | Rule::Alt(rules) => {
 			for rule in rules {
-				lower_rule(acc, grammar, label, rule, in_optional)
+				lower_rule(acc, grammar, label, rule, in_optional);
 			}
 		}
 		Rule::Opt(rule) => lower_rule(acc, grammar, label, rule, true),
modifiedxtask/src/sourcegen/kinds.rsdiffbeforeafterboth
--- a/xtask/src/sourcegen/kinds.rs
+++ b/xtask/src/sourcegen/kinds.rs
@@ -41,33 +41,33 @@
 impl TokenKind {
 	pub fn grammar_name(&self) -> &str {
 		match self {
-			TokenKind::Keyword { code, .. } => code,
-			TokenKind::Literal { grammar_name, .. } => grammar_name,
-			TokenKind::Meta { grammar_name, .. } => grammar_name,
-			TokenKind::Error { grammar_name, .. } => grammar_name,
+			Self::Keyword { code, .. } => code,
+			Self::Literal { grammar_name, .. }
+			| Self::Meta { grammar_name, .. }
+			| Self::Error { grammar_name, .. } => grammar_name,
 		}
 	}
 	/// How this keyword should appear in kinds enum, screaming snake cased
 	pub fn name(&self) -> &str {
 		match self {
-			TokenKind::Keyword { name, .. } => name,
-			TokenKind::Literal { name, .. } => name,
-			TokenKind::Meta { name, .. } => name,
-			TokenKind::Error { name, .. } => name,
+			Self::Keyword { name, .. }
+			| Self::Literal { name, .. }
+			| Self::Meta { name, .. }
+			| Self::Error { name, .. } => name,
 		}
 	}
 	pub fn expand_kind(&self) -> TokenStream {
 		let name = format_ident!("{}", self.name());
 		let attr = match self {
-			TokenKind::Keyword { code, .. } => quote! {#[token(#code)]},
-			TokenKind::Literal { regex, lexer, .. } => {
+			Self::Keyword { code, .. } => quote! {#[token(#code)]},
+			Self::Literal { regex, lexer, .. } => {
 				let lexer = lexer
 					.as_deref()
 					.map(TokenStream::from_str)
 					.map(|r| r.expect("path is correct"));
 				quote! {#[regex(#regex, #lexer)]}
 			}
-			TokenKind::Error {
+			Self::Error {
 				regex, priority, ..
 			} if regex.is_some() => {
 				let priority = priority.map(|p| quote! {, priority = #p});
@@ -82,7 +82,7 @@
 	}
 	pub fn expand_t_macros(&self) -> Option<TokenStream> {
 		match self {
-			TokenKind::Keyword { code, name } => {
+			Self::Keyword { code, name } => {
 				let code = escape_token_macro(code);
 				let name = format_ident!("{name}");
 				Some(quote! {
@@ -98,29 +98,26 @@
 	/// Keywords are referenced with `T![_]` macro,
 	/// and literals are referenced directly by name
 	pub fn reference(&self) -> TokenStream {
-		match self {
-			TokenKind::Keyword { code, .. } => {
-				let code = escape_token_macro(code);
-				quote! {T![#code]}
-			}
-			_ => {
-				let name = self.name();
-				let ident = format_ident!("{name}");
-				quote! {#ident}
-			}
+		if let Self::Keyword { code, .. } = self {
+			let code = escape_token_macro(code);
+			quote! {T![#code]}
+		} else {
+			let name = self.name();
+			let ident = format_ident!("{name}");
+			quote! {#ident}
 		}
 	}
 
 	pub fn method_name(&self) -> Ident {
 		match self {
-			TokenKind::Keyword { name, .. } => {
+			Self::Keyword { name, .. } => {
 				format_ident!("{}_token", name.to_lowercase())
 			}
-			TokenKind::Literal { name, .. } => {
+			Self::Literal { name, .. } => {
 				format_ident!("{}_lit", name.to_lowercase())
 			}
-			TokenKind::Meta { name, .. } => format_ident!("{}_meta", name.to_lowercase()),
-			TokenKind::Error { name, .. } => format_ident!("{}_error", name.to_lowercase()),
+			Self::Meta { name, .. } => format_ident!("{}_meta", name.to_lowercase()),
+			Self::Error { name, .. } => format_ident!("{}_error", name.to_lowercase()),
 		}
 	}
 }
@@ -188,15 +185,14 @@
 				.is_none(),
 			"token already defined: {}",
 			token.grammar_name()
-		)
+		);
 	}
 	pub fn define_node(&mut self, node: &str) {
 		assert!(
 			self.defined_node_names.insert(node.to_owned()),
-			"node name already defined: {}",
-			node
+			"node name already defined: {node}"
 		);
-		self.nodes.push(node.to_string())
+		self.nodes.push(node.to_string());
 	}
 	pub fn token(&self, tok: &str) -> Option<&TokenKind> {
 		self.defined_tokens.get(tok)
modifiedxtask/src/sourcegen/mod.rsdiffbeforeafterboth
--- a/xtask/src/sourcegen/mod.rs
+++ b/xtask/src/sourcegen/mod.rs
@@ -49,27 +49,27 @@
 				match special {
 					SpecialName::Literal => panic!("literal is not defined: {name}"),
 					SpecialName::Meta => {
-						eprintln!("implicit meta: {}", name);
+						eprintln!("implicit meta: {name}");
 						kinds.define_token(TokenKind::Meta {
 							grammar_name: token.to_owned(),
-							name: format!("META_{}", name),
-						})
+							name: format!("META_{name}"),
+						});
 					}
 					SpecialName::Error => {
-						eprintln!("implicit error: {}", name);
+						eprintln!("implicit error: {name}");
 						kinds.define_token(TokenKind::Error {
 							grammar_name: token.to_owned(),
-							name: format!("ERROR_{}", name),
+							name: format!("ERROR_{name}"),
 							regex: None,
 							priority: None,
 							is_lexer_error: true,
-						})
+						});
 					}
 				};
 				continue;
 			};
 			let name = to_upper_snake_case(token);
-			eprintln!("implicit kw: {}", token);
+			eprintln!("implicit kw: {token}");
 			kinds.define_token(TokenKind::Keyword {
 				code: token.to_owned(),
 				name: format!("{name}_KW"),
@@ -98,14 +98,14 @@
 			"/../crates/jrsonnet-rowan-parser/src/generated/syntax_kinds.rs",
 		)),
 		&syntax_kinds,
-	)?;
+	);
 	ensure_file_contents(
 		&PathBuf::from(concat!(
 			env!("CARGO_MANIFEST_DIR"),
 			"/../crates/jrsonnet-rowan-parser/src/generated/nodes.rs",
 		)),
 		&nodes,
-	)?;
+	);
 	Ok(())
 }
 
@@ -189,6 +189,7 @@
 	reformat(&ast.to_string())
 }
 
+#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
 fn generate_nodes(kinds: &KindsSrc, grammar: &AstSrc) -> Result<String> {
 	let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
 		.nodes
@@ -524,7 +525,7 @@
 fn write_doc_comment(contents: &[String], dest: &mut String) {
 	use std::fmt::Write;
 	for line in contents {
-		writeln!(dest, "///{}", line).unwrap();
+		writeln!(dest, "///{line}").unwrap();
 	}
 }
 
modifiedxtask/src/sourcegen/util.rsdiffbeforeafterboth
--- a/xtask/src/sourcegen/util.rs
+++ b/xtask/src/sourcegen/util.rs
@@ -1,3 +1,5 @@
+// FIXME: Replace various helper here with inflector?
+
 use std::{fs, path::Path};
 
 use anyhow::Result;
@@ -5,11 +7,11 @@
 
 /// Checks that the `file` has the specified `contents`. If that is not the
 /// case, updates the file and then fails the test.
-pub fn ensure_file_contents(file: &Path, contents: &str) -> Result<()> {
+pub fn ensure_file_contents(file: &Path, contents: &str) {
 	if let Ok(old_contents) = fs::read_to_string(file) {
 		if normalize_newlines(&old_contents) == normalize_newlines(contents) {
 			// File is already up to date.
-			return Ok(());
+			return;
 		}
 	}
 
@@ -18,7 +20,6 @@
 		let _ = fs::create_dir_all(parent);
 	}
 	fs::write(file, contents).unwrap();
-	Ok(())
 }
 
 // Eww, someone configured git to use crlf?
@@ -26,8 +27,9 @@
 	s.replace("\r\n", "\n")
 }
 
-pub(crate) fn pluralize(s: &str) -> String {
-	format!("{}s", s)
+pub fn pluralize(s: &str) -> String {
+	// FIXME: Inflector?
+	format!("{s}s")
 }
 
 pub fn to_upper_snake_case(s: &str) -> String {
@@ -35,7 +37,7 @@
 	let mut prev = false;
 	for c in s.chars() {
 		if c.is_ascii_uppercase() && prev {
-			buf.push('_')
+			buf.push('_');
 		}
 		prev = true;
 
@@ -48,7 +50,7 @@
 	let mut prev = false;
 	for c in s.chars() {
 		if c.is_ascii_uppercase() && prev {
-			buf.push('_')
+			buf.push('_');
 		}
 		prev = true;