Giter Club home page Giter Club logo

prom-attire-rs's Introduction

prom-attire travis-badge cargo-badge license-badge rust-version-badge

Procedural Macro Attributes

For when you need the best dressed procedural macro.

Developing

This project uses clippy and denies warnings in CI builds. To ensure your changes will be accepted please check them with cargo clippy (available via cargo install clippy on nightly rust) before submitting a pull request (along with cargo test as usual).

Both the nightly date and clippy version used in CI are pinned in the .travis.yml as clippy sometimes breaks for a few days after a new nightly is published, feel free to update to a new known good pair anytime as part of a pull request.

Why Three Crates

Why not three crates?

One issue with current procedural macros is that crates defining procedural macros can't use their own procedural macros. In this case prom-attire wants to have some attributes controlling how it parses the attributes (at the moment, only the top level "scope" attribute identifier, i.e. the value attire in #[attire(scope = shoes)]), obviously prom-attire will need to parse these attributes out to get the details it needs, but the entire point of prom-attire is to make parsing attributes pain-free, having a manual parser in prom-attire itself mean any upgrades to the parsing code generated by prom-attire would probably have to be duplicated in the parsing code inside prom-attire itself.

Luckily there is a solution, by using three crates ;-)

The base is prom-attire-impl, this implements the entirety of the procedural derive, but does not itself define a procedural derive macro. Instead it exports a single function taking in the AST provided to a procedural derive and some configuration and returns the derived implementation.

Next prom-attire-bootstrap defines a simple procedural derive macro FromAttributesBootstrap that calls into prom-attire-impl with a hardcoded configuration.

Finally prom-attire defines a slightly more complicated procedural derive macro (FromAttributes) that parses some attributes (using a parser derived with FromAttributesBootstrap), then calls into prom-attire-impl with a configuration derived from those parsed attributes. This is the "public" entrypoint to the crates, technically the others could be used but they're unlikely to be useful.

So, in the end prom-attire is a crate defining a procedural derive macro, to help developers write procedural derive macros, that uses a procedural derive in its implementation (no, that is not inception).

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be dual licensed as above, without any additional terms or conditions.

prom-attire-rs's People

Contributors

nemo157 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

prom-attire-rs's Issues

Parsing docs

Need to somehow choose a field to write docs to, could be an attribute #[attire(docs = foo)] on the struct?

Allow parsing to a borrowing type

FromStr doesn't allow the resulting type to borrow from the input string. If possible to implement nicely/easily this could be useful.

Document the generated error type somewhere

Currently there's no documentation on what the generated error type will look like. error-chain has an internal module showing the generated code, maybe we could do something similar.

Naming is hard

Alternatives:

  • hats (Helper for Attribute T... S...)
  • prom-attire (Procedural Macro Attributes)

(what's with the clothing references?)

Release Chores

  • Cargo.toml Metadata (description, repository url, keywords, categories, license, etc.)
  • Examples
  • Travis CI (tests (w/ --all for workspace), rustfmt, clippy)
  • Name (#1)

Tests w/ coverage

Should be relatively easy to hit 100% test coverage of both this code and generated code, coverage for the generated code is important since verifying if tests hit it all by eye is super difficult.

Can't specify a default for a string reference attribute

#[derive(PromAttire)]
struct Attributes<'a> {
    #[attire(default = "bar")]
    foo: &'a str,
}

Defaults use FromStr only, so you get errors like

error[E0277]: the trait bound `str: std::str::FromStr` is not satisfied                                                                                                    --> <anon>:9:10
  |
9 | #[derive(PromAttire)]
  |          ^^^^^^^^^^ the trait `std::str::FromStr` is not implemented for `str`

Probably need to use something like prom_attire_impl::expand::match_parse for parsing the provided default.

Examples for all features

Currently there's just the one basic example. The docs should be extended to show all the different features. There should be tests covering them all so basically need to take a good subset of the tests, clean them up, add some notes, and put them in the crate docs.

Quick list of what features I can think of right now:

  • attire(scope) - setting a wrapper attribute
  • attire(default) - setting a default if unspecified
  • FromStr parsing - parsing strings passed in as values
  • attire(docs) - putting docs attributes into a place
  • attire(attribute) - setting a different attribute name to use (#9)
  • attire(split_attribute_of) - complicated, semi-unstable (#10)
  • attire(flag_value) - set a default if the attribute is used without a value, (#11)
  • literals - support for non-string literals (currently unstable in Rust, but supported by syn)
  • bool - special cased default and flag_value
  • Vec - attributes that can take multiple values
  • errors - the errors that can be returned during parsing
  • lifetimes - borrowing strings from the AST

Support parsing via TryFrom<MetaItem>

It would be useful to write something like...

pub struct Lorem {
    #[attire(meta_item)]
    ipsum: Dolor
}

impl TryFrom<syn::MetaItem> for Dolor {
    type Error = String;

    fn try_from(v: syn::MetaItem) -> Result<Self, Self::Error> {
        // do stuff.
    }
}

In parallel, it'd be useful if prom-attire could generate such implementations. This would make it easier to create reusable parts that adhered to the normal attribute format.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.