Skip to content

Commit 138f365

Browse files
authored
Snapshot Testing for CGP Proc Macros (#236)
* Draft implement new assert_delegate_components macro * Add pretty_format helper * Use pretty_format in assert_delegate_components * Try file-based snapshot * Inline snapshot now works * Put original code first before snapshot * Migrate more tests to assert_delegate_components * Rename to snapshot_delegate_components * Allow arbitrary expression in body * Add MacroSnapshot::wrap_output helper * Add snapshot_cgp_component * Add cgp-macro-test-util-lib crate * Refactor snapshot_delegate_components macro * Add back snapshot_cgp_component * Snapshot cgp_component is now working * Format output as string inside macro * Implement `snapshot_cgp_impl!` * Implement `snapshot_cgp_auto_getter!` * Move pretty_format to test-util-lib * AI-migrate tests * Implement `snapshot_cgp_fn!` * Use fully qualified `insta::assert_snapshot!` * Add `snapshot_cgp_namespace!` macro * Add `snapshot_cgp_type!` macro * Add `snapshot_check_components!` and `snapshot_delegate_and_check_components!` * Add StatementMacroSnapshot * Add AttributeMacroSnapshot * Remove SnapshotCgpComponent * Migrate all other macros * Add `snapshot_cgp_provider!` macro * Fix formatting
1 parent cd96aa9 commit 138f365

118 files changed

Lines changed: 18801 additions & 1716 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 150 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ members = [
2626
"crates/macros/cgp-macro",
2727
"crates/macros/cgp-macro-core",
2828
"crates/macros/cgp-macro-lib",
29+
"crates/macros/cgp-macro-test-util",
30+
"crates/macros/cgp-macro-test-util-lib",
2931
"crates/macros/cgp-extra-macro",
3032
"crates/macros/cgp-extra-macro-lib",
3133

@@ -68,5 +70,7 @@ cgp-async-macro = { version = "0.7.0", path = "./crates/macros/cgp-a
6870
cgp-macro = { version = "0.7.0", path = "./crates/macros/cgp-macro" }
6971
cgp-macro-core = { version = "0.7.0", path = "./crates/macros/cgp-macro-core" }
7072
cgp-macro-lib = { version = "0.7.0", path = "./crates/macros/cgp-macro-lib" }
73+
cgp-macro-test-util = { version = "0.7.0", path = "./crates/macros/cgp-macro-test-util" }
74+
cgp-macro-test-util-lib = { version = "0.7.0", path = "./crates/macros/cgp-macro-test-util-lib" }
7175
cgp-extra-macro = { version = "0.7.0", path = "./crates/macros/cgp-extra-macro" }
7276
cgp-extra-macro-lib = { version = "0.7.0", path = "./crates/macros/cgp-extra-macro-lib" }

crates/macros/cgp-macro-core/Cargo.toml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,9 @@ repository = { workspace = true }
77
authors = { workspace = true }
88
rust-version = { workspace = true }
99
keywords = { workspace = true }
10-
description = """
11-
Context-generic programming core component macros implemented as a library.
12-
"""
13-
14-
[features]
15-
default = []
1610

1711
[dependencies]
18-
syn = { version = "2.0.95", features = [ "full", "extra-traits", "visit", "visit-mut" ] }
19-
quote = "1.0.38"
20-
proc-macro2 = "1.0.92"
21-
itertools = "0.14.0"
12+
syn = { version = "2.0.95", features = [ "full", "extra-traits", "visit", "visit-mut" ] }
13+
quote = { version = "1.0.38" }
14+
proc-macro2 = { version = "1.0.92" }
15+
itertools = { version = "0.14.0" }

crates/macros/cgp-macro-core/src/functions/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod implicits;
77
mod is_provider_params;
88
mod parse_internal;
99
mod snake_case;
10+
mod strip;
1011

1112
pub use camel_case::*;
1213
pub use delegated_impls::*;
@@ -17,3 +18,4 @@ pub use implicits::*;
1718
pub use is_provider_params::*;
1819
pub use parse_internal::*;
1920
pub use snake_case::*;
21+
pub use strip::*;
Lines changed: 2 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use core::any::type_name;
22

3-
use proc_macro2::{Group, TokenStream, TokenTree};
3+
use proc_macro2::TokenStream;
44
use syn::parse::Parse;
55
use syn::spanned::Spanned;
66
use syn::{Error, parse2};
77

8+
use crate::functions::strip_macro_prelude;
89
pub use crate::macros::parse_internal;
910

1011
pub fn parse_internal<T>(body: TokenStream) -> Result<T, Error>
@@ -23,57 +24,3 @@ where
2324
e
2425
})
2526
}
26-
27-
/// Strips the `::cgp::macro_prelude::` prefix from the [`TokenStream`] so the
28-
/// error message shows the more readable, unqualified paths. The replacement is
29-
/// done at the token level, recursing into nested groups.
30-
fn strip_macro_prelude(body: TokenStream) -> TokenStream {
31-
// The prefix `::cgp::macro_prelude::` is made up of the following tokens.
32-
fn is_prefix(tokens: &[TokenTree]) -> bool {
33-
matches!(
34-
tokens,
35-
[
36-
TokenTree::Punct(p1),
37-
TokenTree::Punct(p2),
38-
TokenTree::Ident(cgp),
39-
TokenTree::Punct(p3),
40-
TokenTree::Punct(p4),
41-
TokenTree::Ident(prelude),
42-
TokenTree::Punct(p5),
43-
TokenTree::Punct(p6),
44-
] if p1.as_char() == ':'
45-
&& p2.as_char() == ':'
46-
&& cgp == "cgp"
47-
&& p3.as_char() == ':'
48-
&& p4.as_char() == ':'
49-
&& prelude == "macro_prelude"
50-
&& p5.as_char() == ':'
51-
&& p6.as_char() == ':'
52-
)
53-
}
54-
55-
const PREFIX_LEN: usize = 8;
56-
57-
let tokens: Vec<TokenTree> = body.into_iter().collect();
58-
let mut output = Vec::with_capacity(tokens.len());
59-
let mut i = 0;
60-
61-
while i < tokens.len() {
62-
if is_prefix(&tokens[i..(i + PREFIX_LEN).min(tokens.len())]) {
63-
i += PREFIX_LEN;
64-
} else {
65-
match &tokens[i] {
66-
TokenTree::Group(group) => {
67-
let inner = strip_macro_prelude(group.stream());
68-
let mut new_group = Group::new(group.delimiter(), inner);
69-
new_group.set_span(group.span());
70-
output.push(TokenTree::Group(new_group));
71-
}
72-
other => output.push(other.clone()),
73-
}
74-
i += 1;
75-
}
76-
}
77-
78-
output.into_iter().collect()
79-
}

0 commit comments

Comments
 (0)