Skip to content

Commit 5511bbc

Browse files
marcianxcopybara-github
authored andcommitted
In property_matcher! and field_matcher!, support explicit type parameters in structs and method calls. This effectively also adds support for these in matches_pattern!.
PiperOrigin-RevId: 773363853
1 parent 59d3eab commit 5511bbc

File tree

7 files changed

+229
-48
lines changed

7 files changed

+229
-48
lines changed

googletest/src/internal/test_data.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,17 @@ impl TestStruct {
1313
self.value
1414
}
1515
}
16+
17+
#[doc(hidden)]
18+
#[derive(Debug)]
19+
pub struct GenericTestStruct<T> {
20+
#[doc(hidden)]
21+
pub value: T,
22+
}
23+
24+
impl<T> GenericTestStruct<T> {
25+
#[doc(hidden)]
26+
pub fn get_value<U>(&self, a: U) -> U {
27+
a
28+
}
29+
}

googletest/src/matchers/field_matcher.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -196,34 +196,34 @@ macro_rules! __field {
196196
#[doc(hidden)]
197197
#[macro_export]
198198
macro_rules! field_internal {
199-
(&$($t:ident)::+.$field:tt, ref $m:expr) => {{
199+
(&$($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)? .$field:tt, ref $m:expr) => {{
200200
$crate::field_internal!(@internal
201-
[&_] [&$($t)::*]
201+
[&_] [&$($t)::* $(::<$($t_ty_args),*>)*]
202202
[$field] [ref] [$m])
203203
}};
204-
(&$($t:ident)::+.$field:tt, $m:expr) => {{
204+
(&$($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)? .$field:tt, $m:expr) => {{
205205
$crate::field_internal!(@internal
206-
[&&_] [&$($t)::*]
206+
[&&_] [&$($t)::* $(::<$($t_ty_args),*>)*]
207207
[$field] [] [$m])
208208
}};
209-
($($t:ident)::+.$field:tt, $m:expr) => {{
209+
($($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)? .$field:tt, $m:expr) => {{
210210
$crate::field_internal!(@internal
211-
[&_] [$($t)::*]
211+
[&_] [$($t)::* $(::<$($t_ty_args),*>)*]
212212
[$field] [] [$m])
213213
}};
214-
(& :: $($t:ident)::+.$field:tt, ref $m:expr) => {{
214+
(& :: $($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)? .$field:tt, ref $m:expr) => {{
215215
$crate::field_internal!(@internal
216-
[&_] [&::$($t)::*]
216+
[&_] [&::$($t)::* $(::<$($t_ty_args),*>)*]
217217
[$field] [ref] [$m])
218218
}};
219-
(& :: $($t:ident)::+.$field:tt, $m:expr) => {{
219+
(& :: $($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)? .$field:tt, $m:expr) => {{
220220
$crate::field_internal!(@internal
221-
[&&_] [&::$($t)::*]
221+
[&&_] [&::$($t)::* $(::<$($t_ty_args),*>)*]
222222
[$field] [] [$m])
223223
}};
224-
(:: $($t:ident)::+.$field:tt, $m:expr) => {{
224+
(:: $($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)? .$field:tt, $m:expr) => {{
225225
$crate::field_internal!(@internal
226-
[&_] [::$($t)::*]
226+
[&_] [::$($t)::* $(::<$($t_ty_args),*>)*]
227227
[$field] [] [$m])
228228
}};
229229

googletest/src/matchers/property_matcher.rs

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -176,67 +176,82 @@ macro_rules! __property {
176176
#[doc(hidden)]
177177
#[macro_export]
178178
macro_rules! property_internal {
179-
180-
(& $($t:ident)::+.$method:tt($($argument:expr),* $(,)?), ref $m:expr) => {{
179+
(& $($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
180+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
181+
ref $m:expr) => {{
181182
$crate::property_internal!(@self_arg
182-
struct_type: [&$($t)::+]
183-
method_prefix: [ $($t)::+]
184-
[$method] [$($argument),*] [$m])
183+
struct_type: [&$($t)::+ $( <$($t_ty_args),*>)*]
184+
method_prefix: [ $($t)::+ $(::<$($t_ty_args),*>)*]
185+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
185186
}};
186-
($($t:ident)::+.$method:tt($($argument:expr),* $(,)?), ref $m:expr) => {{
187+
($($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
188+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
189+
ref $m:expr) => {{
187190
$crate::property_internal!(@self_arg
188-
struct_type: [$($t)::+]
189-
method_prefix: [$($t)::+]
190-
[$method] [$($argument),*] [$m])
191+
struct_type: [$($t)::+ $( <$($t_ty_args),*>)*]
192+
method_prefix: [$($t)::+ $(::<$($t_ty_args),*>)*]
193+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
191194
}};
192-
(& ::$($t:ident)::+.$method:tt($($argument:expr),* $(,)?), ref $m:expr) => {{
195+
(& ::$($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
196+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
197+
ref $m:expr) => {{
193198
$crate::property_internal!(@self_arg
194-
struct_type: [&::$($t)::+]
195-
method_prefix: [ ::$($t)::+]
196-
[$method] [$($argument),*] [$m])
199+
struct_type: [&::$($t)::+ $( <$($t_ty_args),*>)*]
200+
method_prefix: [ ::$($t)::+ $(::<$($t_ty_args),*>)*]
201+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
197202
}};
198-
(::$($t:ident)::+.$method:tt($($argument:expr),* $(,)?), ref $m:expr) => {{
203+
(::$($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
204+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
205+
ref $m:expr) => {{
199206
$crate::property_internal!(@self_arg
200-
struct_type: [::$($t)::+]
201-
method_prefix: [::$($t)::+]
202-
[$method] [$($argument),*] [$m])
207+
struct_type: [::$($t)::+ $( <$($t_ty_args),*>)*]
208+
method_prefix: [::$($t)::+ $(::<$($t_ty_args),*>)*]
209+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
203210
}};
204211

205-
(& $($t:ident)::+.$method:tt($($argument:expr),* $(,)?), $m:expr) => {{
212+
(& $($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
213+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
214+
$m:expr) => {{
206215
$crate::property_internal!(@self_dot
207-
struct_type: [&&$($t)::+]
208-
[$method] [$($argument),*] [$m])
216+
struct_type: [&&$($t)::+ $(<$($t_ty_args),*>)*]
217+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
209218
}};
210-
($($t:ident)::+.$method:tt($($argument:expr),* $(,)?), $m:expr) => {{
219+
($($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
220+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
221+
$m:expr) => {{
211222
$crate::property_internal!(@self_dot
212-
struct_type: [&$($t)::+]
213-
[$method] [$($argument),*] [$m])
223+
struct_type: [&$($t)::+ $(<$($t_ty_args),*>)*]
224+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
214225
}};
215-
(& ::$($t:ident)::+.$method:tt($($argument:expr),* $(,)?), $m:expr) => {{
226+
(& ::$($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
227+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
228+
$m:expr) => {{
216229
$crate::property_internal!(@self_dot
217-
struct_type: [&&::$($t)::+]
218-
[$method] [$($argument),*] [$m])
230+
struct_type: [&&::$($t)::+ $(<$($t_ty_args),*>)*]
231+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
219232
}};
220-
(::$($t:ident)::+.$method:tt($($argument:expr),* $(,)?), $m:expr) => {{
233+
(::$($t:ident)::+ $(::<$($t_ty_args:ty),* $(,)?>)?
234+
.$method:tt $(::<$($m_ty_args:ty),* $(,)?>)? ($($argument:expr),* $(,)?),
235+
$m:expr) => {{
221236
$crate::property_internal!(@self_dot
222-
struct_type: [&::$($t)::+]
223-
[$method] [$($argument),*] [$m])
237+
struct_type: [&::$($t)::+ $(<$($t_ty_args),*>)*]
238+
[$method $(::<$($m_ty_args),*>)*] [$($argument),*] [$m])
224239
}};
225240

226241
(@self_arg struct_type: [$struct_ty:ty]
227242
method_prefix: [$($method_prefix:tt)+]
228-
[$method:tt] [$($argument:expr),*] [$m:expr]) => {{
243+
[$($method:tt)*] [$($argument:expr),*] [$m:expr]) => {{
229244
$crate::matchers::__internal_unstable_do_not_depend_on_these::property_ref_matcher(
230-
|o: $struct_ty| $($method_prefix)*::$method (o, $($argument),*),
231-
&stringify!($method($($argument),*)),
245+
|o: $struct_ty| $($method_prefix)*::$($method)* (o, $($argument),*),
246+
&stringify!($($method)* ($($argument),*)),
232247
$crate::matcher_support::__internal_unstable_do_not_depend_on_these::auto_eq!($m))
233248
}};
234249

235250
(@self_dot struct_type: [$struct_ty:ty]
236-
[$method:tt] [$($argument:expr),*] [$m:expr]) => {{
251+
[$($method:tt)*] [$($argument:expr),*] [$m:expr]) => {{
237252
$crate::matchers::__internal_unstable_do_not_depend_on_these::property_matcher(
238-
|o: $struct_ty| o.$method ($($argument),*),
239-
&stringify!($method($($argument),*)),
253+
|o: $struct_ty| o.$($method)* ($($argument),*),
254+
&stringify!($($method)* ($($argument),*)),
240255
$crate::matcher_support::__internal_unstable_do_not_depend_on_these::auto_eq!($m))
241256
}};
242257
}

googletest/tests/field_matcher_test.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,40 @@ fn supports_fully_qualified_struct_path() -> Result<()> {
275275
verify_that!(value, field!(::googletest::internal::test_data::TestStruct.value, eq(&10)))?;
276276
Ok(())
277277
}
278+
279+
#[test]
280+
fn supports_generic_struct() -> Result<()> {
281+
#[derive(Debug)]
282+
struct Struct<S, T> {
283+
#[allow(dead_code)] // The property1 field is used only for adding the type parameter.
284+
property1: S,
285+
property2: T,
286+
}
287+
288+
let value = Struct { property1: 1, property2: 10 };
289+
verify_that!(&value, field!(&Struct::<i32, u32>.property2, ref eq(&10)))?;
290+
verify_that!(value, field!(&Struct::<i32, u32>.property2, eq(10)))?;
291+
verify_that!(value, field!(Struct::<i32, u32>.property2, eq(&10)))?;
292+
Ok(())
293+
}
294+
295+
#[test]
296+
fn supports_fully_qualified_generic_struct() -> Result<()> {
297+
// Ensure that the macro expands to the fully-qualified struct path.
298+
mod googletest {}
299+
300+
let value = ::googletest::internal::test_data::GenericTestStruct { value: 10 };
301+
verify_that!(
302+
&value,
303+
field!(&::googletest::internal::test_data::GenericTestStruct::<i32>.value, ref eq(&10))
304+
)?;
305+
verify_that!(
306+
value,
307+
field!(&::googletest::internal::test_data::GenericTestStruct::<i32>.value, eq(10))
308+
)?;
309+
verify_that!(
310+
value,
311+
field!(::googletest::internal::test_data::GenericTestStruct::<i32>.value, eq(&10))
312+
)?;
313+
Ok(())
314+
}

googletest/tests/matches_pattern_struct_test.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,3 +1211,40 @@ fn matches_with_fully_qualified_struct_path() -> Result<()> {
12111211
)
12121212
)
12131213
}
1214+
1215+
#[test]
1216+
fn matches_with_explicit_type_parameters() -> Result<()> {
1217+
#[derive(Debug)]
1218+
struct AStruct<T> {
1219+
field: T,
1220+
}
1221+
1222+
impl<T: Copy> AStruct<T> {
1223+
fn get_default<U: Default>(&self) -> U {
1224+
Default::default()
1225+
}
1226+
}
1227+
1228+
let actual = AStruct::<i32> { field: 1 };
1229+
verify_that!(
1230+
actual,
1231+
matches_pattern!(&AStruct::<i32> { field: eq(1), get_default::<i16>(): eq(0) })
1232+
)
1233+
}
1234+
1235+
#[test]
1236+
fn matches_with_fully_qualified_generic_struct_path() -> Result<()> {
1237+
// Ensure that the macro expands to the fully-qualified struct path.
1238+
mod googletest {}
1239+
1240+
let value = ::googletest::internal::test_data::GenericTestStruct { value: 10 };
1241+
verify_that!(
1242+
value,
1243+
matches_pattern!(
1244+
&::googletest::internal::test_data::GenericTestStruct::<i16> {
1245+
value: eq(10),
1246+
get_value::<i16>(20): eq(20)
1247+
}
1248+
)
1249+
)
1250+
}

googletest/tests/property_matcher_test.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ impl SomeStruct {
3737
fn get_property_ref_with_params(&self, _a: u32, _b: u32) -> &u32 {
3838
&self.a_property
3939
}
40+
41+
fn generic_method<U, V>(&self, _a: U, _b: V) -> u32 {
42+
self.a_property
43+
}
44+
45+
fn generic_method_ref<U, V>(&self, _a: U, _b: V) -> &u32 {
46+
&self.a_property
47+
}
4048
}
4149

4250
#[test]
@@ -132,6 +140,74 @@ fn supports_fully_qualified_struct_path() -> Result<()> {
132140
Ok(())
133141
}
134142

143+
#[test]
144+
fn supports_generic_struct_matches() -> Result<()> {
145+
#[derive(Debug)]
146+
struct GenericStruct<S, T> {
147+
#[allow(dead_code)] // The property1 field is used only for adding the type parameter.
148+
property1: S,
149+
property2: T,
150+
}
151+
152+
impl<S, T: Copy> GenericStruct<S, T> {
153+
fn get_property(&self) -> T {
154+
self.property2
155+
}
156+
157+
fn get_property_ref(&self) -> &T {
158+
&self.property2
159+
}
160+
}
161+
162+
let value = GenericStruct { property1: 1, property2: 10 };
163+
verify_that!(value, property!(GenericStruct::<i32, u32>.get_property(), eq(&10)))?;
164+
verify_that!(value, property!(&GenericStruct::<i32, u32>.get_property(), eq(10)))?;
165+
verify_that!(value, property!(&GenericStruct::<i32, u32>.get_property(), ref eq(&10)))?;
166+
verify_that!(value, property!(&GenericStruct::<i32, u32>.get_property_ref(), eq(&10)))?;
167+
verify_that!(value, property!(&GenericStruct::<i32, u32>.get_property_ref(), ref eq(&&10)))?;
168+
Ok(())
169+
}
170+
171+
#[test]
172+
fn supports_generic_method_matches() -> Result<()> {
173+
let value = SomeStruct { a_property: 10 };
174+
verify_that!(value, property!(SomeStruct.generic_method::<i32, i16>(1, 2), eq(&10)))?;
175+
verify_that!(value, property!(&SomeStruct.generic_method::<i32, i16>(1, 2), eq(10)))?;
176+
verify_that!(value, property!(&SomeStruct.generic_method::<i32, i16>(1, 2), ref eq(&10)))?;
177+
verify_that!(value, property!(&SomeStruct.generic_method_ref::<i32, i16>(1, 2), eq(&10)))?;
178+
verify_that!(value, property!(&SomeStruct.generic_method_ref::<i32, i16>(1, 2), ref eq(&&10)))?;
179+
Ok(())
180+
}
181+
182+
#[test]
183+
fn supports_fully_qualified_generic_struct_path() -> Result<()> {
184+
// Ensure that the macro expands to the fully-qualified struct path.
185+
mod googletest {}
186+
187+
let value = ::googletest::internal::test_data::GenericTestStruct { value: 1 };
188+
verify_that!(
189+
value,
190+
property!(
191+
::googletest::internal::test_data::GenericTestStruct::<i32>.get_value::<i16>(10),
192+
eq(&10)
193+
)
194+
)?;
195+
verify_that!(
196+
value,
197+
property!(
198+
&::googletest::internal::test_data::GenericTestStruct::<i32>.get_value::<i16>(10),
199+
eq(10)
200+
)
201+
)?;
202+
verify_that!(
203+
value,
204+
property!(
205+
&::googletest::internal::test_data::GenericTestStruct::<i32>.get_value::<i16>(10),
206+
ref eq(&10))
207+
)?;
208+
Ok(())
209+
}
210+
135211
#[test]
136212
fn describes_itself_in_matching_case() -> Result<()> {
137213
verify_that!(

googletest_macro/src/matches_pattern.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,9 @@ enum FieldOrMethod {
244244
impl Parse for FieldOrMethod {
245245
/// Parses the field name or method call along with the `:` that follows it.
246246
fn parse(input: ParseStream) -> syn::Result<Self> {
247-
let value = if input.peek2(Token![:]) {
247+
// If the ident is followed by a single `:` and not a `::`, then it's a field
248+
// match and not a method call match.
249+
let value = if input.peek2(Token![:]) && !input.peek2(Token![::]) {
248250
input.parse().map(FieldOrMethod::Field)
249251
} else {
250252
input.parse().map(FieldOrMethod::Method)

0 commit comments

Comments
 (0)