1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#![crate_type = "lib"]
#![doc(html_root_url = "https://docs.rs/macrotest/1.0.6")]

//! ####   Test harness for macro expansion.
//!
//! Similar to [trybuild], but allows you to write tests on how macros are expanded.
//!
//! <br>
//!
//! # Macro expansion tests
//!
//! A minimal `macrotest` setup looks like this:
//!
//! ```rust
//! #[test]
//! pub fn pass() {
//!     macrotest::expand("tests/expand/*.rs");
//!     // Alternatively,
//!     macrotest::expand_without_refresh("tests/expand/*.rs");
//! }
//! ```
//!
//! The test can be run with `cargo test`. This test will invoke the [`cargo expand`] command
//! on each of the source files that matches the glob pattern and will compare the expansion result
//! with the corresponding `*.expanded.rs` file.
//!
//! If a `*.expanded.rs` file doesn't exists and it's not explicitly expected to (see [`expand_without_refresh`]),
//! it will be created (this is how you update your tests).
//!
//! Possible test outcomes are:
//! - **Pass**: expansion succeeded and the result is the same as in the `.expanded.rs` file
//! - **Fail**: expansion was different from the `.expanded.rs` file content
//! - **Refresh**: `.expanded.rs` didn't exist and has been created
//! - **Refresh-fail**: `.expanded.rs` is expected to be present, but not exists. See [`expand_without_refresh`].
//!
//! *Note:* when working with multiple expansion test files, it is recommended to
//! specify wildcard (*.rs) instead of doing a multiple calls to `expand` functions for individual files.
//! Usage of wildcards for multiple files will group them under a single temporary crate for which
//! dependencies will be built a single time. In contrast, calling `expand` functions for each
//! source file will create multiple temporary crates and that will reduce performance as depdendencies
//! will be build for each of the temporary crates.
//!
//! ## Passing additional arguments to `cargo expand`
//!
//! It's possible to specify additional arguments for [`cargo expand`] command.
//!
//! In order to do so, use the following functions with `_args` suffix:
//! - [`expand_args`]
//! - [`expand_without_refresh_args`]
//!
//! Example:
//!
//! ```rust
//! pub fn pass() {
//!     macrotest::expand_args("tests/expand/*.rs", &["--features", "my-feature"]);
//!     // Or
//!     macrotest::expand_without_refresh_args("tests/expand/*.rs", &["--features", "my-feature"]);
//! }
//! ```
//!
//! The `_args` functions will result in the following [`cargo expand`] command being run:
//!
//! ```bash
//! cargo expand --bin <test-name> --theme none --features my-feature
//! ```
//!
//! # Workflow
//!
//! First of all, the [`cargo expand`] tool must be present. You can install it via cargo:
//!
//! ```bash
//! cargo install cargo-expand
//! ```
//!
//! A **nightly** compiler is required for this tool to work, so it must be installed as well.
//!
//! `cargo-expand` uses [`rustfmt`](https://github.com/rust-lang/rustfmt) to format expanded code.
//! It's highly recommended to install it since the examples in the `test-project/` and
//! `test-procmacro-project/` folders are using a formatted version of the expanded code
//! to compare with.
//!
//! ## Setting up a test project
//!
//! In your crate that provides procedural or declarative macros, under the `tests` directory,
//! create an `expand` directory and populate it with different expansion test cases as
//! rust source files.
//!
//! Then create a `tests.rs` file that will run the tests:
//!
//! ```rust
//! #[test]
//! pub fn pass() {
//!     macrotest::expand("tests/expand/*.rs");
//!     // Or:
//!     macrotest::expand_without_refresh("tests/expand/*.rs");
//! }
//! ```
//!
//! And then you can run `cargo test`, which will
//!
//! 1. Expand macros in source files that match glob pattern
//! 1. In case if [`expand`] function is used:
//!     - On the first run, generate the `*.expanded.rs` files for each of the test cases under
//!     the `expand` directory
//!     - On subsequent runs, compare test cases' expansion result with the
//!     content of the respective `*.expanded.rs` files
//! 1. In case if [`expand_without_refresh`] is used:
//!     - On each run, it will compare test cases' expansion result with the content of the
//!     respective `*.expanded.rs` files.
//!     - If one or more `*.expanded.rs` files is not found, the test will fail.
//!
//! ## Updating `.expanded.rs`
//!
//! This applicable only to tests that are using [`expand`] or [`expand_args`] function.
//!
//! Run tests with the environment variable `MACROTEST=overwrite` or remove the `*.expanded.rs`
//! files and re-run the corresponding tests. Files will be created automatically; hand-writing
//! them is not recommended.
//!
//! [`expand_without_refresh`]: expand/fn.expand_without_refresh.html
//! [`expand_without_refresh_args`]: expand/fn.expand_without_refresh_args.html
//! [`expand`]: expand/fn.expand.html
//! [`expand_args`]: expand/fn.expand_args.html
//! [trybuild]: https://github.com/dtolnay/trybuild
//! [`cargo expand`]: https://github.com/dtolnay/cargo-expand

#[macro_use]
mod path;

mod cargo;
mod dependencies;
mod error;
mod expand;
mod features;
mod manifest;
mod message;
mod rustflags;

pub use expand::expand;
pub use expand::expand_args;
pub use expand::expand_without_refresh;
pub use expand::expand_without_refresh_args;