diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..71607d0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: +- package-ecosystem: github-actions + directory: "/" + schedule: + interval: daily diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d577df7..06628da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,78 +11,55 @@ env: jobs: build_and_test: - name: Deluxe + name: Build & Test + strategy: + matrix: + features: ["--all-features", "--no-default-features"] runs-on: ubuntu-latest timeout-minutes: 45 steps: - - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - run: cargo build -r --all-features --workspace - - run: cargo test -r --all-features --workspace - - build_and_test_no_default: - name: Deluxe No Default Features - runs-on: ubuntu-latest - timeout-minutes: 45 - steps: - - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - run: cargo build -r --no-default-features --workspace - - run: cargo test -r --no-default-features --workspace + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + - run: cargo build -r ${{ matrix.features }} --workspace + - run: cargo test -r ${{ matrix.features }} --workspace rustfmt: - name: Deluxe Rustfmt + name: Rustfmt runs-on: ubuntu-latest timeout-minutes: 45 steps: - - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly with: - profile: minimal - toolchain: stable - override: true components: rustfmt - - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check + - run: cargo fmt --all --check clippy: - name: Deluxe Clippy + name: Clippy runs-on: ubuntu-latest timeout-minutes: 45 steps: - - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly with: - profile: minimal - toolchain: stable - override: true components: clippy - - uses: actions-rs/cargo@v1 - with: - command: clippy - args: --workspace + - run: cargo clippy --workspace --all-targets docs: - name: Deluxe Docs + name: Docs runs-on: ubuntu-latest timeout-minutes: 45 steps: - - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - components: rust-docs - - uses: actions-rs/cargo@v1 - with: - command: doc - args: --workspace + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo doc --workspace --no-deps + + msrv: + runs-on: ubuntu-latest + env: + CARGO_NET_GIT_FETCH_WITH_CLI: true + steps: + - uses: actions/checkout@v4 + - uses: taiki-e/install-action@cargo-no-dev-deps + - uses: dtolnay/rust-toolchain@1.67.1 + - run: cargo no-dev-deps check diff --git a/Cargo.toml b/Cargo.toml index 6e842e3..5300989 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ readme = "README.md" keywords = ["macros", "derive", "attributes"] include = ["/src", "/tests", "/README.md", "/COPYING"] resolver = "2" +rust-version = "1.67.1" [features] default = ["full", "proc-macro"] diff --git a/README.md b/README.md index 9c44f17..5d3544e 100644 --- a/README.md +++ b/README.md @@ -89,9 +89,8 @@ pub fn derive_my_description(item: TokenStream) -> TokenStream { let mut input = syn::parse::(item).unwrap(); // Extract a description, modifying `input.attrs` to remove the matched attributes. - let MyDescription { name, version } = match deluxe::extract_attributes(&mut input) { - Ok(desc) => desc, - Err(e) => return e.into_compile_error().into() + let Ok(MyDescription { name, version }) = deluxe::extract_attributes(&mut input) else { + return e.into_compile_error().into() }; let ident = &input.ident; @@ -136,9 +135,8 @@ pub fn my_desc( attr: proc_macro::TokenStream, item: proc_macro::TokenStream, ) -> proc_macro::TokenStream { - let MyDescription { name, version } = match deluxe::parse::(attr) { - Ok(desc) => desc, - Err(e) => return e.into_compile_error().into() + let Ok(MyDescription { name, version }) = deluxe::parse(attr) else { + return e.into_compile_error().into() }; let tokens = quote::quote! { @@ -305,9 +303,8 @@ pub fn my_desc_mod( attr: proc_macro::TokenStream, item: proc_macro::TokenStream, ) -> proc_macro::TokenStream { - let mut module = syn::parse::(item) { - Ok(module) => module, - Err(e) => return e.into_compile_error().into() + let mut Ok(module) = syn::parse::(item) else { + return e.into_compile_error().into() }; let errors = deluxe::Errors::new(); @@ -533,9 +530,8 @@ pub fn derive_my_object(item: TokenStream) -> TokenStream { let input = syn::parse::(item).unwrap(); // `obj.container` now holds a reference to `input` - let obj: MyObject = match deluxe::parse_attributes(&input) { - Ok(obj) => obj, - Err(e) => return e.into_compile_error().into() + let Ok(obj: MyObject) = deluxe::parse_attributes(&input) else { + return e.into_compile_error().into() }; let tokens = quote::quote! { /* ... generate some code here ... */ }; diff --git a/core/parse_helpers.rs b/core/parse_helpers.rs index 18748bd..d37b5db 100644 --- a/core/parse_helpers.rs +++ b/core/parse_helpers.rs @@ -939,8 +939,10 @@ where P: crate::ParseAttributes<'t, T>, T: crate::HasAttributes, { - T::attrs(input).iter().filter_map(|a| { - P::path_matches(a.path()).then(|| { + T::attrs(input) + .iter() + .filter(|&a| P::path_matches(a.path())) + .map(|a| { let value = match &a.meta { syn::Meta::Path(_) => Default::default(), syn::Meta::List(list) => proc_macro2::TokenTree::Group(proc_macro2::Group::new( @@ -956,7 +958,6 @@ where }; (value, key_to_string(a.path()), a.path().span()) }) - }) } /// Returns an iterator of [`TokenStream`](proc_macro2::TokenStream)s and the corresponding path diff --git a/core/small_string.rs b/core/small_string.rs index 1ecd2b8..7e7bfb9 100644 --- a/core/small_string.rs +++ b/core/small_string.rs @@ -103,6 +103,7 @@ impl<'a> Ord for SmallString<'a> { } } +#[allow(clippy::non_canonical_partial_ord_impl)] impl<'a> PartialOrd for SmallString<'a> { #[inline] fn partial_cmp(&self, other: &Self) -> Option { diff --git a/macros/parse_attributes.rs b/macros/parse_attributes.rs index d4bcdc1..70ff942 100644 --- a/macros/parse_attributes.rs +++ b/macros/parse_attributes.rs @@ -186,7 +186,7 @@ pub fn impl_parse_attributes(input: syn::DeriveInput, errors: &Errors, mode: Mod return Default::default(); } }; - let AttrImpl { + let Some(AttrImpl { parse, crate_path: crate_, priv_path: priv_, @@ -194,9 +194,9 @@ pub fn impl_parse_attributes(input: syn::DeriveInput, errors: &Errors, mode: Mod container_field, mut container_lifetime, container_ty, - } = match attr { - Some(a) => a, - None => return Default::default(), + }) = attr + else { + return TokenStream::default(); }; let ident = &input.ident; diff --git a/macros/parse_meta_item.rs b/macros/parse_meta_item.rs index 099e0b2..630ca3a 100644 --- a/macros/parse_meta_item.rs +++ b/macros/parse_meta_item.rs @@ -335,7 +335,8 @@ pub fn impl_parse_meta_item(input: syn::DeriveInput, errors: &Errors) -> TokenSt return Default::default(); } }; - let MetaDef { + + let Some(MetaDef { parse, inline, flag, @@ -343,9 +344,9 @@ pub fn impl_parse_meta_item(input: syn::DeriveInput, errors: &Errors) -> TokenSt extra, crate_path: crate_, priv_path: priv_, - } = match meta { - Some(m) => m, - None => return Default::default(), + }) = meta + else { + return TokenStream::default(); }; let ident = &input.ident; diff --git a/macros/types/enum.rs b/macros/types/enum.rs index df0bdb3..ac74655 100644 --- a/macros/types/enum.rs +++ b/macros/types/enum.rs @@ -176,9 +176,8 @@ impl<'e> ParseAttributes<'e, syn::DeriveInput> for Enum<'e> { parse_helpers::parse_struct_attr_tokens( parse_helpers::ref_tokens::(i), |inputs, _| { - let enum_ = match &i.data { - syn::Data::Enum(e) => e, - _ => return Err(syn::Error::new_spanned(i, "wrong DeriveInput type")), + let syn::Data::Enum(enum_) = &i.data else { + return Err(syn::Error::new_spanned(i, "wrong DeriveInput type")); }; let errors = crate::Errors::new(); let mut default = FieldStatus::::None; diff --git a/macros/types/field.rs b/macros/types/field.rs index a02e729..eaef790 100644 --- a/macros/types/field.rs +++ b/macros/types/field.rs @@ -507,9 +507,13 @@ impl<'f> Field<'f> { .enumerate() .map(|(i, _)| quote::format_ident!("field{i}", span = Span::mixed_site())) .collect::>(); - let container_def = fields.iter().enumerate().filter_map(|(i, f)| { - (f.is_container() && *mode != TokenMode::ParseMetaItem).then(|| { - let name = names[i].clone(); + let container_def = fields + .iter() + .zip(&names) + .filter_map(|(f, name)| { + (f.is_container() && *mode != TokenMode::ParseMetaItem).then_some(name) + }) + .map(|name| { let func = match mode { TokenMode::ParseAttributes => quote! { container_from }, TokenMode::ExtractAttributes => quote! { container_from_mut }, @@ -518,8 +522,7 @@ impl<'f> Field<'f> { quote_mixed! { #name = #priv_::FieldStatus::Some(#crate_::ContainerFrom::#func(obj)); } - }) - }); + }); let field_errors = { let mut cur_index = 0usize; let mut extra_counts = quote! {}; @@ -685,14 +688,16 @@ impl<'f> Field<'f> { #(#transforms)* } }); - let field_unwraps = fields.iter().enumerate().filter_map(|(i, _)| { - (!matches!(target, ParseTarget::Var(_))).then(|| { - let name = &names[i]; - quote_mixed! { - let #name = #name.unwrap_or_else(|| #priv_::unreachable!()); - } + let field_unwraps = (!matches!(target, ParseTarget::Var(_))) + .then(|| { + names.iter().take(fields.len()).map(|name| { + quote_mixed! { + let #name = #name.unwrap_or_else(|| #priv_::unreachable!()); + } + }) }) - }); + .into_iter() + .flatten(); let option_inits = fields.iter().enumerate().map(|(i, f)| { let name = &names[i]; diff --git a/macros/types/struct.rs b/macros/types/struct.rs index fe2c252..69c3cb4 100644 --- a/macros/types/struct.rs +++ b/macros/types/struct.rs @@ -398,9 +398,8 @@ impl<'s> ParseAttributes<'s, syn::DeriveInput> for Struct<'s> { parse_helpers::parse_struct_attr_tokens( parse_helpers::ref_tokens::(i), |inputs, _| { - let struct_ = match &i.data { - syn::Data::Struct(s) => s, - _ => return Err(syn::Error::new_spanned(i, "wrong DeriveInput type")), + let syn::Data::Struct(struct_) = &i.data else { + return Err(syn::Error::new_spanned(i, "wrong DeriveInput type")); }; let errors = crate::Errors::new(); let mut transparent = FieldStatus::None;