getset-0.1.2/.cargo_vcs_info.json0000644000000001120000000000100123210ustar { "git": { "sha1": "e540fd438dada61f39f81a5cc87192cce9c9d1e0" } } getset-0.1.2/.dependabot/config.yml000064400000000000000000000003000072674642500153130ustar 00000000000000version: 1 update_configs: - package_manager: "rust:cargo" directory: "/" update_schedule: "live" default_reviewers: - "hoverbear" default_labels: - "dependency" getset-0.1.2/.github/actions-rs/grcov.yml000064400000000000000000000002260072674642500164340ustar 00000000000000branch: true ignore-not-existing: true llvm: true filter: covered output-type: lcov output-file: /tmp/lcov.info ignore: - "/*" - "C:/*" - "../*"getset-0.1.2/.github/workflows/audit.yml000064400000000000000000000006760072674642500164060ustar 00000000000000name: audit on: schedule: - cron: '0 0 * * *' push: jobs: audit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Cache target id: cache-target uses: actions/cache@v1 with: path: target key: ${{ runner.os }}-audit-target-${{ hashFiles('**/Cargo.toml') }} - uses: actions-rs/audit-check@v1 with: token: ${{ secrets.GITHUB_TOKEN }}getset-0.1.2/.github/workflows/test.yml000064400000000000000000000034120072674642500162460ustar 00000000000000name: test on: push: pull_request: env: RUSTFLAGS: "--deny=warnings" jobs: test: strategy: matrix: os: [macos-latest, windows-latest, ubuntu-latest] rust: [stable, nightly] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v1 - name: Cache target id: cache-target uses: actions/cache@v1 with: path: target key: ${{ runner.os }}-${{ matrix.rust }}-test-target-${{ hashFiles('**/Cargo.toml') }} - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: toolchain: ${{ matrix.rust }} - name: Test uses: actions-rs/cargo@v1 with: command: test args: -- --nocapture clippy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Cache target id: cache-target uses: actions/cache@v1 with: path: target key: ${{ runner.os }}-clippy-target-${{ hashFiles('**/Cargo.toml') }} - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: toolchain: stable - run: rustup component add clippy - uses: actions-rs/clippy-check@v1 with: token: ${{ secrets.GITHUB_TOKEN }} format: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Cache target id: cache-target uses: actions/cache@v1 with: path: target key: ${{ runner.os }}-format-target-${{ hashFiles('**/Cargo.toml') }} - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: toolchain: stable - run: rustup component add rustfmt - uses: actions-rs/cargo@v1 with: command: fmt args: -- --check getset-0.1.2/.gitignore000064400000000000000000000000370072674642500131370ustar 00000000000000/target/ **/*.rs.bk Cargo.lock getset-0.1.2/Cargo.lock0000644000000035360000000000100103110ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "getset" version = "0.1.2" dependencies = [ "proc-macro-error", "proc-macro2", "quote", "syn", ] [[package]] name = "proc-macro-error" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", "syn", "version_check", ] [[package]] name = "proc-macro-error-attr" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2", "quote", "version_check", ] [[package]] name = "proc-macro2" version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" dependencies = [ "unicode-xid", ] [[package]] name = "quote" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" dependencies = [ "proc-macro2", ] [[package]] name = "syn" version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "version_check" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" getset-0.1.2/Cargo.toml0000644000000022350000000000100103270ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "getset" version = "0.1.2" authors = ["Ana Hobden "] description = "Getset, we're ready to go!\n\nA procedural macro for generating the most basic getters and setters on fields.\n" readme = "README.md" keywords = ["macro", "getter", "setter", "getters", "setters"] categories = ["development-tools::procedural-macro-helpers"] license = "MIT" repository = "https://github.com/Hoverbear/getset" [lib] proc-macro = true [dependencies.proc-macro-error] version = "1.0" [dependencies.proc-macro2] version = "1" default-features = false [dependencies.quote] version = "1" [dependencies.syn] version = "1" getset-0.1.2/Cargo.toml.orig000064400000000000000000000011230072674642500140330ustar 00000000000000[package] name = "getset" description = """ Getset, we're ready to go! A procedural macro for generating the most basic getters and setters on fields. """ version = "0.1.2" authors = ["Ana Hobden "] license = "MIT" edition = "2018" categories = ["development-tools::procedural-macro-helpers"] keywords = ["macro", "getter", "setter", "getters", "setters"] readme = "README.md" repository = "https://github.com/Hoverbear/getset" [lib] proc-macro = true [dependencies] quote = "1" syn = "1" proc-macro2 = { version = "1", default-features = false } proc-macro-error = "1.0" getset-0.1.2/LICENSE000064400000000000000000000020550072674642500121560ustar 00000000000000MIT License Copyright (c) [year] [fullname] Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. getset-0.1.2/README.md000064400000000000000000000107410072674642500124310ustar 00000000000000# getset [![Download](https://img.shields.io/crates/d/getset)](https://crates.io/crates/getset) [![License](https://img.shields.io/crates/l/getset)](https://github.com/Hoverbear/getset/blob/master/LICENSE) [![Docs](https://docs.rs/getset/badge.svg)](https://docs.rs/getset/) [![Coverage Status](https://coveralls.io/repos/github/Hoverbear/getset/badge.svg)](https://coveralls.io/github/Hoverbear/getset) Getset, we're ready to go! A procedural macro for generating the most basic getters and setters on fields. Getters are generated as `fn field(&self) -> &type`, while setters are generated as `fn field(&mut self, val: type)`. These macros are not intended to be used on fields which require custom logic inside of their setters and getters. Just write your own in that case! ```rust use getset::{CopyGetters, Getters, MutGetters, Setters}; #[derive(Getters, Setters, MutGetters, CopyGetters, Default)] pub struct Foo where T: Copy + Clone + Default, { /// Doc comments are supported! /// Multiline, even. #[getset(get, set, get_mut)] private: T, /// Doc comments are supported! /// Multiline, even. #[getset(get_copy = "pub", set = "pub", get_mut = "pub")] public: T, } fn main() { let mut foo = Foo::default(); foo.set_private(1); (*foo.private_mut()) += 1; assert_eq!(*foo.private(), 2); } ``` You can use `cargo-expand` to generate the output. Here are the functions that the above generates (Replicate with `cargo expand --example simple`): ```rust use getset::{Getters, MutGetters, CopyGetters, Setters}; pub struct Foo where T: Copy + Clone + Default, { /// Doc comments are supported! /// Multiline, even. #[getset(get, get, get_mut)] private: T, /// Doc comments are supported! /// Multiline, even. #[getset(get_copy = "pub", set = "pub", get_mut = "pub")] public: T, } impl Foo where T: Copy + Clone + Default, { /// Doc comments are supported! /// Multiline, even. #[inline(always)] fn private(&self) -> &T { &self.private } } impl Foo where T: Copy + Clone + Default, { /// Doc comments are supported! /// Multiline, even. #[inline(always)] pub fn set_public(&mut self, val: T) -> &mut Self { self.public = val; self } } impl Foo where T: Copy + Clone + Default, { /// Doc comments are supported! /// Multiline, even. #[inline(always)] fn private_mut(&mut self) -> &mut T { &mut self.private } /// Doc comments are supported! /// Multiline, even. #[inline(always)] pub fn public_mut(&mut self) -> &mut T { &mut self.public } } impl Foo where T: Copy + Clone + Default, { /// Doc comments are supported! /// Multiline, even. #[inline(always)] pub fn public(&self) -> T { self.public } } ``` Attributes can be set on struct level for all fields in struct as well. Field level attributes take precedence. ```rust #[macro_use] extern crate getset; mod submodule { #[derive(Getters, CopyGetters, Default)] #[get_copy = "pub"] // By default add a pub getting for all fields. pub struct Foo { public: i32, #[get_copy] // Override as private private: i32, } fn demo() { let mut foo = Foo::default(); foo.private(); } } fn main() { let mut foo = submodule::Foo::default(); foo.public(); } ``` For some purposes, it's useful to have the `get_` prefix on the getters for either legacy of compatability reasons. It is done with `with_prefix`. ```rust #[macro_use] extern crate getset; #[derive(Getters, Default)] pub struct Foo { #[get = "pub with_prefix"] field: bool, } fn main() { let mut foo = Foo::default(); let val = foo.get_field(); } ``` Skipping setters and getters generation for a field when struct level attribute is used is possible with `#[getset(skip)]`. ```rust use getset::{CopyGetters, Setters}; #[derive(CopyGetters, Setters)] #[getset(get_copy, set)] pub struct Foo { // If the field was not skipped, the compiler would complain about moving // a non-copyable type in copy getter. #[getset(skip)] skipped: String, field1: usize, field2: usize, } impl Foo { // It is possible to write getters and setters manually, // possibly with a custom logic. fn skipped(&self) -> &str { &self.skipped } fn set_skipped(&mut self, val: &str) -> &mut Self { self.skipped = val.to_string(); self } } ``` getset-0.1.2/examples/simple.rs000064400000000000000000000010670072674642500146300ustar 00000000000000use getset::{CopyGetters, Getters, MutGetters, Setters}; #[derive(Getters, Setters, MutGetters, CopyGetters, Default)] pub struct Foo where T: Copy + Clone + Default, { /// Doc comments are supported! /// Multiline, even. #[getset(get, set, get_mut)] private: T, /// Doc comments are supported! /// Multiline, even. #[getset(get_copy = "pub", set = "pub", get_mut = "pub")] public: T, } fn main() { let mut foo = Foo::default(); foo.set_private(1); (*foo.private_mut()) += 1; assert_eq!(*foo.private(), 2); } getset-0.1.2/src/generate.rs000064400000000000000000000130130072674642500140740ustar 00000000000000use proc_macro2::TokenStream as TokenStream2; use proc_macro2::{Ident, Span}; use proc_macro_error::{abort, ResultExt}; use syn::{self, ext::IdentExt, spanned::Spanned, Field, Lit, Meta, MetaNameValue, Visibility}; use self::GenMode::*; use super::parse_attr; pub struct GenParams { pub mode: GenMode, pub global_attr: Option, } #[derive(PartialEq, Eq, Copy, Clone)] pub enum GenMode { Get, GetCopy, Set, GetMut, } impl GenMode { pub fn name(self) -> &'static str { match self { Get => "get", GetCopy => "get_copy", Set => "set", GetMut => "get_mut", } } pub fn prefix(self) -> &'static str { match self { Get | GetCopy | GetMut => "", Set => "set_", } } pub fn suffix(self) -> &'static str { match self { Get | GetCopy | Set => "", GetMut => "_mut", } } fn is_get(self) -> bool { match self { GenMode::Get | GenMode::GetCopy | GenMode::GetMut => true, GenMode::Set => false, } } } pub fn parse_visibility(attr: Option<&Meta>, meta_name: &str) -> Option { match attr { // `#[get = "pub"]` or `#[set = "pub"]` Some(Meta::NameValue(MetaNameValue { lit: Lit::Str(ref s), path, .. })) => { if path.is_ident(meta_name) { s.value().split(' ').find(|v| *v != "with_prefix").map(|v| { syn::parse_str(v) .map_err(|e| syn::Error::new(s.span(), e)) .expect_or_abort("invalid visibility found") }) } else { None } } _ => None, } } /// Some users want legacy/compatability. /// (Getters are often prefixed with `get_`) fn has_prefix_attr(f: &Field, params: &GenParams) -> bool { let inner = f .attrs .iter() .filter_map(|v| parse_attr(v, params.mode)) .filter(|meta| { ["get", "get_copy"] .iter() .any(|ident| meta.path().is_ident(ident)) }) .last(); // Check it the attr includes `with_prefix` let wants_prefix = |possible_meta: &Option| -> bool { match possible_meta { Some(Meta::NameValue(meta)) => { if let Lit::Str(lit_str) = &meta.lit { // Naive tokenization to avoid a possible visibility mod named `with_prefix`. lit_str.value().split(' ').any(|v| v == "with_prefix") } else { false } } _ => false, } }; // `with_prefix` can either be on the local or global attr wants_prefix(&inner) || wants_prefix(¶ms.global_attr) } pub fn implement(field: &Field, params: &GenParams) -> TokenStream2 { let field_name = field .clone() .ident .unwrap_or_else(|| abort!(field.span(), "Expected the field to have a name")); let fn_name = if !has_prefix_attr(field, params) && (params.mode.is_get()) && params.mode.suffix().is_empty() && field_name.to_string().starts_with("r#") { field_name.clone() } else { Ident::new( &format!( "{}{}{}{}", if has_prefix_attr(field, params) && (params.mode.is_get()) { "get_" } else { "" }, params.mode.prefix(), field_name.unraw(), params.mode.suffix() ), Span::call_site(), ) }; let ty = field.ty.clone(); let doc = field.attrs.iter().filter(|v| { v.parse_meta() .map(|meta| meta.path().is_ident("doc")) .unwrap_or(false) }); let attr = field .attrs .iter() .filter_map(|v| parse_attr(v, params.mode)) .last() .or_else(|| params.global_attr.clone()); let visibility = parse_visibility(attr.as_ref(), params.mode.name()); match attr { // Generate nothing for skipped field. Some(meta) if meta.path().is_ident("skip") => quote! {}, Some(_) => match params.mode { GenMode::Get => { quote! { #(#doc)* #[inline(always)] #visibility fn #fn_name(&self) -> &#ty { &self.#field_name } } } GenMode::GetCopy => { quote! { #(#doc)* #[inline(always)] #visibility fn #fn_name(&self) -> #ty { self.#field_name } } } GenMode::Set => { quote! { #(#doc)* #[inline(always)] #visibility fn #fn_name(&mut self, val: #ty) -> &mut Self { self.#field_name = val; self } } } GenMode::GetMut => { quote! { #(#doc)* #[inline(always)] #visibility fn #fn_name(&mut self) -> &mut #ty { &mut self.#field_name } } } }, // Don't need to do anything. None => quote! {}, } } getset-0.1.2/src/lib.rs000064400000000000000000000227110072674642500130550ustar 00000000000000/*! Getset, we're ready to go! A procedural macro for generating the most basic getters and setters on fields. Getters are generated as `fn field(&self) -> &type`, while setters are generated as `fn field(&mut self, val: type)`. These macros are not intended to be used on fields which require custom logic inside of their setters and getters. Just write your own in that case! ```rust use getset::{CopyGetters, Getters, MutGetters, Setters}; #[derive(Getters, Setters, MutGetters, CopyGetters, Default)] pub struct Foo where T: Copy + Clone + Default, { /// Doc comments are supported! /// Multiline, even. #[getset(get, set, get_mut)] private: T, /// Doc comments are supported! /// Multiline, even. #[getset(get_copy = "pub", set = "pub", get_mut = "pub")] public: T, } let mut foo = Foo::default(); foo.set_private(1); (*foo.private_mut()) += 1; assert_eq!(*foo.private(), 2); ``` You can use `cargo-expand` to generate the output. Here are the functions that the above generates (Replicate with `cargo expand --example simple`): ```rust,ignore use getset::{Getters, MutGetters, CopyGetters, Setters}; pub struct Foo where T: Copy + Clone + Default, { /// Doc comments are supported! /// Multiline, even. #[getset(get, get, get_mut)] private: T, /// Doc comments are supported! /// Multiline, even. #[getset(get_copy = "pub", set = "pub", get_mut = "pub")] public: T, } impl Foo where T: Copy + Clone + Default, { /// Doc comments are supported! /// Multiline, even. #[inline(always)] fn private(&self) -> &T { &self.private } } impl Foo where T: Copy + Clone + Default, { /// Doc comments are supported! /// Multiline, even. #[inline(always)] pub fn set_public(&mut self, val: T) -> &mut Self { self.public = val; self } } impl Foo where T: Copy + Clone + Default, { /// Doc comments are supported! /// Multiline, even. #[inline(always)] fn private_mut(&mut self) -> &mut T { &mut self.private } /// Doc comments are supported! /// Multiline, even. #[inline(always)] pub fn public_mut(&mut self) -> &mut T { &mut self.public } } impl Foo where T: Copy + Clone + Default, { /// Doc comments are supported! /// Multiline, even. #[inline(always)] pub fn public(&self) -> T { self.public } } ``` Attributes can be set on struct level for all fields in struct as well. Field level attributes take precedence. ```rust mod submodule { use getset::{Getters, MutGetters, CopyGetters, Setters}; #[derive(Getters, CopyGetters, Default)] #[getset(get_copy = "pub")] // By default add a pub getting for all fields. pub struct Foo { public: i32, #[getset(get_copy)] // Override as private private: i32, } fn demo() { let mut foo = Foo::default(); foo.private(); } } let mut foo = submodule::Foo::default(); foo.public(); ``` For some purposes, it's useful to have the `get_` prefix on the getters for either legacy of compatibility reasons. It is done with `with_prefix`. ```rust use getset::{Getters, MutGetters, CopyGetters, Setters}; #[derive(Getters, Default)] pub struct Foo { #[getset(get = "pub with_prefix")] field: bool, } let mut foo = Foo::default(); let val = foo.get_field(); ``` Skipping setters and getters generation for a field when struct level attribute is used is possible with `#[getset(skip)]`. ```rust use getset::{CopyGetters, Setters}; #[derive(CopyGetters, Setters)] #[getset(get_copy, set)] pub struct Foo { // If the field was not skipped, the compiler would complain about moving // a non-copyable type in copy getter. #[getset(skip)] skipped: String, field1: usize, field2: usize, } impl Foo { // It is possible to write getters and setters manually, // possibly with a custom logic. fn skipped(&self) -> &str { &self.skipped } fn set_skipped(&mut self, val: &str) -> &mut Self { self.skipped = val.to_string(); self } } ``` */ extern crate proc_macro; extern crate syn; #[macro_use] extern crate quote; extern crate proc_macro2; use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; use proc_macro_error::{abort, abort_call_site, proc_macro_error, ResultExt}; use syn::{spanned::Spanned, DataStruct, DeriveInput, Meta}; mod generate; use crate::generate::{GenMode, GenParams}; #[proc_macro_derive(Getters, attributes(get, with_prefix, getset))] #[proc_macro_error] pub fn getters(input: TokenStream) -> TokenStream { // Parse the string representation let ast: DeriveInput = syn::parse(input).expect_or_abort("Couldn't parse for getters"); let params = GenParams { mode: GenMode::Get, global_attr: parse_global_attr(&ast.attrs, GenMode::Get), }; // Build the impl let gen = produce(&ast, ¶ms); // Return the generated impl gen.into() } #[proc_macro_derive(CopyGetters, attributes(get_copy, with_prefix, getset))] #[proc_macro_error] pub fn copy_getters(input: TokenStream) -> TokenStream { // Parse the string representation let ast: DeriveInput = syn::parse(input).expect_or_abort("Couldn't parse for getters"); let params = GenParams { mode: GenMode::GetCopy, global_attr: parse_global_attr(&ast.attrs, GenMode::GetCopy), }; // Build the impl let gen = produce(&ast, ¶ms); // Return the generated impl gen.into() } #[proc_macro_derive(MutGetters, attributes(get_mut, getset))] #[proc_macro_error] pub fn mut_getters(input: TokenStream) -> TokenStream { // Parse the string representation let ast: DeriveInput = syn::parse(input).expect_or_abort("Couldn't parse for getters"); let params = GenParams { mode: GenMode::GetMut, global_attr: parse_global_attr(&ast.attrs, GenMode::GetMut), }; // Build the impl let gen = produce(&ast, ¶ms); // Return the generated impl gen.into() } #[proc_macro_derive(Setters, attributes(set, getset))] #[proc_macro_error] pub fn setters(input: TokenStream) -> TokenStream { // Parse the string representation let ast: DeriveInput = syn::parse(input).expect_or_abort("Couldn't parse for setters"); let params = GenParams { mode: GenMode::Set, global_attr: parse_global_attr(&ast.attrs, GenMode::Set), }; // Build the impl let gen = produce(&ast, ¶ms); // Return the generated impl gen.into() } fn parse_global_attr(attrs: &[syn::Attribute], mode: GenMode) -> Option { attrs .iter() .filter_map(|v| parse_attr(v, mode)) // non "meta" attributes are not our concern .last() } fn parse_attr(attr: &syn::Attribute, mode: GenMode) -> Option { use syn::{punctuated::Punctuated, Token}; if attr.path.is_ident("getset") { let (last, skip, mut collected) = attr .parse_args_with(Punctuated::::parse_terminated) .unwrap_or_abort() .into_iter() .inspect(|meta| { if !(meta.path().is_ident("get") || meta.path().is_ident("get_copy") || meta.path().is_ident("get_mut") || meta.path().is_ident("set") || meta.path().is_ident("skip")) { abort!(meta.path().span(), "unknown setter or getter") } }) .fold( (None, None, Vec::new()), |(last, skip, mut collected), meta| { if meta.path().is_ident(mode.name()) { (Some(meta), skip, collected) } else if meta.path().is_ident("skip") { (last, Some(meta), collected) } else { // Store inapplicable item for potential error message // if used with skip. collected.push(meta); (last, skip, collected) } }, ); if skip.is_some() { // Check if there is any setter or getter used with skip, which is // forbidden. if last.is_none() && collected.is_empty() { skip } else { abort!( last.or_else(|| collected.pop()).unwrap().path().span(), "use of setters and getters with skip is invalid" ); } } else { // If skip is not used, return the last occurrence of matching // setter/getter, if there is any. last } } else { attr.parse_meta() .ok() .filter(|meta| meta.path().is_ident(mode.name())) } } fn produce(ast: &DeriveInput, params: &GenParams) -> TokenStream2 { let name = &ast.ident; let generics = &ast.generics; let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); // Is it a struct? if let syn::Data::Struct(DataStruct { ref fields, .. }) = ast.data { let generated = fields.iter().map(|f| generate::implement(f, params)); quote! { impl #impl_generics #name #ty_generics #where_clause { #(#generated)* } } } else { // Nope. This is an Enum. We cannot handle these! abort_call_site!("#[derive(Getters)] is only defined for structs, not for enums!"); } } getset-0.1.2/tests/copy_getters.rs000064400000000000000000000074230072674642500153740ustar 00000000000000#[macro_use] extern crate getset; use crate::submodule::other::{Generic, Plain, Where}; // For testing `pub(super)` mod submodule { // For testing `pub(super::other)` pub mod other { #[derive(CopyGetters)] #[get_copy] pub struct Plain { /// A doc comment. /// Multiple lines, even. private_accessible: usize, /// A doc comment. #[get_copy = "pub"] public_accessible: usize, // /// A doc comment. // #[get_copy = "pub(crate)"] // crate_accessible: usize, // /// A doc comment. // #[get_copy = "pub(super)"] // super_accessible: usize, // /// A doc comment. // #[get_copy = "pub(super::other)"] // scope_accessible: usize, // Prefixed getter. #[get_copy = "with_prefix"] private_prefixed: usize, // Prefixed getter. #[get_copy = "pub with_prefix"] public_prefixed: usize, } impl Default for Plain { fn default() -> Plain { Plain { private_accessible: 17, public_accessible: 18, private_prefixed: 19, public_prefixed: 20, } } } #[derive(CopyGetters, Default)] #[get_copy] pub struct Generic { /// A doc comment. /// Multiple lines, even. private_accessible: T, /// A doc comment. #[get_copy = "pub"] public_accessible: T, // /// A doc comment. // #[get_copy = "pub(crate)"] // crate_accessible: usize, // /// A doc comment. // #[get_copy = "pub(super)"] // super_accessible: usize, // /// A doc comment. // #[get_copy = "pub(super::other)"] // scope_accessible: usize, } #[derive(CopyGetters, Getters, Default)] #[get_copy] pub struct Where where T: Copy + Clone + Default, { /// A doc comment. /// Multiple lines, even. private_accessible: T, /// A doc comment. #[get_copy = "pub"] public_accessible: T, // /// A doc comment. // #[get_copy = "pub(crate)"] // crate_accessible: usize, // /// A doc comment. // #[get_copy = "pub(super)"] // super_accessible: usize, // /// A doc comment. // #[get_copy = "pub(super::other)"] // scope_accessible: usize, } #[test] fn test_plain() { let val = Plain::default(); val.private_accessible(); } #[test] fn test_generic() { let val = Generic::::default(); val.private_accessible(); } #[test] fn test_where() { let val = Where::::default(); val.private_accessible(); } #[test] fn test_prefixed_plain() { let val = Plain::default(); assert_eq!(19, val.get_private_prefixed()); } } } #[test] fn test_plain() { let val = Plain::default(); assert_eq!(18, val.public_accessible()); } #[test] fn test_generic() { let val = Generic::::default(); assert_eq!(usize::default(), val.public_accessible()); } #[test] fn test_where() { let val = Where::::default(); assert_eq!(usize::default(), val.public_accessible()); } #[test] fn test_prefixed_plain() { let val = Plain::default(); assert_eq!(20, val.get_public_prefixed()); } getset-0.1.2/tests/getset.rs000064400000000000000000000063360072674642500141620ustar 00000000000000#[macro_use] extern crate getset; use crate::submodule::other::{Generic, Plain, Where}; // For testing `pub(super)` mod submodule { // For testing `pub(in super::other)` pub mod other { #[derive(MutGetters, Getters, Default)] #[getset(get_mut)] pub struct Plain { /// A doc comment. /// Multiple lines, even. private_accessible: usize, /// A doc comment. #[getset(get = "pub", get_mut = "pub")] public_accessible: usize, // /// A doc comment. // #[get_mut = "pub(crate)"] // crate_accessible: usize, // /// A doc comment. // #[get_mut = "pub(super)"] // super_accessible: usize, // /// A doc comment. // #[get_mut = "pub(in super::other)"] // scope_accessible: usize, } #[derive(MutGetters, Getters, Default)] #[getset(get_mut)] pub struct Generic { /// A doc comment. /// Multiple lines, even. private_accessible: T, /// A doc comment. #[getset(get = "pub", get_mut = "pub")] public_accessible: T, // /// A doc comment. // #[get_mut = "pub(crate)"] // crate_accessible: usize, // /// A doc comment. // #[get_mut = "pub(super)"] // super_accessible: usize, // /// A doc comment. // #[get_mut = "pub(in super::other)"] // scope_accessible: usize, } #[derive(MutGetters, Getters, Default)] #[getset(get_mut)] pub struct Where where T: Copy + Clone + Default, { /// A doc comment. /// Multiple lines, even. private_accessible: T, /// A doc comment. #[getset(get = "pub", get_mut = "pub")] public_accessible: T, // /// A doc comment. // #[get_mut = "pub(crate)"] // crate_accessible: usize, // /// A doc comment. // #[get_mut = "pub(super)"] // super_accessible: usize, // /// A doc comment. // #[get_mut = "pub(in super::other)"] // scope_accessible: usize, } #[test] fn test_plain() { let mut val = Plain::default(); (*val.private_accessible_mut()) += 1; } #[test] fn test_generic() { let mut val = Generic::::default(); (*val.private_accessible_mut()) += 1; } #[test] fn test_where() { let mut val = Where::::default(); (*val.private_accessible_mut()) += 1; } } } #[test] fn test_plain() { let mut val = Plain::default(); let _ = val.public_accessible(); (*val.public_accessible_mut()) += 1; } #[test] fn test_generic() { let mut val = Generic::::default(); let _ = val.public_accessible(); (*val.public_accessible_mut()) += 1; } #[test] fn test_where() { let mut val = Where::::default(); let _ = val.public_accessible(); (*val.public_accessible_mut()) += 1; } getset-0.1.2/tests/getters.rs000064400000000000000000000072650072674642500143460ustar 00000000000000#[macro_use] extern crate getset; use crate::submodule::other::{Generic, Plain, Where}; // For testing `pub(super)` mod submodule { // For testing `pub(super::other)` pub mod other { #[derive(Getters)] #[get] pub struct Plain { /// A doc comment. /// Multiple lines, even. private_accessible: usize, /// A doc comment. #[get = "pub"] public_accessible: usize, // /// A doc comment. // #[get = "pub(crate)"] // crate_accessible: usize, // /// A doc comment. // #[get = "pub(super)"] // super_accessible: usize, // /// A doc comment. // #[get = "pub(super::other)"] // scope_accessible: usize, // Prefixed getter. #[get = "with_prefix"] private_prefixed: usize, // Prefixed getter. #[get = "pub with_prefix"] public_prefixed: usize, } impl Default for Plain { fn default() -> Plain { Plain { private_accessible: 17, public_accessible: 18, private_prefixed: 19, public_prefixed: 20, } } } #[derive(Getters, Default)] #[get] pub struct Generic { /// A doc comment. /// Multiple lines, even. private_accessible: T, /// A doc comment. #[get = "pub(crate)"] public_accessible: T, // /// A doc comment. // #[get = "pub(crate)"] // crate_accessible: usize, // /// A doc comment. // #[get = "pub(super)"] // super_accessible: usize, // /// A doc comment. // #[get = "pub(super::other)"] // scope_accessible: usize, } #[derive(Getters, Default)] #[get] pub struct Where where T: Copy + Clone + Default, { /// A doc comment. /// Multiple lines, even. private_accessible: T, /// A doc comment. #[get = "pub"] public_accessible: T, // /// A doc comment. // #[get = "pub(crate)"] // crate_accessible: usize, // /// A doc comment. // #[get = "pub(super)"] // super_accessible: usize, // /// A doc comment. // #[get = "pub(super::other)"] // scope_accessible: usize, } #[test] fn test_plain() { let val = Plain::default(); val.private_accessible(); } #[test] fn test_generic() { let val = Generic::::default(); val.private_accessible(); } #[test] fn test_where() { let val = Where::::default(); val.private_accessible(); } #[test] fn test_prefixed_plain() { let val = Plain::default(); assert_eq!(19, *val.get_private_prefixed()); } } } #[test] fn test_plain() { let val = Plain::default(); assert_eq!(18, *val.public_accessible()); } #[test] fn test_generic() { let val = Generic::::default(); assert_eq!(usize::default(), *val.public_accessible()); } #[test] fn test_where() { let val = Where::::default(); assert_eq!(usize::default(), *val.public_accessible()); } #[test] fn test_prefixed_plain() { let val = Plain::default(); assert_eq!(20, *val.get_public_prefixed()); } getset-0.1.2/tests/mut_getters.rs000064400000000000000000000057750072674642500152370ustar 00000000000000#[macro_use] extern crate getset; use crate::submodule::other::{Generic, Plain, Where}; // For testing `pub(super)` mod submodule { // For testing `pub(in super::other)` pub mod other { #[derive(MutGetters, Default)] #[get_mut] pub struct Plain { /// A doc comment. /// Multiple lines, even. private_accessible: usize, /// A doc comment. #[get_mut = "pub"] public_accessible: usize, // /// A doc comment. // #[get_mut = "pub(crate)"] // crate_accessible: usize, // /// A doc comment. // #[get_mut = "pub(super)"] // super_accessible: usize, // /// A doc comment. // #[get_mut = "pub(in super::other)"] // scope_accessible: usize, } #[derive(MutGetters, Default)] #[get_mut] pub struct Generic { /// A doc comment. /// Multiple lines, even. private_accessible: T, /// A doc comment. #[get_mut = "pub"] public_accessible: T, // /// A doc comment. // #[get_mut = "pub(crate)"] // crate_accessible: usize, // /// A doc comment. // #[get_mut = "pub(super)"] // super_accessible: usize, // /// A doc comment. // #[get_mut = "pub(in super::other)"] // scope_accessible: usize, } #[derive(MutGetters, Default)] #[get_mut] pub struct Where where T: Copy + Clone + Default, { /// A doc comment. /// Multiple lines, even. private_accessible: T, /// A doc comment. #[get_mut = "pub"] public_accessible: T, // /// A doc comment. // #[get_mut = "pub(crate)"] // crate_accessible: usize, // /// A doc comment. // #[get_mut = "pub(super)"] // super_accessible: usize, // /// A doc comment. // #[get_mut = "pub(in super::other)"] // scope_accessible: usize, } #[test] fn test_plain() { let mut val = Plain::default(); (*val.private_accessible_mut()) += 1; } #[test] fn test_generic() { let mut val = Generic::::default(); (*val.private_accessible_mut()) += 1; } #[test] fn test_where() { let mut val = Where::::default(); (*val.private_accessible_mut()) += 1; } } } #[test] fn test_plain() { let mut val = Plain::default(); (*val.public_accessible_mut()) += 1; } #[test] fn test_generic() { let mut val = Generic::::default(); (*val.public_accessible_mut()) += 1; } #[test] fn test_where() { let mut val = Where::::default(); (*val.public_accessible_mut()) += 1; } getset-0.1.2/tests/raw_identifiers.rs000064400000000000000000000020430072674642500160340ustar 00000000000000#[macro_use] extern crate getset; #[derive(CopyGetters, Default, Getters, MutGetters, Setters)] struct RawIdentifiers { #[get] r#type: usize, #[get_copy] r#move: usize, #[get_mut] r#union: usize, #[set] r#enum: usize, #[get = "with_prefix"] r#const: usize, #[get_copy = "with_prefix"] r#if: usize, // Ensure having no gen mode doesn't break things. #[allow(dead_code)] r#loop: usize, } #[test] fn test_get() { let val = RawIdentifiers::default(); let _ = val.r#type(); } #[test] fn test_get_copy() { let val = RawIdentifiers::default(); let _ = val.r#move(); } #[test] fn test_get_mut() { let mut val = RawIdentifiers::default(); let _ = val.union_mut(); } #[test] fn test_set() { let mut val = RawIdentifiers::default(); val.set_enum(42); } #[test] fn test_get_with_prefix() { let val = RawIdentifiers::default(); let _ = val.get_const(); } #[test] fn test_get_copy_with_prefix() { let val = RawIdentifiers::default(); let _ = val.get_if(); } getset-0.1.2/tests/setters.rs000064400000000000000000000061750072674642500143610ustar 00000000000000#[macro_use] extern crate getset; use crate::submodule::other::{Generic, Plain, Where}; // For testing `pub(super)` mod submodule { // For testing `pub(in super::other)` pub mod other { #[derive(Setters, Default)] #[set] pub struct Plain { /// A doc comment. /// Multiple lines, even. private_accessible: usize, /// A doc comment. #[set = "pub"] public_accessible: usize, /// This field is used for testing chaining. #[set = "pub"] second_public_accessible: bool, // /// A doc comment. // #[set = "pub(crate)"] // crate_accessible: usize, // /// A doc comment. // #[set = "pub(super)"] // super_accessible: usize, // /// A doc comment. // #[set = "pub(in super::other)"] // scope_accessible: usize, } #[derive(Setters, Default)] #[set] pub struct Generic { /// A doc comment. /// Multiple lines, even. private_accessible: T, /// A doc comment. #[set = "pub"] public_accessible: T, // /// A doc comment. // #[set = "pub(crate)"] // crate_accessible: usize, // /// A doc comment. // #[set = "pub(super)"] // super_accessible: usize, // /// A doc comment. // #[set = "pub(in super::other)"] // scope_accessible: usize, } #[derive(Setters, Default)] #[set] pub struct Where where T: Copy + Clone + Default, { /// A doc comment. /// Multiple lines, even. private_accessible: T, /// A doc comment. #[set = "pub"] public_accessible: T, // /// A doc comment. // #[set = "pub(crate)"] // crate_accessible: usize, // /// A doc comment. // #[set = "pub(super)"] // super_accessible: usize, // /// A doc comment. // #[set = "pub(in super::other)"] // scope_accessible: usize, } #[test] fn test_plain() { let mut val = Plain::default(); val.set_private_accessible(1); } #[test] fn test_generic() { let mut val = Generic::default(); val.set_private_accessible(1); } #[test] fn test_where() { let mut val = Where::default(); val.set_private_accessible(1); } } } #[test] fn test_plain() { let mut val = Plain::default(); val.set_public_accessible(1); } #[test] fn test_generic() { let mut val = Generic::default(); val.set_public_accessible(1); } #[test] fn test_where() { let mut val = Where::default(); val.set_public_accessible(1); } #[test] fn test_chaining() { let mut val = Plain::default(); val.set_public_accessible(1) .set_second_public_accessible(true); } getset-0.1.2/tests/skip.rs000064400000000000000000000022120072674642500136220ustar 00000000000000#[macro_use] extern crate getset; #[derive(CopyGetters, Setters)] #[getset(get_copy, set)] pub struct Plain { // If the field was not skipped, the compiler would complain about moving a // non-copyable type. #[getset(skip)] non_copyable: String, copyable: usize, // Invalid use of skip -- compilation error. // #[getset(skip, get_copy)] // non_copyable2: String, // Invalid use of skip -- compilation error. // #[getset(get_copy, skip)] // non_copyable2: String, } impl Plain { fn custom_non_copyable(&self) -> &str { &self.non_copyable } // If the field was not skipped, the compiler would complain about duplicate // definitions of `set_non_copyable`. fn set_non_copyable(&mut self, val: String) -> &mut Self { self.non_copyable = val; self } } impl Default for Plain { fn default() -> Self { Plain { non_copyable: "foo".to_string(), copyable: 3, } } } #[test] fn test_plain() { let mut val = Plain::default(); val.copyable(); val.custom_non_copyable(); val.set_non_copyable("bar".to_string()); }