difftreelog
style fix clippy warnings
in: master
24 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -676,18 +676,18 @@
[[package]]
name = "jrsonnet-gcmodule"
-version = "0.4.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c33f4f6cdc60f5ae94ebae3dfe7f484ae79b364225d9b19601b24c804cfd8751"
+checksum = "f95b976a79e4000bb9e07ff0709dca0ea27bcf1952d4c17d91fb7364d6145683"
dependencies = [
"jrsonnet-gcmodule-derive",
]
[[package]]
name = "jrsonnet-gcmodule-derive"
-version = "0.4.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b30c95b285f9bb6709f1b3e6fc69b3a25e39b32ff987587fd108f0f22be5fa3"
+checksum = "51d928626220a310ff0cec815e80cf7fe104697184352ca21c40534e0b0d72d9"
dependencies = [
"proc-macro2",
"quote",
@@ -1602,7 +1602,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
- "windows-sys 0.59.0",
+ "windows-sys 0.61.2",
]
[[package]]
Cargo.tomldiffbeforeafterboth--- a/Cargo.toml
+++ b/Cargo.toml
@@ -20,7 +20,7 @@
jrsonnet-cli = { path = "./crates/jrsonnet-cli", version = "0.5.0-pre97" }
jrsonnet-types = { path = "./crates/jrsonnet-types", version = "0.5.0-pre97" }
jrsonnet-formatter = { path = "./crates/jrsonnet-formatter", version = "0.5.0-pre97" }
-jrsonnet-gcmodule = { version = "0.4.1" }
+jrsonnet-gcmodule = { version = "0.4.2" }
# Diagnostics.
# hi-doc is my library, which handles text formatting very well, but isn't polished enough yet
# Previous implementation was based on annotate-snippets, which I don't like for many reasons.
bindings/jsonnet/src/import.rsdiffbeforeafterboth--- a/bindings/jsonnet/src/import.rs
+++ b/bindings/jsonnet/src/import.rs
@@ -66,8 +66,8 @@
base.as_ptr(),
rel.as_ptr(),
&mut found_here.cast_const(),
- &mut buf,
- &mut buf_len,
+ &raw mut buf,
+ &raw mut buf_len,
)
};
let buf_slice: &[u8] = unsafe { std::slice::from_raw_parts(buf.cast(), buf_len) };
crates/jrsonnet-evaluator/src/evaluate/destructure.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/destructure.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/destructure.rs
@@ -9,6 +9,9 @@
evaluate_method, evaluate_named_param, Context, Pending, Thunk, Val,
};
+#[cfg(feature = "exp-preserve-order")]
+use crate::evaluate;
+
#[allow(clippy::too_many_lines)]
#[allow(unused_variables)]
pub fn destruct<H: BuildHasher>(
crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -143,7 +143,7 @@
false,
) {
let fctx = Pending::new();
- let mut new_bindings = FxHashMap::with_capacity(var.capacity_hint());
+ let mut new_bindings = FxHashMap::with_capacity(var.binds_len());
let obj = obj.clone();
let value = Thunk::evaluated(Val::Arr(ArrValue::lazy(vec![
Thunk::evaluated(Val::string(field.clone())),
crates/jrsonnet-evaluator/src/function/builtin.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function/builtin.rs
+++ b/crates/jrsonnet-evaluator/src/function/builtin.rs
@@ -98,9 +98,9 @@
fn call(&self, _loc: CallLocation<'_>, args: &[Option<Thunk<Val>>]) -> Result<Val> {
let args = args
- .into_iter()
+ .iter()
.map(|a| a.as_ref().expect("legacy natives have no default params"))
- .map(|a| a.evaluate())
+ .map(Thunk::evaluate)
.collect::<Result<Vec<Val>>>()?;
self.handler.call(&args)
}
crates/jrsonnet-evaluator/src/obj/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/obj/mod.rs
+++ b/crates/jrsonnet-evaluator/src/obj/mod.rs
@@ -1,12 +1,5 @@
use std::{
- any::Any,
- cell::{Cell, RefCell},
- clone::Clone,
- collections::hash_map::Entry,
- fmt::{self, Debug},
- hash::{Hash, Hasher},
- num::Saturating,
- ops::ControlFlow,
+ any::Any, cell::{Cell, RefCell}, clone::Clone, cmp::Reverse, collections::hash_map::Entry, fmt::{self, Debug}, hash::{Hash, Hasher}, num::Saturating, ops::ControlFlow
};
use educe::Educe;
@@ -39,18 +32,19 @@
use jrsonnet_gcmodule::Trace;
- #[derive(Clone, Copy, Default, Debug, Trace)]
+ #[derive(Clone, Copy, Default, Debug, Trace, PartialEq, Eq, PartialOrd, Ord)]
pub struct FieldIndex(());
impl FieldIndex {
pub fn absolute(_v: u32) -> Self {
Self(())
}
+ #[must_use]
pub const fn next(self) -> Self {
Self(())
}
}
- #[derive(Clone, Copy, Default, Debug, Trace)]
+ #[derive(Clone, Copy, Default, Debug, Trace, PartialEq, Eq, PartialOrd, Ord)]
pub struct SuperDepth(());
impl SuperDepth {
pub(super) fn deepen(self) {}
@@ -59,8 +53,6 @@
#[cfg(feature = "exp-preserve-order")]
pub mod ordering {
- use std::cmp::Reverse;
-
use jrsonnet_gcmodule::Trace;
#[derive(Clone, Copy, Default, Debug, Trace, PartialEq, Eq, PartialOrd, Ord)]
@@ -69,6 +61,7 @@
pub fn absolute(v: u32) -> Self {
Self(v)
}
+ #[must_use]
pub fn next(self) -> Self {
Self(self.0 + 1)
}
@@ -78,22 +71,20 @@
pub struct SuperDepth(u32);
impl SuperDepth {
pub(super) fn deepen(&mut self) {
- self.0 += 1
+ self.0 += 1;
}
}
+}
+
+use ordering::{FieldIndex, SuperDepth};
- #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
- pub struct FieldSortKey(Reverse<SuperDepth>, FieldIndex);
- impl FieldSortKey {
- pub fn new(depth: SuperDepth, index: FieldIndex) -> Self {
- Self(Reverse(depth), index)
- }
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
+pub struct FieldSortKey(Reverse<SuperDepth>, FieldIndex);
+impl FieldSortKey {
+ pub fn new(depth: SuperDepth, index: FieldIndex) -> Self {
+ Self(Reverse(depth), index)
}
}
-
-#[cfg(feature = "exp-preserve-order")]
-use ordering::FieldSortKey;
-use ordering::{FieldIndex, SuperDepth};
// 0 - add
// 12 - visibility
@@ -795,7 +786,7 @@
struct FieldVisibilityData {
omitted_until: Saturating<usize>,
exists_visible: Option<Visibility>,
- #[cfg(feature = "exp-preserve-order")]
+ #[allow(dead_code, reason = "used for exp-object-ordering, ZST otherwise")]
key: FieldSortKey,
}
impl FieldVisibilityData {
@@ -804,7 +795,7 @@
.expect("non-existing fields shall be dropped at the end of fn fields_visibility()")
.is_visible()
}
- #[cfg(feature = "exp-preserve-order")]
+ #[allow(dead_code, reason = "used for exp-object-ordering, ZST otherwise")]
fn sort_key(&self) -> FieldSortKey {
self.key
}
@@ -818,12 +809,11 @@
let mut omit_index = Saturating(0);
for core in self.0.cores.iter().rev() {
core.0
- .enum_fields_core(&mut super_depth, &mut |_depth, _index, name, visibility| {
+ .enum_fields_core(&mut super_depth, &mut |depth, index, name, visibility| {
let entry = out.entry(name);
- let data = entry.or_insert(FieldVisibilityData {
+ let data = entry.or_insert_with(|| FieldVisibilityData {
exists_visible: None,
- #[cfg(feature = "exp-preserve-order")]
- key: FieldSortKey::new(_depth, _index),
+ key: FieldSortKey::new(depth, index),
omitted_until: omit_index,
});
match visibility {
crates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/typed/conversions.rs
+++ b/crates/jrsonnet-evaluator/src/typed/conversions.rs
@@ -61,9 +61,16 @@
}
}
+#[diagnostic::on_unimplemented(
+ note = "don't implement `ParseTypedObj` directly, it is automatically provided by `FromUntyped` derive"
+)]
pub trait ParseTypedObj: Typed {
fn parse(obj: &ObjValue) -> Result<Self>;
}
+
+#[diagnostic::on_unimplemented(
+ note = "don't implement `SerializeTypedObj` directly, it is automatically provided by `IntoUntyped` derive"
+)]
pub trait SerializeTypedObj: Typed {
fn serialize(self, out: &mut ObjValueBuilder) -> Result<()>;
fn into_object(self) -> Result<ObjValue> {
crates/jrsonnet-formatter/src/comments.rsdiffbeforeafterboth--- a/crates/jrsonnet-formatter/src/comments.rs
+++ b/crates/jrsonnet-formatter/src/comments.rs
@@ -136,7 +136,7 @@
}
line = new_line.to_string();
}
- p!(out, string(line.to_string()) nl);
+ p!(out, string(line.clone()) nl);
}
}
if doc {
crates/jrsonnet-formatter/src/lib.rsdiffbeforeafterboth1use std::{any::type_name, rc::Rc};23use children::{children_between, trivia_before};4use dprint_core::formatting::{5 condition_helpers::is_multiple_lines,6 condition_resolvers::true_resolver,7 ir_helpers::{new_line_group, with_indent},8 ConditionResolver, ConditionResolverContext, LineNumber, PrintItems, PrintOptions,9};10use hi_doc::{Formatting, SnippetBuilder};11use jrsonnet_rowan_parser::{12 collect_lexed_str_block,13 nodes::{14 Arg, ArgsDesc, Assertion, BinaryOperator, Bind, CompSpec, Destruct, DestructArrayPart,15 DestructRest, Expr, ExprArray, ExprBase, FieldName, ForSpec, IfSpec, ImportKind, Literal,16 Member, Name, Number, ObjBody, ObjLocal, ParamsDesc, SliceDesc, SourceFile, Stmt, Suffix,17 Text, TextKind, UnaryOperator, Visibility,18 },19 AstNode, AstToken as _, SyntaxToken,20};2122use crate::{23 children::{trivia_after, Child, EndingComments},24 comments::{format_comments, CommentLocation},25};2627mod children;28mod comments;29mod tests;3031fn with_indent_eoi(cond: ConditionResolver, o: PrintItems, e: EndingComments) -> PrintItems {32 let end_comments_items = {33 let mut items = PrintItems::new();34 if e.should_start_with_newline {35 p!(&mut items, nl);36 }37 format_comments(&e.trivia, CommentLocation::EndOfItems, &mut items);38 items.into_rc_path()39 };40 let items =41 new_line_group(pi!(@i; items(o.into()) items(end_comments_items.into()))).into_rc_path();4243 let indented = with_indent(pi!(@i; nl items(items.into())));4445 pi!(@i; if_else("indented body", cond, items(indented))(str(" ") items(items.into())))46}4748pub trait Printable {49 fn print(&self, out: &mut PrintItems);50}5152macro_rules! pi {53 (@i; $($t:tt)*) => {{54 #[allow(unused_mut)]55 let mut o = dprint_core::formatting::PrintItems::new();56 pi!(@s; o: $($t)*);57 o58 }};59 (@s; $o:ident: str($e:expr $(,)?) $($t:tt)*) => {{60 $o.push_string($e.to_owned());61 pi!(@s; $o: $($t)*);62 }};63 (@s; $o:ident: string($e:expr $(,)?) $($t:tt)*) => {{64 $o.push_string($e);65 pi!(@s; $o: $($t)*);66 }};67 (@s; $o:ident: nl $($t:tt)*) => {{68 $o.push_signal(dprint_core::formatting::Signal::NewLine);69 pi!(@s; $o: $($t)*);70 }};71 (@s; $o:ident: sonl $($t:tt)*) => {{72 $o.push_signal(dprint_core::formatting::Signal::SpaceOrNewLine);73 pi!(@s; $o: $($t)*);74 }};75 (@s; $o:ident: tab $($t:tt)*) => {{76 $o.push_signal(dprint_core::formatting::Signal::Tab);77 pi!(@s; $o: $($t)*);78 }};79 (@s; $o:ident: >i $($t:tt)*) => {{80 $o.push_signal(dprint_core::formatting::Signal::StartIndent);81 pi!(@s; $o: $($t)*);82 }};83 (@s; $o:ident: <i $($t:tt)*) => {{84 $o.push_signal(dprint_core::formatting::Signal::FinishIndent);85 pi!(@s; $o: $($t)*);86 }};87 (@s; $o:ident: >ii $($t:tt)*) => {{88 $o.push_signal(dprint_core::formatting::Signal::StartIgnoringIndent);89 pi!(@s; $o: $($t)*);90 }};91 (@s; $o:ident: <ii $($t:tt)*) => {{92 $o.push_signal(dprint_core::formatting::Signal::FinishIgnoringIndent);93 pi!(@s; $o: $($t)*);94 }};95 (@s; $o:ident: info($v:expr) $($t:tt)*) => {{96 $o.push_info($v);97 pi!(@s; $o: $($t)*);98 }};99 (@s; $o:ident: ln_anchor($v:expr) $($t:tt)*) => {{100 $o.push_anchor(LineNumberAnchor::new($v));101 pi!(@s; $o: $($t)*);102 }};103 (@s; $o:ident: if($s:literal, $cond:expr, $($i:tt)*) $($t:tt)*) => {{104 $o.push_condition(dprint_core::formatting::conditions::if_true(105 $s,106 $cond.clone(),107 {108 let mut o = PrintItems::new();109 p!(o, $($i)*);110 o111 },112 ));113 pi!(@s; $o: $($t)*);114 }};115 (@s; $o:ident: if_else($s:literal, $cond:expr, $($i:tt)*)($($e:tt)+) $($t:tt)*) => {{116 $o.push_condition(dprint_core::formatting::conditions::if_true_or(117 $s,118 $cond.clone(),119 {120 let mut o = PrintItems::new();121 p!(o, $($i)*);122 o123 },124 {125 let mut o = PrintItems::new();126 p!(o, $($e)*);127 o128 },129 ));130 pi!(@s; $o: $($t)*);131 }};132 (@s; $o:ident: if_not($s:literal, $cond:expr, $($e:tt)*) $($t:tt)*) => {{133 $o.push_condition(dprint_core::formatting::conditions::if_true_or(134 $s,135 $cond.clone(),136 {137 let o = PrintItems::new();138 o139 },140 {141 let mut o = PrintItems::new();142 p!(o, $($e)*);143 o144 },145 ));146 pi!(@s; $o: $($t)*);147 }};148 (@s; $o:ident: {$expr:expr} $($t:tt)*) => {{149 $expr.print($o);150 pi!(@s; $o: $($t)*);151 }};152 (@s; $o:ident: items($expr:expr) $($t:tt)*) => {{153 $o.extend($expr);154 pi!(@s; $o: $($t)*);155 }};156 (@s; $o:ident: if ($e:expr)($($then:tt)*) $($t:tt)*) => {{157 if $e {158 pi!(@s; $o: $($then)*);159 }160 pi!(@s; $o: $($t)*);161 }};162 (@s; $o:ident: ifelse ($e:expr)($($then:tt)*)($($else:tt)*) $($t:tt)*) => {{163 if $e {164 pi!(@s; $o: $($then)*);165 } else {166 pi!(@s; $o: $($else)*);167 }168 pi!(@s; $o: $($t)*);169 }};170 (@s; $i:ident:) => {}171}172macro_rules! p {173 ($o:ident, $($t:tt)*) => {174 pi!(@s; $o: $($t)*)175 };176 (&mut $o:ident, $($t:tt)*) => {177 let om = &mut $o;178 pi!(@s; om: $($t)*)179 };180}181pub(crate) use p;182pub(crate) use pi;183184impl<P> Printable for Option<P>185where186 P: Printable,187{188 fn print(&self, out: &mut PrintItems) {189 if let Some(v) = self {190 v.print(out);191 } else {192 p!(193 out,194 string(format!(195 "/*missing {}*/",196 type_name::<P>().replace("jrsonnet_rowan_parser::generated::nodes::", "")197 ),)198 );199 }200 }201}202203impl Printable for SyntaxToken {204 fn print(&self, out: &mut PrintItems) {205 p!(out, string(self.to_string()));206 }207}208209impl Printable for Text {210 fn print(&self, out: &mut PrintItems) {211 if matches!(self.kind(), TextKind::StringBlock) {212 let text = self.text();213 let mut text = collect_lexed_str_block(&text[3..])214 .expect("formatting is not performed on code with parsing errors");215216 if text.truncate && text.lines.ends_with(&[""]) {217 text.truncate = false;218 text.lines.pop();219 }220221 p!(out, str("|||"));222 if text.truncate {223 p!(out, str("-"));224 }225 p!(out, nl > i);226 for ele in text.lines {227 if ele.is_empty() {228 p!(out, >ii nl <ii);229 } else {230 p!(out, string(ele.to_string()) nl);231 }232 }233 p!(out, <i str("|||"));234235 return;236 }237 p!(out, string(format!("{}", self)));238 }239}240impl Printable for Number {241 fn print(&self, out: &mut PrintItems) {242 p!(out, string(format!("{}", self)));243 }244}245246impl Printable for Name {247 fn print(&self, out: &mut PrintItems) {248 p!(out, { self.ident_lit() });249 }250}251252impl Printable for DestructRest {253 fn print(&self, out: &mut PrintItems) {254 p!(out, str("..."));255 if let Some(name) = self.into() {256 p!(out, { name });257 }258 }259}260261impl Printable for Destruct {262 fn print(&self, out: &mut PrintItems) {263 match self {264 Self::DestructFull(f) => {265 p!(out, { f.name() });266 }267 Self::DestructSkip(_) => p!(out, str("?")),268 Self::DestructArray(a) => {269 p!(out, str("[") >i nl);270 for el in a.destruct_array_parts() {271 match el {272 DestructArrayPart::DestructArrayElement(e) => {273 p!(out, {e.destruct()} str(",") nl);274 }275 DestructArrayPart::DestructRest(d) => {276 p!(out, {d} str(",") nl);277 }278 }279 }280 p!(out, <i str("]"));281 }282 Self::DestructObject(o) => {283 p!(out, str("{") >i nl);284 for item in o.destruct_object_fields() {285 p!(out, { item.field() });286 if let Some(des) = item.destruct() {287 p!(out, str(": ") {des});288 }289 if let Some(def) = item.expr() {290 p!(out, str(" = ") {def});291 }292 p!(out, str(",") nl);293 }294 if let Some(rest) = o.destruct_rest() {295 p!(out, {rest} nl);296 }297 p!(out, <i str("}"));298 }299 }300 }301}302303impl Printable for FieldName {304 fn print(&self, out: &mut PrintItems) {305 match self {306 Self::FieldNameFixed(f) => {307 if let Some(id) = f.id() {308 p!(out, { id });309 } else if let Some(str) = f.text() {310 p!(out, { str });311 } else {312 p!(out, str("/*missing FieldName*/"));313 }314 }315 Self::FieldNameDynamic(d) => {316 p!(out, str("[") {d.expr()} str("]"));317 }318 }319 }320}321322impl Printable for Visibility {323 fn print(&self, out: &mut PrintItems) {324 p!(out, string(self.to_string()));325 }326}327328impl Printable for ObjLocal {329 fn print(&self, out: &mut PrintItems) {330 p!(out, str("local ") {self.bind()});331 }332}333334impl Printable for Assertion {335 fn print(&self, out: &mut PrintItems) {336 p!(out, str("assert ") {self.condition()});337 if self.colon_token().is_some() || self.message().is_some() {338 p!(out, str(": ") {self.message()});339 }340 }341}342343impl Printable for ParamsDesc {344 fn print(&self, out: &mut PrintItems) {345 p!(out, str("(") >i nl);346 for param in self.params() {347 p!(out, { param.destruct() });348 if param.assign_token().is_some() || param.expr().is_some() {349 p!(out, str(" = ") {param.expr()});350 }351 p!(out, str(",") nl);352 }353 p!(out, <i str(")"));354 }355}356impl Printable for ArgsDesc {357 fn print(&self, out: &mut PrintItems) {358 let start = LineNumber::new("args start line");359 let end = LineNumber::new("args end line");360 let multi_line = Rc::new(move |condition_context: &mut ConditionResolverContext| {361 is_multiple_lines(condition_context, start, end)362 });363364 let (children, end_comments) = children_between::<Arg>(365 self.syntax().clone(),366 self.l_paren_token().map(Into::into).as_ref(),367 self.r_paren_token().map(Into::into).as_ref(),368 None,369 );370371 fn gen_args(children: Vec<Child<Arg>>, multi_line: ConditionResolver) -> PrintItems {372 let mut _out = PrintItems::new();373 let out = &mut _out;374375 let mut args = children.into_iter().peekable();376 while let Some(ele) = args.next() {377 if ele.should_start_with_newline {378 p!(out, nl);379 }380 format_comments(&ele.before_trivia, CommentLocation::AboveItem, out);381 let arg = ele.value;382 if arg.name().is_some() || arg.assign_token().is_some() {383 p!(out, {arg.name()} str(" = "));384 }385 p!(out, { arg.expr() });386 let has_more = args.peek().is_some();387 if has_more {388 p!(out, str(","));389 } else {390 p!(out, if("trailing comma", multi_line, str(",")));391 }392 format_comments(&ele.inline_trivia, CommentLocation::ItemInline, out);393 if has_more {394 p!(out, if_else("arg separator", multi_line, nl)(sonl));395 }396 }397 _out398 }399400 let args_items = new_line_group(gen_args(children, multi_line.clone())).into_rc_path();401 let args_indented = with_indent(pi!(@i; nl items(args_items.into())));402403 p!(out, str("(") info(start));404 p!(out, if_else("args body", multi_line, items(args_indented) nl)(items(args_items.into())));405 if end_comments.should_start_with_newline {406 p!(out, nl);407 }408 format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);409 p!(out, str(")") info(end));410 }411}412impl Printable for SliceDesc {413 fn print(&self, out: &mut PrintItems) {414 p!(out, str("["));415 if self.from().is_some() {416 p!(out, { self.from() });417 }418 p!(out, str(":"));419 if self.end().is_some() {420 p!(out, { self.end().map(|e| e.expr()) });421 }422 // Keep only one : in case if we don't need step423 if self.step().is_some() {424 p!(out, str(":") {self.step().map(|e|e.expr())});425 }426 p!(out, str("]"));427 }428}429430impl Printable for Member {431 fn print(&self, out: &mut PrintItems) {432 match self {433 Self::MemberBindStmt(b) => {434 p!(out, { b.obj_local() });435 }436 Self::MemberAssertStmt(ass) => {437 p!(out, { ass.assertion() });438 }439 Self::MemberFieldNormal(n) => {440 p!(out, {n.field_name()} if(n.plus_token().is_some())({n.plus_token()}) {n.visibility()} str(" ") {n.expr()});441 }442 Self::MemberFieldMethod(m) => {443 p!(out, {m.field_name()} {m.params_desc()} {m.visibility()} str(" ") {m.expr()});444 }445 }446 }447}448449impl Printable for ObjBody {450 fn print(&self, out: &mut PrintItems) {451 match self {452 Self::ObjBodyComp(l) => {453 let (children, mut end_comments) = children_between::<Member>(454 l.syntax().clone(),455 l.l_brace_token().map(Into::into).as_ref(),456 Some(457 &(l.comp_specs()458 .next()459 .expect("at least one spec is defined")460 .syntax()461 .clone())462 .into(),463 ),464 None,465 );466 let trailing_for_comp = end_comments.extract_trailing();467 p!(out, str("{") >i nl);468 for mem in children {469 if mem.should_start_with_newline {470 p!(out, nl);471 }472 format_comments(&mem.before_trivia, CommentLocation::AboveItem, out);473 p!(out, {mem.value} str(","));474 format_comments(&mem.inline_trivia, CommentLocation::ItemInline, out);475 p!(out, nl);476 }477478 if end_comments.should_start_with_newline {479 p!(out, nl);480 }481 format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);482483 let (compspecs, end_comments) = children_between::<CompSpec>(484 l.syntax().clone(),485 l.member_comps()486 .last()487 .map(|m| m.syntax().clone())488 .map(Into::into)489 .or_else(|| l.l_brace_token().map(Into::into))490 .as_ref(),491 l.r_brace_token().map(Into::into).as_ref(),492 Some(trailing_for_comp),493 );494 for mem in compspecs {495 if mem.should_start_with_newline {496 p!(out, nl);497 }498 format_comments(&mem.before_trivia, CommentLocation::AboveItem, out);499 p!(out, { mem.value });500 format_comments(&mem.inline_trivia, CommentLocation::ItemInline, out);501 }502 if end_comments.should_start_with_newline {503 p!(out, nl);504 }505 format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);506507 p!(out, nl <i str("}"));508 }509 Self::ObjBodyMemberList(l) => {510 let (children, end_comments) = children_between::<Member>(511 l.syntax().clone(),512 l.l_brace_token().map(Into::into).as_ref(),513 l.r_brace_token().map(Into::into).as_ref(),514 None,515 );516 if children.is_empty() && end_comments.is_empty() {517 p!(out, str("{ }"));518 return;519 }520521 let source_is_multiline = children.iter().any(|c| c.triggers_multiline)522 || end_comments.should_start_with_newline;523524 let start = LineNumber::new("obj start line");525 let end = LineNumber::new("obj end line");526 let multi_line: ConditionResolver = if source_is_multiline {527 true_resolver()528 } else {529 Rc::new(move |ctx: &mut ConditionResolverContext| {530 is_multiple_lines(ctx, start, end)531 })532 };533534 fn gen_members(535 children: Vec<Child<Member>>,536 multi_line: ConditionResolver,537 ) -> PrintItems {538 let mut _out = PrintItems::new();539 let out = &mut _out;540 let mut members = children.into_iter().peekable();541 while let Some(mem) = members.next() {542 if mem.should_start_with_newline {543 p!(out, nl);544 }545 format_comments(&mem.before_trivia, CommentLocation::AboveItem, out);546 p!(out, { mem.value });547 let has_more = members.peek().is_some();548 if has_more {549 p!(out, str(","));550 } else {551 p!(out, if("trailing comma", multi_line, str(",")));552 }553 format_comments(&mem.inline_trivia, CommentLocation::ItemInline, out);554 p!(out, if_else("member separator", multi_line, nl)(sonl));555 }556 _out557 }558559 let members_items =560 new_line_group(gen_members(children, multi_line.clone())).into_rc_path();561562 let members = with_indent_eoi(multi_line, members_items.into(), end_comments);563564 p!(out, str("{") info(start));565 p!(out, items(members));566 p!(out, str("}") info(end));567 }568 }569 }570}571impl Printable for UnaryOperator {572 fn print(&self, out: &mut PrintItems) {573 p!(out, string(self.text().to_string()));574 }575}576impl Printable for BinaryOperator {577 fn print(&self, out: &mut PrintItems) {578 p!(out, string(self.text().to_string()));579 }580}581impl Printable for Bind {582 fn print(&self, out: &mut PrintItems) {583 match self {584 Self::BindDestruct(d) => {585 p!(out, {d.into()} str(" = ") {d.value()});586 }587 Self::BindFunction(f) => {588 p!(out, {f.name()} {f.params()} str(" = ") {f.value()});589 }590 }591 }592}593impl Printable for Literal {594 fn print(&self, out: &mut PrintItems) {595 p!(out, string(self.syntax().to_string()));596 }597}598impl Printable for ImportKind {599 fn print(&self, out: &mut PrintItems) {600 p!(out, string(self.syntax().to_string()));601 }602}603impl Printable for ForSpec {604 fn print(&self, out: &mut PrintItems) {605 p!(out, str("for ") {self.bind()} str(" in ") {self.expr()});606 }607}608impl Printable for IfSpec {609 fn print(&self, out: &mut PrintItems) {610 p!(out, str("if ") {self.expr()});611 }612}613impl Printable for CompSpec {614 fn print(&self, out: &mut PrintItems) {615 match self {616 Self::ForSpec(f) => f.print(out),617 Self::IfSpec(i) => i.print(out),618 }619 }620}621impl Printable for Expr {622 fn print(&self, out: &mut PrintItems) {623 let (stmts, _ending) = children_between::<Stmt>(624 self.syntax().clone(),625 None,626 self.expr_base()627 .as_ref()628 .map(ExprBase::syntax)629 .cloned()630 .map(Into::into)631 .as_ref(),632 None,633 );634 for stmt in stmts {635 p!(out, { stmt.value });636 }637 p!(out, { self.expr_base() });638 let (suffixes, _ending) = children_between::<Suffix>(639 self.syntax().clone(),640 self.expr_base()641 .as_ref()642 .map(ExprBase::syntax)643 .cloned()644 .map(Into::into)645 .as_ref(),646 None,647 None,648 );649 for suffix in suffixes {650 p!(out, { suffix.value });651 }652 }653}654impl Printable for Suffix {655 fn print(&self, out: &mut PrintItems) {656 match self {657 Self::SuffixIndex(i) => {658 if i.question_mark_token().is_some() {659 p!(out, str("?"));660 }661 p!(out, str(".") {i.index()});662 }663 Self::SuffixIndexExpr(e) => {664 if e.question_mark_token().is_some() {665 p!(out, str(".?"));666 }667 p!(out, str("[") {e.index()} str("]"));668 }669 Self::SuffixSlice(d) => {670 p!(out, { d.slice_desc() });671 }672 Self::SuffixApply(a) => {673 p!(out, { a.args_desc() });674 }675 }676 }677}678impl Printable for Stmt {679 fn print(&self, out: &mut PrintItems) {680 match self {681 Self::StmtLocal(l) => {682 let (binds, end_comments) = children_between::<Bind>(683 l.syntax().clone(),684 l.local_kw_token().map(Into::into).as_ref(),685 l.semi_token().map(Into::into).as_ref(),686 None,687 );688 if binds.len() == 1 {689 let bind = &binds[0];690 format_comments(&bind.before_trivia, CommentLocation::AboveItem, out);691 p!(out, str("local ") {bind.value});692 // TODO: keep end_comments, child.inline_trivia somehow, force multiple locals formatting in case of presence?693 } else {694 p!(out,str("local") >i nl);695 for bind in binds {696 if bind.should_start_with_newline {697 p!(out, nl);698 }699 format_comments(&bind.before_trivia, CommentLocation::AboveItem, out);700 p!(out, {bind.value} str(","));701 format_comments(&bind.inline_trivia, CommentLocation::ItemInline, out);702 p!(out, nl);703 }704 if end_comments.should_start_with_newline {705 p!(out, nl);706 }707 format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);708 p!(out,<i);709 }710 p!(out,str(";") nl);711 }712 Self::StmtAssert(a) => {713 p!(out, {a.assertion()} str(";") nl);714 }715 }716 }717}718719impl Printable for ExprArray {720 fn print(&self, out: &mut PrintItems) {721 let (children, end_comments) = children_between::<Expr>(722 self.syntax().clone(),723 self.l_brack_token().map(Into::into).as_ref(),724 self.r_brack_token().map(Into::into).as_ref(),725 None,726 );727 if children.is_empty() && end_comments.is_empty() {728 p!(out, str("[ ]"));729 return;730 }731732 let source_is_multiline =733 children.iter().any(|c| c.triggers_multiline) || end_comments.should_start_with_newline;734735 let start = LineNumber::new("arr start line");736 let end = LineNumber::new("arr end line");737 let multi_line: ConditionResolver = if source_is_multiline {738 true_resolver()739 } else {740 Rc::new(move |ctx: &mut ConditionResolverContext| is_multiple_lines(ctx, start, end))741 };742743 fn gen_elements(children: Vec<Child<Expr>>, multi_line: ConditionResolver) -> PrintItems {744 let mut _out = PrintItems::new();745 let out = &mut _out;746 let mut els = children.into_iter().peekable();747 while let Some(el) = els.next() {748 if el.should_start_with_newline {749 p!(out, nl);750 }751 format_comments(&el.before_trivia, CommentLocation::AboveItem, out);752 p!(out, { el.value });753 let has_more = els.peek().is_some();754 if has_more {755 p!(out, str(","));756 } else {757 p!(out, if("trailing comma", multi_line, str(",")));758 }759 format_comments(&el.inline_trivia, CommentLocation::ItemInline, out);760 p!(out, if_else("element separator", multi_line, nl)(sonl))761 }762 _out763 }764765 let els_items = new_line_group(gen_elements(children, multi_line.clone())).into_rc_path();766767 let els = with_indent_eoi(multi_line, els_items.into(), end_comments);768769 p!(out, str("[") info(start) items(els) str("]") info(end));770 }771}772773impl Printable for ExprBase {774 fn print(&self, out: &mut PrintItems) {775 match self {776 Self::ExprBinary(b) => {777 p!(out, {b.lhs()} str(" ") {b.binary_operator()} str(" ") {b.rhs()});778 }779 Self::ExprUnary(u) => p!(out, {u.unary_operator()} {u.rhs()}),780 // Self::ExprSlice(s) => {781 // p!(new: {s.expr()} {s.slice_desc()})782 // }783 // Self::ExprIndex(i) => {784 // p!(new: {i.expr()} str(".") {i.index()})785 // }786 // Self::ExprIndexExpr(i) => p!(new: {i.base()} str("[") {i.index()} str("]")),787 // Self::ExprApply(a) => {788 // let mut pi = p!(new: {a.expr()} {a.args_desc()});789 // if a.tailstrict_kw_token().is_some() {790 // p!(out,str(" tailstrict"));791 // }792 // pi793 // }794 Self::ExprObjExtend(ex) => {795 p!(out, {ex.lhs_work()} str(" ") {ex.rhs_work()});796 }797 Self::ExprParened(p) => {798 p!(out, str("(") {p.expr()} str(")"));799 }800 Self::ExprString(s) => p!(out, { s.text() }),801 Self::ExprNumber(n) => p!(out, { n.number() }),802 Self::ExprArray(a) => {803 p!(out, { a })804 }805 Self::ExprObject(obj) => {806 p!(out, { obj.obj_body() });807 }808 Self::ExprArrayComp(arr) => {809 p!(out, str("[") {arr.expr()});810 for spec in arr.comp_specs() {811 p!(out, str(" ") {spec});812 }813 p!(out, str("]"));814 }815 Self::ExprImport(v) => {816 p!(out, {v.import_kind()} str(" ") {v.text()});817 }818 Self::ExprVar(n) => p!(out, { n.name() }),819 // Self::ExprLocal(l) => {820 // }821 Self::ExprIfThenElse(ite) => {822 p!(out, str("if ") {ite.cond()} str(" then ") {ite.then().map(|t| t.expr())});823 if ite.else_kw_token().is_some() || ite.else_().is_some() {824 p!(out, str(" else ") {ite.else_().map(|t| t.expr())});825 }826 }827 Self::ExprFunction(f) => p!(out, str("function") {f.params_desc()} nl {f.expr()}),828 // Self::ExprAssert(a) => p!(new: {a.assertion()} str("; ") {a.expr()}),829 Self::ExprError(e) => p!(out, str("error ") {e.expr()}),830 Self::ExprLiteral(l) => {831 p!(out, { l.literal() });832 }833 }834 }835}836837impl Printable for SourceFile {838 fn print(&self, out: &mut PrintItems) {839 let before = trivia_before(840 self.syntax().clone(),841 self.expr()842 .map(|e| e.syntax().clone())843 .map(Into::into)844 .as_ref(),845 );846 let after = trivia_after(847 self.syntax().clone(),848 self.expr()849 .map(|e| e.syntax().clone())850 .map(Into::into)851 .as_ref(),852 );853 format_comments(&before, CommentLocation::AboveItem, out);854 p!(out, {self.expr()} nl);855 format_comments(&after, CommentLocation::EndOfItems, out);856 }857}858859pub struct FormatOptions {860 // 0 for hard tabs861 pub indent: u8,862}863pub fn format(input: &str, opts: &FormatOptions) -> Result<String, SnippetBuilder> {864 let (parsed, errors) = jrsonnet_rowan_parser::parse(input);865 if !errors.is_empty() {866 let mut builder = hi_doc::SnippetBuilder::new(input);867 for error in errors {868 builder869 .error(hi_doc::Text::fragment(870 format!("{:?}", error.error),871 Formatting::default(),872 ))873 .range(874 error.range.start().into()875 ..=(usize::from(error.range.end()) - 1).max(error.range.start().into()),876 )877 .build();878 }879 // let snippet = builder.build();880 return Err(builder);881 // It is possible to recover from this failure, but the output may be broken, as formatter is free to skip882 // ERROR rowan nodes.883 // Recovery needs to be enabled for LSP, though.884 }885 Ok(dprint_core::formatting::format(886 || {887 let mut out = PrintItems::new();888 parsed.print(&mut out);889 out890 },891 PrintOptions {892 indent_width: if opts.indent == 0 {893 // Reasonable max length for both 2 and 4 space sized tabs.894 3895 } else {896 opts.indent897 },898 max_width: 100,899 use_tabs: opts.indent == 0,900 new_line_text: "\n",901 },902 ))903}1use std::{any::type_name, rc::Rc};23use children::{children_between, trivia_before};4use dprint_core::formatting::{5 condition_helpers::is_multiple_lines,6 condition_resolvers::true_resolver,7 ir_helpers::{new_line_group, with_indent},8 ConditionResolver, ConditionResolverContext, LineNumber, PrintItems, PrintOptions,9};10use hi_doc::{Formatting, SnippetBuilder};11use jrsonnet_rowan_parser::{12 collect_lexed_str_block,13 nodes::{14 Arg, ArgsDesc, Assertion, BinaryOperator, Bind, CompSpec, Destruct, DestructArrayPart,15 DestructRest, Expr, ExprArray, ExprBase, FieldName, ForSpec, IfSpec, ImportKind, Literal,16 Member, Name, Number, ObjBody, ObjLocal, ParamsDesc, SliceDesc, SourceFile, Stmt, Suffix,17 Text, TextKind, UnaryOperator, Visibility,18 },19 AstNode, AstToken as _, SyntaxToken,20};2122use crate::{23 children::{trivia_after, Child, EndingComments},24 comments::{format_comments, CommentLocation},25};2627mod children;28mod comments;29mod tests;3031fn with_indent_eoi(cond: ConditionResolver, o: PrintItems, e: EndingComments) -> PrintItems {32 let end_comments_items = {33 let mut items = PrintItems::new();34 if e.should_start_with_newline {35 p!(&mut items, nl);36 }37 format_comments(&e.trivia, CommentLocation::EndOfItems, &mut items);38 items.into_rc_path()39 };40 let items = new_line_group(pi!(@i; items(o) items(end_comments_items.into()))).into_rc_path();4142 let indented = with_indent(pi!(@i; nl items(items.into())));4344 pi!(@i; if_else("indented body", cond, items(indented))(str(" ") items(items.into())))45}4647pub trait Printable {48 fn print(&self, out: &mut PrintItems);49}5051macro_rules! pi {52 (@i; $($t:tt)*) => {{53 #[allow(unused_mut)]54 let mut o = dprint_core::formatting::PrintItems::new();55 pi!(@s; o: $($t)*);56 o57 }};58 (@s; $o:ident: str($e:expr $(,)?) $($t:tt)*) => {{59 $o.push_string($e.to_owned());60 pi!(@s; $o: $($t)*);61 }};62 (@s; $o:ident: string($e:expr $(,)?) $($t:tt)*) => {{63 $o.push_string($e);64 pi!(@s; $o: $($t)*);65 }};66 (@s; $o:ident: nl $($t:tt)*) => {{67 $o.push_signal(dprint_core::formatting::Signal::NewLine);68 pi!(@s; $o: $($t)*);69 }};70 (@s; $o:ident: sonl $($t:tt)*) => {{71 $o.push_signal(dprint_core::formatting::Signal::SpaceOrNewLine);72 pi!(@s; $o: $($t)*);73 }};74 (@s; $o:ident: tab $($t:tt)*) => {{75 $o.push_signal(dprint_core::formatting::Signal::Tab);76 pi!(@s; $o: $($t)*);77 }};78 (@s; $o:ident: >i $($t:tt)*) => {{79 $o.push_signal(dprint_core::formatting::Signal::StartIndent);80 pi!(@s; $o: $($t)*);81 }};82 (@s; $o:ident: <i $($t:tt)*) => {{83 $o.push_signal(dprint_core::formatting::Signal::FinishIndent);84 pi!(@s; $o: $($t)*);85 }};86 (@s; $o:ident: >ii $($t:tt)*) => {{87 $o.push_signal(dprint_core::formatting::Signal::StartIgnoringIndent);88 pi!(@s; $o: $($t)*);89 }};90 (@s; $o:ident: <ii $($t:tt)*) => {{91 $o.push_signal(dprint_core::formatting::Signal::FinishIgnoringIndent);92 pi!(@s; $o: $($t)*);93 }};94 (@s; $o:ident: info($v:expr) $($t:tt)*) => {{95 $o.push_info($v);96 pi!(@s; $o: $($t)*);97 }};98 (@s; $o:ident: ln_anchor($v:expr) $($t:tt)*) => {{99 $o.push_anchor(LineNumberAnchor::new($v));100 pi!(@s; $o: $($t)*);101 }};102 (@s; $o:ident: if($s:literal, $cond:expr, $($i:tt)*) $($t:tt)*) => {{103 $o.push_condition(dprint_core::formatting::conditions::if_true(104 $s,105 $cond.clone(),106 {107 let mut o = PrintItems::new();108 p!(o, $($i)*);109 o110 },111 ));112 pi!(@s; $o: $($t)*);113 }};114 (@s; $o:ident: if_else($s:literal, $cond:expr, $($i:tt)*)($($e:tt)+) $($t:tt)*) => {{115 $o.push_condition(dprint_core::formatting::conditions::if_true_or(116 $s,117 $cond.clone(),118 {119 let mut o = PrintItems::new();120 p!(o, $($i)*);121 o122 },123 {124 let mut o = PrintItems::new();125 p!(o, $($e)*);126 o127 },128 ));129 pi!(@s; $o: $($t)*);130 }};131 (@s; $o:ident: if_not($s:literal, $cond:expr, $($e:tt)*) $($t:tt)*) => {{132 $o.push_condition(dprint_core::formatting::conditions::if_true_or(133 $s,134 $cond.clone(),135 {136 let o = PrintItems::new();137 o138 },139 {140 let mut o = PrintItems::new();141 p!(o, $($e)*);142 o143 },144 ));145 pi!(@s; $o: $($t)*);146 }};147 (@s; $o:ident: {$expr:expr} $($t:tt)*) => {{148 $expr.print($o);149 pi!(@s; $o: $($t)*);150 }};151 (@s; $o:ident: items($expr:expr) $($t:tt)*) => {{152 $o.extend($expr);153 pi!(@s; $o: $($t)*);154 }};155 (@s; $o:ident: if ($e:expr)($($then:tt)*) $($t:tt)*) => {{156 if $e {157 pi!(@s; $o: $($then)*);158 }159 pi!(@s; $o: $($t)*);160 }};161 (@s; $o:ident: ifelse ($e:expr)($($then:tt)*)($($else:tt)*) $($t:tt)*) => {{162 if $e {163 pi!(@s; $o: $($then)*);164 } else {165 pi!(@s; $o: $($else)*);166 }167 pi!(@s; $o: $($t)*);168 }};169 (@s; $i:ident:) => {}170}171macro_rules! p {172 ($o:ident, $($t:tt)*) => {173 pi!(@s; $o: $($t)*)174 };175 (&mut $o:ident, $($t:tt)*) => {176 let om = &mut $o;177 pi!(@s; om: $($t)*)178 };179}180pub(crate) use p;181pub(crate) use pi;182183impl<P> Printable for Option<P>184where185 P: Printable,186{187 fn print(&self, out: &mut PrintItems) {188 if let Some(v) = self {189 v.print(out);190 } else {191 p!(192 out,193 string(format!(194 "/*missing {}*/",195 type_name::<P>().replace("jrsonnet_rowan_parser::generated::nodes::", "")196 ),)197 );198 }199 }200}201202impl Printable for SyntaxToken {203 fn print(&self, out: &mut PrintItems) {204 p!(out, string(self.to_string()));205 }206}207208impl Printable for Text {209 fn print(&self, out: &mut PrintItems) {210 if matches!(self.kind(), TextKind::StringBlock) {211 let text = self.text();212 let mut text = collect_lexed_str_block(&text[3..])213 .expect("formatting is not performed on code with parsing errors");214215 if text.truncate && text.lines.ends_with(&[""]) {216 text.truncate = false;217 text.lines.pop();218 }219220 p!(out, str("|||"));221 if text.truncate {222 p!(out, str("-"));223 }224 p!(out, nl > i);225 for ele in text.lines {226 if ele.is_empty() {227 p!(out, >ii nl <ii);228 } else {229 p!(out, string(ele.to_string()) nl);230 }231 }232 p!(out, <i str("|||"));233234 return;235 }236 p!(out, string(format!("{}", self)));237 }238}239impl Printable for Number {240 fn print(&self, out: &mut PrintItems) {241 p!(out, string(format!("{}", self)));242 }243}244245impl Printable for Name {246 fn print(&self, out: &mut PrintItems) {247 p!(out, { self.ident_lit() });248 }249}250251impl Printable for DestructRest {252 fn print(&self, out: &mut PrintItems) {253 p!(out, str("..."));254 if let Some(name) = self.into() {255 p!(out, { name });256 }257 }258}259260impl Printable for Destruct {261 fn print(&self, out: &mut PrintItems) {262 match self {263 Self::DestructFull(f) => {264 p!(out, { f.name() });265 }266 Self::DestructSkip(_) => p!(out, str("?")),267 Self::DestructArray(a) => {268 p!(out, str("[") >i nl);269 for el in a.destruct_array_parts() {270 match el {271 DestructArrayPart::DestructArrayElement(e) => {272 p!(out, {e.destruct()} str(",") nl);273 }274 DestructArrayPart::DestructRest(d) => {275 p!(out, {d} str(",") nl);276 }277 }278 }279 p!(out, <i str("]"));280 }281 Self::DestructObject(o) => {282 p!(out, str("{") >i nl);283 for item in o.destruct_object_fields() {284 p!(out, { item.field() });285 if let Some(des) = item.destruct() {286 p!(out, str(": ") {des});287 }288 if let Some(def) = item.expr() {289 p!(out, str(" = ") {def});290 }291 p!(out, str(",") nl);292 }293 if let Some(rest) = o.destruct_rest() {294 p!(out, {rest} nl);295 }296 p!(out, <i str("}"));297 }298 }299 }300}301302impl Printable for FieldName {303 fn print(&self, out: &mut PrintItems) {304 match self {305 Self::FieldNameFixed(f) => {306 if let Some(id) = f.id() {307 p!(out, { id });308 } else if let Some(str) = f.text() {309 p!(out, { str });310 } else {311 p!(out, str("/*missing FieldName*/"));312 }313 }314 Self::FieldNameDynamic(d) => {315 p!(out, str("[") {d.expr()} str("]"));316 }317 }318 }319}320321impl Printable for Visibility {322 fn print(&self, out: &mut PrintItems) {323 p!(out, string(self.to_string()));324 }325}326327impl Printable for ObjLocal {328 fn print(&self, out: &mut PrintItems) {329 p!(out, str("local ") {self.bind()});330 }331}332333impl Printable for Assertion {334 fn print(&self, out: &mut PrintItems) {335 p!(out, str("assert ") {self.condition()});336 if self.colon_token().is_some() || self.message().is_some() {337 p!(out, str(": ") {self.message()});338 }339 }340}341342impl Printable for ParamsDesc {343 fn print(&self, out: &mut PrintItems) {344 p!(out, str("(") >i nl);345 for param in self.params() {346 p!(out, { param.destruct() });347 if param.assign_token().is_some() || param.expr().is_some() {348 p!(out, str(" = ") {param.expr()});349 }350 p!(out, str(",") nl);351 }352 p!(out, <i str(")"));353 }354}355impl Printable for ArgsDesc {356 fn print(&self, out: &mut PrintItems) {357 fn gen_args(children: Vec<Child<Arg>>, multi_line: ConditionResolver) -> PrintItems {358 let mut out = PrintItems::new();359360 let mut args = children.into_iter().peekable();361 while let Some(ele) = args.next() {362 if ele.should_start_with_newline {363 p!(out, nl);364 }365 format_comments(&ele.before_trivia, CommentLocation::AboveItem, &mut out);366 let arg = ele.value;367 if arg.name().is_some() || arg.assign_token().is_some() {368 p!(&mut out, {arg.name()} str(" = "));369 }370 p!(&mut out, { arg.expr() });371 let has_more = args.peek().is_some();372 if has_more {373 p!(out, str(","));374 } else {375 p!(out, if("trailing comma", multi_line, str(",")));376 }377 format_comments(&ele.inline_trivia, CommentLocation::ItemInline, &mut out);378 if has_more {379 p!(out, if_else("arg separator", multi_line, nl)(sonl));380 }381 }382383 out384 }385386 let start = LineNumber::new("args start line");387 let end = LineNumber::new("args end line");388 let multi_line = Rc::new(move |condition_context: &mut ConditionResolverContext| {389 is_multiple_lines(condition_context, start, end)390 });391392 let (children, end_comments) = children_between::<Arg>(393 self.syntax().clone(),394 self.l_paren_token().map(Into::into).as_ref(),395 self.r_paren_token().map(Into::into).as_ref(),396 None,397 );398399 let args_items = new_line_group(gen_args(children, multi_line.clone())).into_rc_path();400 let args_indented = with_indent(pi!(@i; nl items(args_items.into())));401402 p!(out, str("(") info(start));403 p!(out, if_else("args body", multi_line, items(args_indented) nl)(items(args_items.into())));404 if end_comments.should_start_with_newline {405 p!(out, nl);406 }407 format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);408 p!(out, str(")") info(end));409 }410}411impl Printable for SliceDesc {412 fn print(&self, out: &mut PrintItems) {413 p!(out, str("["));414 if self.from().is_some() {415 p!(out, { self.from() });416 }417 p!(out, str(":"));418 if self.end().is_some() {419 p!(out, { self.end().map(|e| e.expr()) });420 }421 // Keep only one : in case if we don't need step422 if self.step().is_some() {423 p!(out, str(":") {self.step().map(|e|e.expr())});424 }425 p!(out, str("]"));426 }427}428429impl Printable for Member {430 fn print(&self, out: &mut PrintItems) {431 match self {432 Self::MemberBindStmt(b) => {433 p!(out, { b.obj_local() });434 }435 Self::MemberAssertStmt(ass) => {436 p!(out, { ass.assertion() });437 }438 Self::MemberFieldNormal(n) => {439 p!(out, {n.field_name()} if(n.plus_token().is_some())({n.plus_token()}) {n.visibility()} str(" ") {n.expr()});440 }441 Self::MemberFieldMethod(m) => {442 p!(out, {m.field_name()} {m.params_desc()} {m.visibility()} str(" ") {m.expr()});443 }444 }445 }446}447448impl Printable for ObjBody {449 #[allow(clippy::too_many_lines)]450 fn print(&self, out: &mut PrintItems) {451 match self {452 Self::ObjBodyComp(l) => {453 let (children, mut end_comments) = children_between::<Member>(454 l.syntax().clone(),455 l.l_brace_token().map(Into::into).as_ref(),456 Some(457 &(l.comp_specs()458 .next()459 .expect("at least one spec is defined")460 .syntax()461 .clone())462 .into(),463 ),464 None,465 );466 let trailing_for_comp = end_comments.extract_trailing();467 p!(out, str("{") >i nl);468 for mem in children {469 if mem.should_start_with_newline {470 p!(out, nl);471 }472 format_comments(&mem.before_trivia, CommentLocation::AboveItem, out);473 p!(out, {mem.value} str(","));474 format_comments(&mem.inline_trivia, CommentLocation::ItemInline, out);475 p!(out, nl);476 }477478 if end_comments.should_start_with_newline {479 p!(out, nl);480 }481 format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);482483 let (compspecs, end_comments) = children_between::<CompSpec>(484 l.syntax().clone(),485 l.member_comps()486 .last()487 .map(|m| m.syntax().clone())488 .map(Into::into)489 .or_else(|| l.l_brace_token().map(Into::into))490 .as_ref(),491 l.r_brace_token().map(Into::into).as_ref(),492 Some(trailing_for_comp),493 );494 for mem in compspecs {495 if mem.should_start_with_newline {496 p!(out, nl);497 }498 format_comments(&mem.before_trivia, CommentLocation::AboveItem, out);499 p!(out, { mem.value });500 format_comments(&mem.inline_trivia, CommentLocation::ItemInline, out);501 }502 if end_comments.should_start_with_newline {503 p!(out, nl);504 }505 format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);506507 p!(out, nl <i str("}"));508 }509 Self::ObjBodyMemberList(l) => {510 fn gen_members(511 children: Vec<Child<Member>>,512 multi_line: ConditionResolver,513 ) -> PrintItems {514 let mut out = PrintItems::new();515 let mut members = children.into_iter().peekable();516 while let Some(mem) = members.next() {517 if mem.should_start_with_newline {518 p!(out, nl);519 }520 format_comments(&mem.before_trivia, CommentLocation::AboveItem, &mut out);521 p!(&mut out, { mem.value });522 let has_more = members.peek().is_some();523 if has_more {524 p!(out, str(","));525 } else {526 p!(out, if("trailing comma", multi_line, str(",")));527 }528 format_comments(&mem.inline_trivia, CommentLocation::ItemInline, &mut out);529 p!(out, if_else("member separator", multi_line, nl)(sonl));530 }531 out532 }533534 let (children, end_comments) = children_between::<Member>(535 l.syntax().clone(),536 l.l_brace_token().map(Into::into).as_ref(),537 l.r_brace_token().map(Into::into).as_ref(),538 None,539 );540 if children.is_empty() && end_comments.is_empty() {541 p!(out, str("{ }"));542 return;543 }544545 let source_is_multiline = children.iter().any(|c| c.triggers_multiline)546 || end_comments.should_start_with_newline;547548 let start = LineNumber::new("obj start line");549 let end = LineNumber::new("obj end line");550 let multi_line: ConditionResolver = if source_is_multiline {551 true_resolver()552 } else {553 Rc::new(move |ctx: &mut ConditionResolverContext| {554 is_multiple_lines(ctx, start, end)555 })556 };557558 let members_items =559 new_line_group(gen_members(children, multi_line.clone())).into_rc_path();560561 let members = with_indent_eoi(multi_line, members_items.into(), end_comments);562563 p!(out, str("{") info(start));564 p!(out, items(members));565 p!(out, str("}") info(end));566 }567 }568 }569}570impl Printable for UnaryOperator {571 fn print(&self, out: &mut PrintItems) {572 p!(out, string(self.text().to_string()));573 }574}575impl Printable for BinaryOperator {576 fn print(&self, out: &mut PrintItems) {577 p!(out, string(self.text().to_string()));578 }579}580impl Printable for Bind {581 fn print(&self, out: &mut PrintItems) {582 match self {583 Self::BindDestruct(d) => {584 p!(out, {d.into()} str(" = ") {d.value()});585 }586 Self::BindFunction(f) => {587 p!(out, {f.name()} {f.params()} str(" = ") {f.value()});588 }589 }590 }591}592impl Printable for Literal {593 fn print(&self, out: &mut PrintItems) {594 p!(out, string(self.syntax().to_string()));595 }596}597impl Printable for ImportKind {598 fn print(&self, out: &mut PrintItems) {599 p!(out, string(self.syntax().to_string()));600 }601}602impl Printable for ForSpec {603 fn print(&self, out: &mut PrintItems) {604 p!(out, str("for ") {self.bind()} str(" in ") {self.expr()});605 }606}607impl Printable for IfSpec {608 fn print(&self, out: &mut PrintItems) {609 p!(out, str("if ") {self.expr()});610 }611}612impl Printable for CompSpec {613 fn print(&self, out: &mut PrintItems) {614 match self {615 Self::ForSpec(f) => f.print(out),616 Self::IfSpec(i) => i.print(out),617 }618 }619}620impl Printable for Expr {621 fn print(&self, out: &mut PrintItems) {622 let (stmts, _ending) = children_between::<Stmt>(623 self.syntax().clone(),624 None,625 self.expr_base()626 .as_ref()627 .map(ExprBase::syntax)628 .cloned()629 .map(Into::into)630 .as_ref(),631 None,632 );633 for stmt in stmts {634 p!(out, { stmt.value });635 }636 p!(out, { self.expr_base() });637 let (suffixes, _ending) = children_between::<Suffix>(638 self.syntax().clone(),639 self.expr_base()640 .as_ref()641 .map(ExprBase::syntax)642 .cloned()643 .map(Into::into)644 .as_ref(),645 None,646 None,647 );648 for suffix in suffixes {649 p!(out, { suffix.value });650 }651 }652}653impl Printable for Suffix {654 fn print(&self, out: &mut PrintItems) {655 match self {656 Self::SuffixIndex(i) => {657 if i.question_mark_token().is_some() {658 p!(out, str("?"));659 }660 p!(out, str(".") {i.index()});661 }662 Self::SuffixIndexExpr(e) => {663 if e.question_mark_token().is_some() {664 p!(out, str(".?"));665 }666 p!(out, str("[") {e.index()} str("]"));667 }668 Self::SuffixSlice(d) => {669 p!(out, { d.slice_desc() });670 }671 Self::SuffixApply(a) => {672 p!(out, { a.args_desc() });673 }674 }675 }676}677impl Printable for Stmt {678 fn print(&self, out: &mut PrintItems) {679 match self {680 Self::StmtLocal(l) => {681 let (binds, end_comments) = children_between::<Bind>(682 l.syntax().clone(),683 l.local_kw_token().map(Into::into).as_ref(),684 l.semi_token().map(Into::into).as_ref(),685 None,686 );687 if binds.len() == 1 {688 let bind = &binds[0];689 format_comments(&bind.before_trivia, CommentLocation::AboveItem, out);690 p!(out, str("local ") {bind.value});691 // TODO: keep end_comments, child.inline_trivia somehow, force multiple locals formatting in case of presence?692 } else {693 p!(out,str("local") >i nl);694 for bind in binds {695 if bind.should_start_with_newline {696 p!(out, nl);697 }698 format_comments(&bind.before_trivia, CommentLocation::AboveItem, out);699 p!(out, {bind.value} str(","));700 format_comments(&bind.inline_trivia, CommentLocation::ItemInline, out);701 p!(out, nl);702 }703 if end_comments.should_start_with_newline {704 p!(out, nl);705 }706 format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);707 p!(out,<i);708 }709 p!(out,str(";") nl);710 }711 Self::StmtAssert(a) => {712 p!(out, {a.assertion()} str(";") nl);713 }714 }715 }716}717718impl Printable for ExprArray {719 fn print(&self, out: &mut PrintItems) {720 fn gen_elements(children: Vec<Child<Expr>>, multi_line: ConditionResolver) -> PrintItems {721 let mut out = PrintItems::new();722 let mut els = children.into_iter().peekable();723 while let Some(el) = els.next() {724 if el.should_start_with_newline {725 p!(out, nl);726 }727 format_comments(&el.before_trivia, CommentLocation::AboveItem, &mut out);728 p!(&mut out, { el.value });729 let has_more = els.peek().is_some();730 if has_more {731 p!(out, str(","));732 } else {733 p!(out, if("trailing comma", multi_line, str(",")));734 }735 format_comments(&el.inline_trivia, CommentLocation::ItemInline, &mut out);736 p!(out, if_else("element separator", multi_line, nl)(sonl));737 }738 out739 }740741 let (children, end_comments) = children_between::<Expr>(742 self.syntax().clone(),743 self.l_brack_token().map(Into::into).as_ref(),744 self.r_brack_token().map(Into::into).as_ref(),745 None,746 );747 if children.is_empty() && end_comments.is_empty() {748 p!(out, str("[ ]"));749 return;750 }751752 let source_is_multiline =753 children.iter().any(|c| c.triggers_multiline) || end_comments.should_start_with_newline;754755 let start = LineNumber::new("arr start line");756 let end = LineNumber::new("arr end line");757 let multi_line: ConditionResolver = if source_is_multiline {758 true_resolver()759 } else {760 Rc::new(move |ctx: &mut ConditionResolverContext| is_multiple_lines(ctx, start, end))761 };762763 let els_items = new_line_group(gen_elements(children, multi_line.clone())).into_rc_path();764765 let els = with_indent_eoi(multi_line, els_items.into(), end_comments);766767 p!(out, str("[") info(start) items(els) str("]") info(end));768 }769}770771impl Printable for ExprBase {772 fn print(&self, out: &mut PrintItems) {773 match self {774 Self::ExprBinary(b) => {775 p!(out, {b.lhs()} str(" ") {b.binary_operator()} str(" ") {b.rhs()});776 }777 Self::ExprUnary(u) => p!(out, {u.unary_operator()} {u.rhs()}),778 // Self::ExprSlice(s) => {779 // p!(new: {s.expr()} {s.slice_desc()})780 // }781 // Self::ExprIndex(i) => {782 // p!(new: {i.expr()} str(".") {i.index()})783 // }784 // Self::ExprIndexExpr(i) => p!(new: {i.base()} str("[") {i.index()} str("]")),785 // Self::ExprApply(a) => {786 // let mut pi = p!(new: {a.expr()} {a.args_desc()});787 // if a.tailstrict_kw_token().is_some() {788 // p!(out,str(" tailstrict"));789 // }790 // pi791 // }792 Self::ExprObjExtend(ex) => {793 p!(out, {ex.lhs_work()} str(" ") {ex.rhs_work()});794 }795 Self::ExprParened(p) => {796 p!(out, str("(") {p.expr()} str(")"));797 }798 Self::ExprString(s) => p!(out, { s.text() }),799 Self::ExprNumber(n) => p!(out, { n.number() }),800 Self::ExprArray(a) => {801 p!(out, { a });802 }803 Self::ExprObject(obj) => {804 p!(out, { obj.obj_body() });805 }806 Self::ExprArrayComp(arr) => {807 p!(out, str("[") {arr.expr()});808 for spec in arr.comp_specs() {809 p!(out, str(" ") {spec});810 }811 p!(out, str("]"));812 }813 Self::ExprImport(v) => {814 p!(out, {v.import_kind()} str(" ") {v.text()});815 }816 Self::ExprVar(n) => p!(out, { n.name() }),817 // Self::ExprLocal(l) => {818 // }819 Self::ExprIfThenElse(ite) => {820 p!(out, str("if ") {ite.cond()} str(" then ") {ite.then().map(|t| t.expr())});821 if ite.else_kw_token().is_some() || ite.else_().is_some() {822 p!(out, str(" else ") {ite.else_().map(|t| t.expr())});823 }824 }825 Self::ExprFunction(f) => p!(out, str("function") {f.params_desc()} nl {f.expr()}),826 // Self::ExprAssert(a) => p!(new: {a.assertion()} str("; ") {a.expr()}),827 Self::ExprError(e) => p!(out, str("error ") {e.expr()}),828 Self::ExprLiteral(l) => {829 p!(out, { l.literal() });830 }831 }832 }833}834835impl Printable for SourceFile {836 fn print(&self, out: &mut PrintItems) {837 let before = trivia_before(838 self.syntax().clone(),839 self.expr()840 .map(|e| e.syntax().clone())841 .map(Into::into)842 .as_ref(),843 );844 let after = trivia_after(845 self.syntax().clone(),846 self.expr()847 .map(|e| e.syntax().clone())848 .map(Into::into)849 .as_ref(),850 );851 format_comments(&before, CommentLocation::AboveItem, out);852 p!(out, {self.expr()} nl);853 format_comments(&after, CommentLocation::EndOfItems, out);854 }855}856857pub struct FormatOptions {858 // 0 for hard tabs859 pub indent: u8,860}861862#[allow(863 clippy::result_large_err,864 reason = "TODO: there should be an intermediate representation for such reports"865)]866pub fn format(input: &str, opts: &FormatOptions) -> Result<String, SnippetBuilder> {867 let (parsed, errors) = jrsonnet_rowan_parser::parse(input);868 if !errors.is_empty() {869 let mut builder = hi_doc::SnippetBuilder::new(input);870 for error in errors {871 builder872 .error(hi_doc::Text::fragment(873 format!("{:?}", error.error),874 Formatting::default(),875 ))876 .range(877 error.range.start().into()878 ..=(usize::from(error.range.end()) - 1).max(error.range.start().into()),879 )880 .build();881 }882 // let snippet = builder.build();883 return Err(builder);884 // It is possible to recover from this failure, but the output may be broken, as formatter is free to skip885 // ERROR rowan nodes.886 // Recovery needs to be enabled for LSP, though.887 }888 Ok(dprint_core::formatting::format(889 || {890 let mut out = PrintItems::new();891 parsed.print(&mut out);892 out893 },894 PrintOptions {895 indent_width: if opts.indent == 0 {896 // Reasonable max length for both 2 and 4 space sized tabs.897 3898 } else {899 opts.indent900 },901 max_width: 100,902 use_tabs: opts.indent == 0,903 new_line_text: "\n",904 },905 ))906}crates/jrsonnet-macros/src/typed.rsdiffbeforeafterboth--- a/crates/jrsonnet-macros/src/typed.rs
+++ b/crates/jrsonnet-macros/src/typed.rs
@@ -156,7 +156,7 @@
// optional flatten is handled in same way as serde
if self.attr.flatten {
return quote! {
- #ident: <#ty as TypedObj>::parse(&obj).ok(),
+ #ident: <#ty as ParseTypedObj>::parse(&obj).ok(),
};
}
@@ -190,7 +190,7 @@
// optional flatten is handled in same way as serde
if self.attr.flatten {
return quote! {
- #ident: <#ty as TypedObj>::parse(&obj)?,
+ #ident: <#ty as ParseTypedObj>::parse(&obj)?,
};
}
@@ -232,12 +232,12 @@
if self.is_option {
quote! {
if let Some(value) = self.#ident {
- <#ty as TypedObj>::serialize(value, out)?;
+ <#ty as SerializeTypedObj>::serialize(value, out)?;
}
}
} else {
quote! {
- <#ty as TypedObj>::serialize(self.#ident, out)?;
+ <#ty as SerializeTypedObj>::serialize(self.#ident, out)?;
}
}
},
crates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth--- a/crates/jrsonnet-parser/src/expr.rs
+++ b/crates/jrsonnet-parser/src/expr.rs
@@ -224,7 +224,8 @@
},
#[cfg(feature = "exp-destruct")]
Object {
- fields: Vec<(IStr, Option<Destruct>, Option<Spanned<Expr>>)>,
+ #[allow(clippy::type_complexity)]
+ fields: Vec<(IStr, Option<Destruct>, Option<Rc<Spanned<Expr>>>)>,
rest: Option<DestructRest>,
},
}
@@ -261,7 +262,7 @@
let mut out = 0;
for (_, into, _) in fields {
match into {
- Some(v) => out += v.capacity_hint(),
+ Some(v) => out += v.binds_len(),
// Field is destructured to default name
None => out += 1,
}
crates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-parser/src/lib.rs
+++ b/crates/jrsonnet-parser/src/lib.rs
@@ -119,7 +119,7 @@
}
pub rule destruct_object(s: &ParserSettings) -> expr::Destruct
= "{" _
- fields:(name:id() into:(_ ":" _ into:destruct(s) {into})? default:(_ "=" _ v:expr(s) {v})? {(name, into, default)})**comma()
+ fields:(name:id() into:(_ ":" _ into:destruct(s) {into})? default:(_ "=" _ v:expr(s) {v})? {(name, into, default.map(Rc::new))})**comma()
rest:(
comma() rest:destruct_rest()? {rest}
/ comma()? {None}
crates/jrsonnet-rowan-parser/src/ast.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/ast.rs
+++ b/crates/jrsonnet-rowan-parser/src/ast.rs
@@ -2,8 +2,9 @@
use crate::{SyntaxKind, SyntaxNode, SyntaxNodeChildren, SyntaxToken};
-/// The main trait to go from untyped `SyntaxNode` to a typed ast. The
-/// conversion itself has zero runtime cost: ast and syntax nodes have exactly
+/// The main trait to go from untyped `SyntaxNode` to a typed ast.
+///
+/// The conversion itself has zero runtime cost: ast and syntax nodes have exactly
/// the same representation: a pointer to the tree root and a pointer to the
/// node itself.
pub trait AstNode {
crates/jrsonnet-rowan-parser/src/event.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/event.rs
+++ b/crates/jrsonnet-rowan-parser/src/event.rs
@@ -56,7 +56,7 @@
fn text_offset(&self) -> TextSize {
if self.offset == 0 {
return 0.into();
- };
+ }
self.lexemes.get(self.offset).map_or_else(
|| {
self.lexemes
crates/jrsonnet-rowan-parser/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/lib.rs
+++ b/crates/jrsonnet-rowan-parser/src/lib.rs
@@ -26,7 +26,7 @@
use self::{
ast::support,
- generated::nodes::{Expr, ExprBinary, ExprObjExtend},
+ generated::nodes::{Expr, ExprObjExtend},
};
pub fn parse(input: &str) -> (SourceFile, Vec<LocatedSyntaxError>) {
crates/jrsonnet-rowan-parser/src/marker.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/marker.rs
+++ b/crates/jrsonnet-rowan-parser/src/marker.rs
@@ -141,7 +141,7 @@
new_m
}
/// Create new node around existing marker
- /// If previous_pos is set - the wrapping node would not include everything that happened between wrapped node end and the current position of the parser
+ /// If `previous_pos` is set - the wrapping node would not include everything that happened between wrapped node end and the current position of the parser
fn wrap_raw(
self,
p: &mut Parser,
crates/jrsonnet-rowan-parser/src/parser.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/parser.rs
+++ b/crates/jrsonnet-rowan-parser/src/parser.rs
@@ -52,8 +52,7 @@
write!(f, "unexpected {found:?}, expecting {expected}")
}
SyntaxError::Missing { expected } => write!(f, "missing {expected}"),
- SyntaxError::Custom { error } => write!(f, "{error}"),
- SyntaxError::Hint { error } => write!(f, "{error}"),
+ SyntaxError::Custom { error } | SyntaxError::Hint { error } => write!(f, "{error}"),
}
}
}
@@ -492,7 +491,7 @@
} else {
m.complete(p, MEMBER_FIELD_NORMAL)
};
- };
+ }
while p.at_ts(COMPSPEC) {
compspecs.push(compspec(p));
}
@@ -747,7 +746,7 @@
if p.at(T![:]) {
p.bump();
destruct(p);
- };
+ }
if p.at(T![=]) {
p.bump();
expr(p);
crates/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
@@ -11,7 +11,7 @@
use crate::SyntaxKind;
-pub(crate) fn lex_str_block_test<'d>(lex: &mut Lexer<'d, SyntaxKind>) {
+pub(crate) fn lex_str_block_test(lex: &mut Lexer<'_, SyntaxKind>) {
let _ = lex_str_block(lex);
}
@@ -48,7 +48,7 @@
}
fn eat_if(&mut self, f: impl Fn(char) -> bool) -> usize {
- if self.peek().map(f).unwrap_or(false) {
+ if self.peek().is_some_and(f) {
self.index += 1;
return 1;
}
@@ -141,9 +141,7 @@
}
}
-pub fn collect_lexed_str_block<'s>(
- input: &'s str,
-) -> Result<CollectStrBlock<'s>, StringBlockError> {
+pub fn collect_lexed_str_block(input: &str) -> Result<CollectStrBlock<'_>, StringBlockError> {
let mut collect = CollectStrBlock {
truncate: false,
lines: vec![],
@@ -179,7 +177,7 @@
}
fn mark_line(&mut self, line: &'d str) {
- self.lines.push(line)
+ self.lines.push(line);
}
}
crates/jrsonnet-rowan-parser/src/tests.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/tests.rs
+++ b/crates/jrsonnet-rowan-parser/src/tests.rs
@@ -2,7 +2,6 @@
#![cfg(test)]
use hi_doc::{Formatting, SnippetBuilder, Text};
-use thiserror::Error;
use crate::{parse, AstNode};
@@ -14,7 +13,7 @@
if !errors.is_empty() && !text.is_empty() {
writeln!(out, "===").unwrap();
for err in &errors {
- writeln!(out, "{:?}", err).unwrap();
+ writeln!(out, "{err:?}").unwrap();
}
let mut code = text.to_string();
crates/jrsonnet-stdlib/src/regex.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/regex.rs
+++ b/crates/jrsonnet-stdlib/src/regex.rs
@@ -4,7 +4,7 @@
use jrsonnet_evaluator::{
error::{ErrorKind::*, Result},
rustc_hash::FxBuildHasher,
- typed::Typed,
+ typed::{IntoUntyped, Typed},
val::StrValue,
IStr, ObjValue, ObjValueBuilder,
};
@@ -41,7 +41,7 @@
}
}
-#[derive(Typed)]
+#[derive(Typed, IntoUntyped)]
pub struct RegexMatch {
string: IStr,
captures: Vec<IStr>,
tests/tests/common.rsdiffbeforeafterboth--- a/tests/tests/common.rs
+++ b/tests/tests/common.rs
@@ -41,6 +41,7 @@
}
#[builtin]
+#[allow(dead_code)]
fn assert_throw(lazy: Thunk<Val>, message: String) -> Result<bool> {
match lazy.evaluate() {
Ok(_) => {
@@ -55,6 +56,7 @@
}
#[builtin]
+#[allow(dead_code)]
fn param_names(fun: FuncVal) -> Vec<String> {
fun.params()
.iter()
tests/tests/typed_obj.rsdiffbeforeafterboth--- a/tests/tests/typed_obj.rs
+++ b/tests/tests/typed_obj.rs
@@ -9,7 +9,7 @@
};
use jrsonnet_stdlib::ContextInitializer;
-#[derive(Clone, Typed, PartialEq, Debug)]
+#[derive(Clone, Typed, FromUntyped, IntoUntyped, PartialEq, Debug)]
struct A {
a: u32,
b: u16,
@@ -39,7 +39,7 @@
Ok(())
}
-#[derive(Clone, Typed, PartialEq, Debug)]
+#[derive(Clone, Typed, FromUntyped, IntoUntyped, PartialEq, Debug)]
struct B {
a: u32,
#[typed(rename = "c")]
@@ -62,7 +62,7 @@
Ok(())
}
-#[derive(Clone, Typed, PartialEq, Debug)]
+#[derive(Clone, Typed, FromUntyped, IntoUntyped, PartialEq, Debug)]
struct ObjectKind {
#[typed(rename = "apiVersion")]
api_version: String,
@@ -70,7 +70,7 @@
kind: String,
}
-#[derive(Clone, Typed, PartialEq, Debug)]
+#[derive(Clone, Typed, FromUntyped, IntoUntyped, PartialEq, Debug)]
struct Object {
#[typed(flatten)]
kind: ObjectKind,
@@ -104,7 +104,7 @@
Ok(())
}
-#[derive(Clone, Typed, PartialEq, Debug)]
+#[derive(Clone, Typed, FromUntyped, IntoUntyped, PartialEq, Debug)]
struct C {
a: Option<u32>,
b: u16,
@@ -142,14 +142,14 @@
Ok(())
}
-#[derive(Clone, Typed, PartialEq, Debug)]
+#[derive(Clone, Typed, FromUntyped, IntoUntyped, PartialEq, Debug)]
struct D {
#[typed(flatten(ok))]
e: Option<E>,
b: u16,
}
-#[derive(Clone, Typed, PartialEq, Debug)]
+#[derive(Clone, Typed, FromUntyped, IntoUntyped, PartialEq, Debug)]
struct E {
v: u32,
}
xtask/src/sourcegen/mod.rsdiffbeforeafterboth--- a/xtask/src/sourcegen/mod.rs
+++ b/xtask/src/sourcegen/mod.rs
@@ -65,9 +65,9 @@
is_lexer_error: true,
});
}
- };
+ }
continue;
- };
+ }
let name = to_upper_snake_case(token);
eprintln!("implicit kw: {token}");
kinds.define_token(TokenKind::Keyword {
@@ -447,7 +447,7 @@
let trait_name = format_ident!("{}", trait_name);
let kinds: Vec<_> = nodes
.iter()
- .map(|name| format_ident!("{}", to_upper_snake_case(&name.name.to_string())))
+ .map(|name| format_ident!("{}", to_upper_snake_case(&name.name)))
.collect();
(
@@ -555,10 +555,10 @@
if "{}[]()$".contains(token) {
let c = token.chars().next().unwrap();
quote! { #c }
- } else if token.contains(|v| v == '$') {
+ } else if token.contains('$') {
quote! { #token }
- } else if token.chars().all(|v| ('a'..='z').contains(&v)) {
- let i = Ident::new(&token, Span::call_site());
+ } else if token.chars().all(|v: char| v.is_ascii_lowercase()) {
+ let i = Ident::new(token, Span::call_site());
quote! { #i }
} else {
let cs = token.chars().map(|c| Punct::new(c, Spacing::Joint));