diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2468f4f..5fad259 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,17 +32,9 @@ jobs: - name: Clippy run: cargo clippy --all - test: - name: Test MSRV - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [windows-latest] - toolchain: [stable] - include: - - os: ubuntu-latest - toolchain: "1.56.0" + stable: + name: Stable on Windows + runs-on: windows-latest steps: - uses: actions/checkout@v2 @@ -50,7 +42,7 @@ jobs: uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: ${{ matrix.toolchain }} + toolchain: stable override: true components: clippy @@ -58,3 +50,20 @@ jobs: run: cargo test --all-features - name: Clippy (stable) run: cargo clippy --all -- -D warnings -A unknown_lints + + msrv: + name: MSRV + runs-on: macos-latest + + steps: + - uses: actions/checkout@v2 + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: "1.56.0" + override: true + components: clippy + + - name: Test + run: cargo test --all-features --lib --tests diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e96a26a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.1.0] — 2022-03-21 + +New release, including the `autoimpl` macro (extracted from `kas-macros` crate). diff --git a/Cargo.toml b/Cargo.toml index a0e9176..1d5a31c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "impl-tools" -version = "0.0.0" +version = "0.1.0" authors = ["Diggory Hardy "] edition = "2021" license = "MIT/Apache-2.0" -description = "A set of helper macros" +description = "Helper macros: autoimpl" keywords = ["proc-macro", "macro", "derive", "trait", "procedural"] categories = ["development-tools::procedural-macro-helpers"] repository = "https://github.com/kas-gui/impl-tools" @@ -24,3 +24,6 @@ version = "1.0.14" # We need 'extra-traits' for equality testing # We need 'full' for parsing macros within macro arguments features = ["extra-traits", "full"] + +[dev-dependencies] +doc-comment = "0.3.3" diff --git a/README.md b/README.md index ce080a8..7705b7c 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,59 @@ Impltools A set of helper macros +Macros +------ + +### Autoimpl + +`#[autoimpl]` is a variant of `#[derive]`, supporting: + +- explicit generic parameter bounds +- ignored fields +- traits defined using a primary field +- generic re-implementations for traits + +```rust +# use impl_tools::autoimpl; +# use std::fmt::Debug; + +#[autoimpl(for<'a, T: trait + ?Sized> Box)] +// Generates: impl<'a, T: trait + ?Sized> Animal for Box { .. } +trait Animal { + fn number_of_legs(&self) -> u32; +} + +#[autoimpl(Debug ignore self.animal where T: Debug)] +// Generates: impl std::fmt::Debug for Named where T: Debug { .. } +#[autoimpl(Deref, DerefMut using self.animal)] +// Generates: impl std::ops::Deref for Named { .. } +// Generates: impl std::ops::DerefMut for Named { .. } +struct Named { + name: T, + animal: A, +} + +fn main() { + struct Fish; + impl Animal for Fish { + fn number_of_legs(&self) -> u32 { + 0 + } + } + + let my_fish = Named { + name: "Nemo", + animal: Box::new(Fish), + }; + + assert_eq!( + format!("{my_fish:?} has {} legs!", my_fish.number_of_legs()), + r#"Named { name: "Nemo", .. } has 0 legs!"# + ); +} +``` + + Minimum Supported Rust Version ------------------------------ diff --git a/src/lib.rs b/src/lib.rs index 1df328a..8b54f77 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,58 @@ // https://www.apache.org/licenses/LICENSE-2.0 //! # Impl-tools +//! +//! ## Autoimpl +//! +//! `#[autoimpl]` is a variant of `#[derive]`, supporting: +//! +//! - explicit generic parameter bounds +//! - ignored fields +//! - traits defined using a primary field +//! - generic re-implementations for traits +//! +//! ``` +//! # use impl_tools::autoimpl; +//! # use std::fmt::Debug; +//! +//! #[autoimpl(for<'a, T: trait + ?Sized> Box)] +//! // Generates: impl<'a, T: trait + ?Sized> Animal for Box { .. } +//! trait Animal { +//! fn number_of_legs(&self) -> u32; +//! } +//! +//! #[autoimpl(Debug ignore self.animal where T: Debug)] +//! // Generates: impl std::fmt::Debug for Named where T: Debug { .. } +//! #[autoimpl(Deref, DerefMut using self.animal)] +//! // Generates: impl std::ops::Deref for Named { .. } +//! // Generates: impl std::ops::DerefMut for Named { .. } +//! struct Named { +//! name: T, +//! animal: A, +//! } +//! +//! fn main() { +//! struct Fish; +//! impl Animal for Fish { +//! fn number_of_legs(&self) -> u32 { +//! 0 +//! } +//! } +//! +//! let my_fish = Named { +//! name: "Nemo", +//! animal: Box::new(Fish), +//! }; +//! +//! assert_eq!( +//! format!("{my_fish:?} has {} legs!", my_fish.number_of_legs()), +//! r#"Named { name: "Nemo", .. } has 0 legs!"# +//! ); +//! } +//! ``` + +#[cfg(doctest)] +doc_comment::doctest!("../README.md"); extern crate proc_macro;