From ad7173085a74449555780f3c4a6f016fce34385e Mon Sep 17 00:00:00 2001
From: Lennart Kloock <lennart@scuffle.cloud>
Date: Wed, 15 Jan 2025 23:20:17 +0100
Subject: [PATCH 1/4] docs(postcompile): root docs

---
 crates/postcompile/README.md  |  2 --
 crates/postcompile/src/lib.rs | 68 +++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/crates/postcompile/README.md b/crates/postcompile/README.md
index a673309be..baad501fc 100644
--- a/crates/postcompile/README.md
+++ b/crates/postcompile/README.md
@@ -19,8 +19,6 @@ This is particularly useful when making snapshot tests of proc-macros, look belo
 #[test]
 fn some_cool_test() {
     insta::assert_snapshot!(postcompile::compile! {
-        #![allow(unused)]
-
         #[derive(Debug, Clone)]
         struct Test {
             a: u32,
diff --git a/crates/postcompile/src/lib.rs b/crates/postcompile/src/lib.rs
index 9143b3d72..ab37879a2 100644
--- a/crates/postcompile/src/lib.rs
+++ b/crates/postcompile/src/lib.rs
@@ -1,3 +1,71 @@
+//! # postcompile
+//!
+//! A crate which allows you to compile Rust code at runtime (hence the name `postcompile`).
+//!
+//! What that means is that you can provide the input to `rustc` and then get back the expanded output, compiler errors, warnings, etc.
+//!
+//! This is particularly useful when making snapshot tests of proc-macros, look below for an example with the `insta` crate.
+//!
+//! ## Usage
+//!
+//! ```rs
+//! #[test]
+//! fn some_cool_test() {
+//!     insta::assert_snapshot!(postcompile::compile! {
+//!         #![allow(unused)]
+//!
+//!         #[derive(Debug, Clone)]
+//!         struct Test {
+//!             a: u32,
+//!             b: i32,
+//!         }
+//!
+//!         const TEST: Test = Test { a: 1, b: 3 };
+//!     });
+//! }
+//!
+//! #[test]
+//! fn some_cool_test_extern() {
+//!     insta::assert_snapshot!(postcompile::compile_str!(include_str!("some_file.rs")));
+//! }
+//! ```
+//!
+//! ## Features
+//!
+//! - Cached builds: This crate reuses the cargo build cache of the original crate so that only the contents of the macro are compiled & not any additional dependencies.
+//! - Coverage: This crate works with [`cargo-llvm-cov`](https://crates.io/crates/cargo-llvm-cov) out of the box, which allows you to instrument the proc-macro expansion.
+//!
+//! ## Alternatives
+//!
+//! - [`compiletest_rs`](https://crates.io/crates/compiletest_rs): This crate is used by the Rust compiler team to test the compiler itself. Not really useful for proc-macros.
+//! - [`trybuild`](https://crates.io/crates/trybuild): This crate is an all-in-one solution for testing proc-macros, with built in snapshot testing.
+//! - [`ui_test`](https://crates.io/crates/ui_test): Similar to `trybuild` with a slightly different API & used by the Rust compiler team to test the compiler itself.
+//!
+//! ### Differences
+//!
+//! The other libraries are focused on testing & have built in test harnesses. This crate takes a step back and allows you to compile without a testing harness. This has the advantage of being more flexible, and allows you to use whatever testing framework you want.
+//!
+//! In the examples above I showcase how to use this crate with the `insta` crate for snapshot testing.
+//!
+//! ## Status
+//!
+//! This crate is currently under development and is not yet stable.
+//!
+//! Unit tests are not yet fully implemented. Use at your own risk.
+//!
+//! ## Limitations
+//!
+//! Please note that this crate does not work inside a running compiler process (inside a proc-macro) without hacky workarounds and complete build-cache invalidation.
+//!
+//! This is because `cargo` holds a lock on the build directory and that if we were to compile inside a proc-macro we would recursively invoke the compiler.
+//!
+//! ## License
+//!
+//! This project is licensed under the [MIT](./LICENSE.MIT) or [Apache-2.0](./LICENSE.Apache-2.0) license.
+//! You can choose between one of them if you use this work.
+//!
+//! `SPDX-License-Identifier: MIT OR Apache-2.0`
+
 use std::borrow::Cow;
 use std::ffi::{OsStr, OsString};
 use std::os::unix::ffi::OsStrExt;

From 2636401e53b7a3540a185025fd7497ca19dbcb38 Mon Sep 17 00:00:00 2001
From: Lennart Kloock <lennart@scuffle.cloud>
Date: Wed, 15 Jan 2025 23:23:52 +0100
Subject: [PATCH 2/4] fix(postcompile): readme

---
 crates/postcompile/README.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/crates/postcompile/README.md b/crates/postcompile/README.md
index baad501fc..a673309be 100644
--- a/crates/postcompile/README.md
+++ b/crates/postcompile/README.md
@@ -19,6 +19,8 @@ This is particularly useful when making snapshot tests of proc-macros, look belo
 #[test]
 fn some_cool_test() {
     insta::assert_snapshot!(postcompile::compile! {
+        #![allow(unused)]
+
         #[derive(Debug, Clone)]
         struct Test {
             a: u32,

From 3bed8584855285e33d675905055acd43b43d9480 Mon Sep 17 00:00:00 2001
From: Lennart Kloock <lennart@scuffle.cloud>
Date: Wed, 15 Jan 2025 23:24:25 +0100
Subject: [PATCH 3/4] chore(postcompile): fmt

---
 crates/postcompile/src/lib.rs | 49 +++++++++++++++++++++++++----------
 1 file changed, 35 insertions(+), 14 deletions(-)

diff --git a/crates/postcompile/src/lib.rs b/crates/postcompile/src/lib.rs
index ab37879a2..3c324319d 100644
--- a/crates/postcompile/src/lib.rs
+++ b/crates/postcompile/src/lib.rs
@@ -1,10 +1,13 @@
 //! # postcompile
 //!
-//! A crate which allows you to compile Rust code at runtime (hence the name `postcompile`).
+//! A crate which allows you to compile Rust code at runtime (hence the name
+//! `postcompile`).
 //!
-//! What that means is that you can provide the input to `rustc` and then get back the expanded output, compiler errors, warnings, etc.
+//! What that means is that you can provide the input to `rustc` and then get
+//! back the expanded output, compiler errors, warnings, etc.
 //!
-//! This is particularly useful when making snapshot tests of proc-macros, look below for an example with the `insta` crate.
+//! This is particularly useful when making snapshot tests of proc-macros, look
+//! below for an example with the `insta` crate.
 //!
 //! ## Usage
 //!
@@ -32,20 +35,33 @@
 //!
 //! ## Features
 //!
-//! - Cached builds: This crate reuses the cargo build cache of the original crate so that only the contents of the macro are compiled & not any additional dependencies.
-//! - Coverage: This crate works with [`cargo-llvm-cov`](https://crates.io/crates/cargo-llvm-cov) out of the box, which allows you to instrument the proc-macro expansion.
+//! - Cached builds: This crate reuses the cargo build cache of the original
+//!   crate so that only the contents of the macro are compiled & not any
+//!   additional dependencies.
+//! - Coverage: This crate works with [`cargo-llvm-cov`](https://crates.io/crates/cargo-llvm-cov)
+//!   out of the box, which allows you to instrument the proc-macro expansion.
 //!
 //! ## Alternatives
 //!
-//! - [`compiletest_rs`](https://crates.io/crates/compiletest_rs): This crate is used by the Rust compiler team to test the compiler itself. Not really useful for proc-macros.
-//! - [`trybuild`](https://crates.io/crates/trybuild): This crate is an all-in-one solution for testing proc-macros, with built in snapshot testing.
-//! - [`ui_test`](https://crates.io/crates/ui_test): Similar to `trybuild` with a slightly different API & used by the Rust compiler team to test the compiler itself.
+//! - [`compiletest_rs`](https://crates.io/crates/compiletest_rs): This crate is
+//!   used by the Rust compiler team to test the compiler itself. Not really
+//!   useful for proc-macros.
+//! - [`trybuild`](https://crates.io/crates/trybuild): This crate is an
+//!   all-in-one solution for testing proc-macros, with built in snapshot
+//!   testing.
+//! - [`ui_test`](https://crates.io/crates/ui_test): Similar to `trybuild` with
+//!   a slightly different API & used by the Rust compiler team to test the
+//!   compiler itself.
 //!
 //! ### Differences
 //!
-//! The other libraries are focused on testing & have built in test harnesses. This crate takes a step back and allows you to compile without a testing harness. This has the advantage of being more flexible, and allows you to use whatever testing framework you want.
+//! The other libraries are focused on testing & have built in test harnesses.
+//! This crate takes a step back and allows you to compile without a testing
+//! harness. This has the advantage of being more flexible, and allows you to
+//! use whatever testing framework you want.
 //!
-//! In the examples above I showcase how to use this crate with the `insta` crate for snapshot testing.
+//! In the examples above I showcase how to use this crate with the `insta`
+//! crate for snapshot testing.
 //!
 //! ## Status
 //!
@@ -55,14 +71,19 @@
 //!
 //! ## Limitations
 //!
-//! Please note that this crate does not work inside a running compiler process (inside a proc-macro) without hacky workarounds and complete build-cache invalidation.
+//! Please note that this crate does not work inside a running compiler process
+//! (inside a proc-macro) without hacky workarounds and complete build-cache
+//! invalidation.
 //!
-//! This is because `cargo` holds a lock on the build directory and that if we were to compile inside a proc-macro we would recursively invoke the compiler.
+//! This is because `cargo` holds a lock on the build directory and that if we
+//! were to compile inside a proc-macro we would recursively invoke the
+//! compiler.
 //!
 //! ## License
 //!
-//! This project is licensed under the [MIT](./LICENSE.MIT) or [Apache-2.0](./LICENSE.Apache-2.0) license.
-//! You can choose between one of them if you use this work.
+//! This project is licensed under the [MIT](./LICENSE.MIT) or
+//! [Apache-2.0](./LICENSE.Apache-2.0) license. You can choose between one of
+//! them if you use this work.
 //!
 //! `SPDX-License-Identifier: MIT OR Apache-2.0`
 

From 27d93a9fc70d48e285d1b01c639a9ddfdf652e07 Mon Sep 17 00:00:00 2001
From: Lennart Kloock <lennart@scuffle.cloud>
Date: Mon, 20 Jan 2025 21:08:09 +0100
Subject: [PATCH 4/4] test(postcompile): add tests

---
 Cargo.lock                                    |  1 +
 crates/postcompile/Cargo.toml                 |  7 +-
 crates/postcompile/src/lib.rs                 | 70 ++++++++++++++++++-
 .../postcompile__tests__compile_failure.snap  | 14 ++++
 .../postcompile__tests__compile_success.snap  | 18 +++++
 5 files changed, 106 insertions(+), 4 deletions(-)
 create mode 100644 crates/postcompile/src/snapshots/postcompile__tests__compile_failure.snap
 create mode 100644 crates/postcompile/src/snapshots/postcompile__tests__compile_success.snap

diff --git a/Cargo.lock b/Cargo.lock
index ddd4dbc8b..98fcd7ecc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2135,6 +2135,7 @@ version = "0.0.5"
 dependencies = [
  "cargo-platform",
  "cargo_metadata",
+ "insta",
  "prettyplease",
  "scuffle-workspace-hack",
  "serde",
diff --git a/crates/postcompile/Cargo.toml b/crates/postcompile/Cargo.toml
index e3541798b..88375bffd 100644
--- a/crates/postcompile/Cargo.toml
+++ b/crates/postcompile/Cargo.toml
@@ -11,6 +11,9 @@ license = "MIT OR Apache-2.0"
 description = "Helper crate for post-compiling Rust code."
 keywords = ["postcompile", "snapshot", "test", "proc-macro"]
 
+[lints.rust]
+unexpected_cfgs = { level = "warn", check-cfg = ['cfg(trybuild_no_target)', 'cfg(postcompile_no_target)', 'cfg(coverage_nightly)'] }
+
 [dependencies]
 serde_json = "1.0"
 cargo_metadata = "0.19.1"
@@ -22,8 +25,8 @@ prettyplease = { version = "0.2", optional = true }
 syn = { version = "2", features = ["full"] }
 scuffle-workspace-hack.workspace = true
 
-[lints.rust]
-unexpected_cfgs = { level = "warn", check-cfg = ['cfg(trybuild_no_target)', 'cfg(postcompile_no_target)'] }
+[dev-dependencies]
+insta = "1.42.0"
 
 [features]
 prettyplease = ["dep:prettyplease"]
diff --git a/crates/postcompile/src/lib.rs b/crates/postcompile/src/lib.rs
index 3c324319d..4d156d973 100644
--- a/crates/postcompile/src/lib.rs
+++ b/crates/postcompile/src/lib.rs
@@ -1,5 +1,3 @@
-//! # postcompile
-//!
 //! A crate which allows you to compile Rust code at runtime (hence the name
 //! `postcompile`).
 //!
@@ -86,6 +84,7 @@
 //! them if you use this work.
 //!
 //! `SPDX-License-Identifier: MIT OR Apache-2.0`
+#![cfg_attr(all(coverage_nightly, test), feature(coverage_attribute))]
 
 use std::borrow::Cow;
 use std::ffi::{OsStr, OsString};
@@ -383,3 +382,70 @@ macro_rules! try_compile_str {
         $crate::compile_custom($expr, &$crate::_config!())
     };
 }
+
+#[cfg(test)]
+#[cfg_attr(all(test, coverage_nightly), coverage(off))]
+mod tests {
+    use insta::assert_snapshot;
+
+    use crate::ExitStatus;
+
+    #[test]
+    fn compile_success() {
+        let out = compile! {
+            #[allow(unused)]
+            fn main() {
+                let a = 1;
+                let b = 2;
+                let c = a + b;
+            }
+        };
+
+        assert_eq!(out.status, ExitStatus::Success);
+        assert!(out.stderr.is_empty());
+        assert_snapshot!(out);
+    }
+
+    #[test]
+    fn try_compile_success() {
+        let out = try_compile! {
+            #[allow(unused)]
+            fn main() {
+                let xd = 0xd;
+                let xdd = 0xdd;
+                let xddd = xd + xdd;
+                println!("{}", xddd);
+            }
+        };
+
+        assert!(out.is_ok());
+        let out = out.unwrap();
+        assert_eq!(out.status, ExitStatus::Success);
+        assert!(out.stderr.is_empty());
+        assert!(!out.stdout.is_empty());
+    }
+
+    #[test]
+    fn compile_failure() {
+        let out = compile! {
+            invalid_rust_code
+        };
+
+        assert_eq!(out.status, ExitStatus::Failure(1));
+        assert!(out.stdout.is_empty());
+        assert_snapshot!(out);
+    }
+
+    #[test]
+    fn try_compile_failure() {
+        let out = try_compile! {
+            invalid rust code
+        };
+
+        assert!(out.is_ok());
+        let out = out.unwrap();
+        assert_eq!(out.status, ExitStatus::Failure(1));
+        assert!(out.stdout.is_empty());
+        assert!(!out.stderr.is_empty());
+    }
+}
diff --git a/crates/postcompile/src/snapshots/postcompile__tests__compile_failure.snap b/crates/postcompile/src/snapshots/postcompile__tests__compile_failure.snap
new file mode 100644
index 000000000..1fa9ab347
--- /dev/null
+++ b/crates/postcompile/src/snapshots/postcompile__tests__compile_failure.snap
@@ -0,0 +1,14 @@
+---
+source: crates/postcompile/src/lib.rs
+expression: out
+snapshot_kind: text
+---
+exit status: 1
+--- stderr 
+error: expected one of `!` or `::`, found `<eof>`
+ --> <postcompile>:1:1
+  |
+1 | invalid_rust_code
+  | ^^^^^^^^^^^^^^^^^ expected one of `!` or `::`
+
+error: aborting due to 1 previous error
diff --git a/crates/postcompile/src/snapshots/postcompile__tests__compile_success.snap b/crates/postcompile/src/snapshots/postcompile__tests__compile_success.snap
new file mode 100644
index 000000000..b71eceaf4
--- /dev/null
+++ b/crates/postcompile/src/snapshots/postcompile__tests__compile_success.snap
@@ -0,0 +1,18 @@
+---
+source: crates/postcompile/src/lib.rs
+expression: out
+snapshot_kind: text
+---
+exit status: 0
+--- stdout 
+#![feature(prelude_import)]
+#[prelude_import]
+use std::prelude::rust_2021::*;
+#[macro_use]
+extern crate std;
+#[allow(unused)]
+fn main() {
+    let a = 1;
+    let b = 2;
+    let c = a + b;
+}