--- 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]] --- 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. --- 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) }; --- 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( --- 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())), --- 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>]) -> Result { 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::>>()?; self.handler.call(&args) } --- 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, 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, 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, exists_visible: Option, - #[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 { --- 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; } + +#[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 { --- 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 { --- a/crates/jrsonnet-formatter/src/lib.rs +++ b/crates/jrsonnet-formatter/src/lib.rs @@ -37,8 +37,7 @@ format_comments(&e.trivia, CommentLocation::EndOfItems, &mut items); items.into_rc_path() }; - let items = - new_line_group(pi!(@i; items(o.into()) items(end_comments_items.into()))).into_rc_path(); + let items = new_line_group(pi!(@i; items(o) items(end_comments_items.into()))).into_rc_path(); let indented = with_indent(pi!(@i; nl items(items.into()))); @@ -355,48 +354,48 @@ } impl Printable for ArgsDesc { fn print(&self, out: &mut PrintItems) { - let start = LineNumber::new("args start line"); - let end = LineNumber::new("args end line"); - let multi_line = Rc::new(move |condition_context: &mut ConditionResolverContext| { - is_multiple_lines(condition_context, start, end) - }); - - let (children, end_comments) = children_between::( - self.syntax().clone(), - self.l_paren_token().map(Into::into).as_ref(), - self.r_paren_token().map(Into::into).as_ref(), - None, - ); - fn gen_args(children: Vec>, multi_line: ConditionResolver) -> PrintItems { - let mut _out = PrintItems::new(); - let out = &mut _out; + let mut out = PrintItems::new(); let mut args = children.into_iter().peekable(); while let Some(ele) = args.next() { if ele.should_start_with_newline { p!(out, nl); } - format_comments(&ele.before_trivia, CommentLocation::AboveItem, out); + format_comments(&ele.before_trivia, CommentLocation::AboveItem, &mut out); let arg = ele.value; if arg.name().is_some() || arg.assign_token().is_some() { - p!(out, {arg.name()} str(" = ")); + p!(&mut out, {arg.name()} str(" = ")); } - p!(out, { arg.expr() }); + p!(&mut out, { arg.expr() }); let has_more = args.peek().is_some(); if has_more { p!(out, str(",")); } else { p!(out, if("trailing comma", multi_line, str(","))); } - format_comments(&ele.inline_trivia, CommentLocation::ItemInline, out); + format_comments(&ele.inline_trivia, CommentLocation::ItemInline, &mut out); if has_more { p!(out, if_else("arg separator", multi_line, nl)(sonl)); } } - _out + + out } + let start = LineNumber::new("args start line"); + let end = LineNumber::new("args end line"); + let multi_line = Rc::new(move |condition_context: &mut ConditionResolverContext| { + is_multiple_lines(condition_context, start, end) + }); + + let (children, end_comments) = children_between::( + self.syntax().clone(), + self.l_paren_token().map(Into::into).as_ref(), + self.r_paren_token().map(Into::into).as_ref(), + None, + ); + let args_items = new_line_group(gen_args(children, multi_line.clone())).into_rc_path(); let args_indented = with_indent(pi!(@i; nl items(args_items.into()))); @@ -447,6 +446,7 @@ } impl Printable for ObjBody { + #[allow(clippy::too_many_lines)] fn print(&self, out: &mut PrintItems) { match self { Self::ObjBodyComp(l) => { @@ -507,6 +507,30 @@ p!(out, nl { + fn gen_members( + children: Vec>, + multi_line: ConditionResolver, + ) -> PrintItems { + let mut out = PrintItems::new(); + let mut members = children.into_iter().peekable(); + while let Some(mem) = members.next() { + if mem.should_start_with_newline { + p!(out, nl); + } + format_comments(&mem.before_trivia, CommentLocation::AboveItem, &mut out); + p!(&mut out, { mem.value }); + let has_more = members.peek().is_some(); + if has_more { + p!(out, str(",")); + } else { + p!(out, if("trailing comma", multi_line, str(","))); + } + format_comments(&mem.inline_trivia, CommentLocation::ItemInline, &mut out); + p!(out, if_else("member separator", multi_line, nl)(sonl)); + } + out + } + let (children, end_comments) = children_between::( l.syntax().clone(), l.l_brace_token().map(Into::into).as_ref(), @@ -531,31 +555,6 @@ }) }; - fn gen_members( - children: Vec>, - multi_line: ConditionResolver, - ) -> PrintItems { - let mut _out = PrintItems::new(); - let out = &mut _out; - let mut members = children.into_iter().peekable(); - while let Some(mem) = members.next() { - if mem.should_start_with_newline { - p!(out, nl); - } - format_comments(&mem.before_trivia, CommentLocation::AboveItem, out); - p!(out, { mem.value }); - let has_more = members.peek().is_some(); - if has_more { - p!(out, str(",")); - } else { - p!(out, if("trailing comma", multi_line, str(","))); - } - format_comments(&mem.inline_trivia, CommentLocation::ItemInline, out); - p!(out, if_else("member separator", multi_line, nl)(sonl)); - } - _out - } - let members_items = new_line_group(gen_members(children, multi_line.clone())).into_rc_path(); @@ -718,6 +717,27 @@ impl Printable for ExprArray { fn print(&self, out: &mut PrintItems) { + fn gen_elements(children: Vec>, multi_line: ConditionResolver) -> PrintItems { + let mut out = PrintItems::new(); + let mut els = children.into_iter().peekable(); + while let Some(el) = els.next() { + if el.should_start_with_newline { + p!(out, nl); + } + format_comments(&el.before_trivia, CommentLocation::AboveItem, &mut out); + p!(&mut out, { el.value }); + let has_more = els.peek().is_some(); + if has_more { + p!(out, str(",")); + } else { + p!(out, if("trailing comma", multi_line, str(","))); + } + format_comments(&el.inline_trivia, CommentLocation::ItemInline, &mut out); + p!(out, if_else("element separator", multi_line, nl)(sonl)); + } + out + } + let (children, end_comments) = children_between::( self.syntax().clone(), self.l_brack_token().map(Into::into).as_ref(), @@ -740,28 +760,6 @@ Rc::new(move |ctx: &mut ConditionResolverContext| is_multiple_lines(ctx, start, end)) }; - fn gen_elements(children: Vec>, multi_line: ConditionResolver) -> PrintItems { - let mut _out = PrintItems::new(); - let out = &mut _out; - let mut els = children.into_iter().peekable(); - while let Some(el) = els.next() { - if el.should_start_with_newline { - p!(out, nl); - } - format_comments(&el.before_trivia, CommentLocation::AboveItem, out); - p!(out, { el.value }); - let has_more = els.peek().is_some(); - if has_more { - p!(out, str(",")); - } else { - p!(out, if("trailing comma", multi_line, str(","))); - } - format_comments(&el.inline_trivia, CommentLocation::ItemInline, out); - p!(out, if_else("element separator", multi_line, nl)(sonl)) - } - _out - } - let els_items = new_line_group(gen_elements(children, multi_line.clone())).into_rc_path(); let els = with_indent_eoi(multi_line, els_items.into(), end_comments); @@ -800,7 +798,7 @@ Self::ExprString(s) => p!(out, { s.text() }), Self::ExprNumber(n) => p!(out, { n.number() }), Self::ExprArray(a) => { - p!(out, { a }) + p!(out, { a }); } Self::ExprObject(obj) => { p!(out, { obj.obj_body() }); @@ -860,6 +858,11 @@ // 0 for hard tabs pub indent: u8, } + +#[allow( + clippy::result_large_err, + reason = "TODO: there should be an intermediate representation for such reports" +)] pub fn format(input: &str, opts: &FormatOptions) -> Result { let (parsed, errors) = jrsonnet_rowan_parser::parse(input); if !errors.is_empty() { --- 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)?; } } }, --- 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, Option>)>, + #[allow(clippy::type_complexity)] + fields: Vec<(IStr, Option, Option>>)>, rest: Option, }, } @@ -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, } --- 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} --- 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 { --- 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 --- 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) { --- 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, --- 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); --- 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, StringBlockError> { +pub fn collect_lexed_str_block(input: &str) -> Result, 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); } } --- 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(); --- 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, --- a/tests/tests/common.rs +++ b/tests/tests/common.rs @@ -41,6 +41,7 @@ } #[builtin] +#[allow(dead_code)] fn assert_throw(lazy: Thunk, message: String) -> Result { match lazy.evaluate() { Ok(_) => { @@ -55,6 +56,7 @@ } #[builtin] +#[allow(dead_code)] fn param_names(fun: FuncVal) -> Vec { fun.params() .iter() --- 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, 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, b: u16, } -#[derive(Clone, Typed, PartialEq, Debug)] +#[derive(Clone, Typed, FromUntyped, IntoUntyped, PartialEq, Debug)] struct E { v: u32, } --- 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));