Generate struct assertion with error collection for multiple field failures
(value_expr: &TokenStream, pattern: &PatternStruct)
| 129 | |
| 130 | /// Generate struct assertion with error collection for multiple field failures |
| 131 | fn expand_struct_assertion(value_expr: &TokenStream, pattern: &PatternStruct) -> TokenStream { |
| 132 | let struct_path = &pattern.path; |
| 133 | let fields = &pattern.fields; |
| 134 | let rest = pattern.rest; |
| 135 | |
| 136 | // If struct_path is None, it's a wildcard pattern - use field access |
| 137 | let Some(struct_path) = struct_path.as_ref() else { |
| 138 | return expand_struct_wildcard_assertion(value_expr, fields); |
| 139 | }; |
| 140 | |
| 141 | // For nested field access, we need to collect unique field names only |
| 142 | // If we have middle.inner.value and middle.count, we only want "middle" once |
| 143 | let mut unique_field_names = HashSet::new(); |
| 144 | let field_names: Vec<_> = fields |
| 145 | .iter() |
| 146 | .filter_map(|f| { |
| 147 | let field_name = f.operations.root_field_name(); |
| 148 | if unique_field_names.insert(field_name.clone()) { |
| 149 | Some(field_name) |
| 150 | } else { |
| 151 | None |
| 152 | } |
| 153 | }) |
| 154 | .collect(); |
| 155 | |
| 156 | let rest_pattern = if rest { |
| 157 | quote! { , .. } |
| 158 | } else { |
| 159 | quote! {} |
| 160 | }; |
| 161 | |
| 162 | let field_assertions: Vec<_> = fields |
| 163 | .iter() |
| 164 | .map(|f| { |
| 165 | let field_name = f.operations.root_field_name(); |
| 166 | |
| 167 | // Expand the FieldAssertion starting from the bound field name |
| 168 | let assertion = expand_field_assertion("e! { #field_name }, f); |
| 169 | |
| 170 | // Wrap the assertion with the span of the field pattern if available |
| 171 | if let Some(span) = f.pattern.span() { |
| 172 | quote_spanned! {span=> #assertion } |
| 173 | } else { |
| 174 | assertion |
| 175 | } |
| 176 | }) |
| 177 | .collect(); |
| 178 | |
| 179 | let span = struct_path.span(); |
| 180 | |
| 181 | let error_push = generate_error_push( |
| 182 | span, |
| 183 | quote!(format!("{:?}", #value_expr)), |
| 184 | quote!(None), |
| 185 | pattern.node_id, |
| 186 | ); |
| 187 | |
| 188 | quote_spanned! {span=> |
no test coverage detected