Skip to content

Commit a1db46c

Browse files
committed
Fix handling of enum unit variants
An error in the annotate proc-macro produced invalid code for enums with unit variants. 1. Fix the repetition expansions in the proc macro. 2. Emit comments with unit variants. Place the comment after the variant name. 3. Add a special case for node-then-comment in the emitter to emit the comment on the same line following the node. Signed-off-by: Chris Frantz <cfrantz@google.com>
1 parent fbe22d4 commit a1db46c

File tree

5 files changed

+63
-22
lines changed

5 files changed

+63
-22
lines changed

annotate_derive/src/expand.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ fn impl_variants(variants: &[Variant]) -> (Vec<TokenStream>, Vec<TokenStream>) {
8989
quote! {
9090
#variant => match field {
9191
MemberId::Variant => #vformat,
92-
#(#formats),*,
92+
#(#formats,)*
9393
_ => None,
9494
}
9595
}
@@ -104,7 +104,7 @@ fn impl_variants(variants: &[Variant]) -> (Vec<TokenStream>, Vec<TokenStream>) {
104104
quote! {
105105
#variant => match field {
106106
MemberId::Variant => #vcomment,
107-
#(#comments),*,
107+
#(#comments,)*
108108
_ => None,
109109
}
110110
}
@@ -126,13 +126,13 @@ fn impl_struct(input: Struct) -> TokenStream {
126126
impl Annotate for #name {
127127
fn format(&self, _variant: Option<&str>, field: &MemberId) -> Option<Format> {
128128
match field {
129-
#(#formats),*,
129+
#(#formats,)*
130130
_ => None,
131131
}
132132
}
133133
fn comment(&self, _variant: Option<&str>, field: &MemberId) -> Option<String> {
134134
match field {
135-
#(#comments),*,
135+
#(#comments,)*
136136
_ => None,
137137
}
138138
}
@@ -156,14 +156,14 @@ fn impl_enum(input: Enum) -> TokenStream {
156156
fn format(&self, variant: Option<&str>, field: &MemberId) -> Option<Format> {
157157
let variant = variant?;
158158
match variant {
159-
#(#formats),*,
159+
#(#formats,)*
160160
_ => None,
161161
}
162162
}
163163
fn comment(&self, variant: Option<&str>, field: &MemberId) -> Option<String> {
164164
let variant = variant?;
165165
match variant {
166-
#(#comments),*,
166+
#(#comments,)*
167167
_ => None,
168168
}
169169
}

src/json.rs

+22-6
Original file line numberDiff line numberDiff line change
@@ -210,13 +210,29 @@ impl JsonEmitter {
210210
Document::Null => self.emit_null(w),
211211
Document::Compact(d) => self.emit_compact(w, d),
212212
Document::Fragment(ds) => {
213-
for d in ds {
214-
self.emit_node(w, d)?;
215-
if d.has_value() {
216-
self.writeln(w, "")?;
217-
self.emit_indent(w)?;
213+
match &ds[..] {
214+
// Currently, an enum unit-variant is the only place in the serializer where a
215+
// Fragment is constructed placing the comment after the node. For this case,
216+
// we want to emit the variant name followed by the comment on the same line.
217+
[n, Document::Comment(c, f)] => {
218+
self.emit_node(w, n)?;
219+
if !self.compact && !self.comment.is_empty() {
220+
write!(w, " ")?;
221+
self.emit_comment(w, c, f)?;
222+
}
218223
}
219-
}
224+
_ => {
225+
let mut prior_val = false;
226+
for d in ds {
227+
if prior_val {
228+
self.writeln(w, "")?;
229+
self.emit_indent(w)?;
230+
}
231+
self.emit_node(w, d)?;
232+
prior_val = d.has_value();
233+
}
234+
}
235+
};
220236
Ok(())
221237
}
222238
}

src/ser.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,12 @@ impl<'s, 'a> ser::Serializer for &'s mut AnnotatedSerializer<'a> {
203203
_variant_index: u32,
204204
variant: &'static str,
205205
) -> Result<Self::Ok, Self::Error> {
206-
self.serialize_str(variant)
206+
let node = self.serialize_str(variant)?;
207+
if let Some(c) = self.comment(Some(variant), &MemberId::Variant) {
208+
Ok(Document::Fragment(vec![node, c]))
209+
} else {
210+
Ok(node)
211+
}
207212
}
208213

209214
fn serialize_newtype_struct<T>(

src/yaml.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,26 @@ impl YamlEmitter {
9797
Document::Null => self.emit_null(w),
9898
Document::Compact(d) => self.emit_compact(w, d),
9999
Document::Fragment(ds) => {
100-
for d in ds {
101-
self.emit_node(w, d)?;
102-
if d.has_value() {
103-
self.writeln(w, "")?;
104-
self.emit_indent(w)?;
100+
match &ds[..] {
101+
[n, Document::Comment(c, f)] => {
102+
self.emit_node(w, n)?;
103+
if !self.compact {
104+
write!(w, " ")?;
105+
self.emit_comment(w, c, f)?;
106+
}
105107
}
106-
}
108+
_ => {
109+
let mut prior_val = false;
110+
for d in ds {
111+
if prior_val {
112+
self.writeln(w, "")?;
113+
self.emit_indent(w)?;
114+
}
115+
self.emit_node(w, d)?;
116+
prior_val = d.has_value();
117+
}
118+
}
119+
};
107120
Ok(())
108121
}
109122
}

tests/test_format.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ enum NesAddress {
263263
Prg(#[annotate(format=hex)] u8, #[annotate(format=hex)] u16),
264264
#[annotate(format=compact, comment="NES CHR bank:address")]
265265
Chr(#[annotate(format=hex)] u8, #[annotate(format=hex)] u16),
266+
#[annotate(comment = "Bad Address")]
267+
Invalid,
266268
}
267269

268270
#[derive(Serialize, Deserialize, Annotate, Debug, PartialEq)]
@@ -274,6 +276,7 @@ struct Addresses {
274276
b: NesAddress,
275277
c: Option<NesAddress>,
276278
d: CpuAddress,
279+
e: NesAddress,
277280
}
278281

279282
#[test]
@@ -283,6 +286,7 @@ fn test_nes_addresses() -> Result<()> {
283286
b: NesAddress::Prg(1, 0x8000),
284287
c: Some(NesAddress::Chr(2, 0x400)),
285288
d: CpuAddress(0xFFFA),
289+
e: NesAddress::Invalid,
286290
};
287291

288292
tester!(
@@ -300,7 +304,8 @@ fn test_nes_addresses() -> Result<()> {
300304
"c": {
301305
"Chr": [2, 1024]
302306
},
303-
"d": 65530
307+
"d": 65530,
308+
"e": "Invalid"
304309
}"#
305310
);
306311

@@ -322,7 +327,8 @@ fn test_nes_addresses() -> Result<()> {
322327
// NES CHR bank:address
323328
Chr: [0x2, 0x400]
324329
},
325-
d: 0xFFFA
330+
d: 0xFFFA,
331+
e: "Invalid" // Bad Address
326332
}"#
327333
);
328334

@@ -341,7 +347,8 @@ fn test_nes_addresses() -> Result<()> {
341347
c:
342348
# NES CHR bank:address
343349
Chr: [0x2, 0x400]
344-
d: 0xFFFA"#
350+
d: 0xFFFA
351+
e: Invalid # Bad Address"#
345352
);
346353

347354
Ok(())

0 commit comments

Comments
 (0)