Skip to content

Commit d94b5ea

Browse files
author
andrewleverette
committed
Merge branch 'issue-3-and-4-field-documentation-annotation' of https://github.com/nbigaouette/codegen into nbigaouette-issue-3-and-4-field-documentation-annotation
# Conflicts: # src/lib.rs # tests/codegen.rs
2 parents 87e270f + 2528d99 commit d94b5ea

File tree

2 files changed

+135
-13
lines changed

2 files changed

+135
-13
lines changed

src/lib.rs

Lines changed: 76 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,18 @@ enum Fields {
131131

132132
/// Defines a struct field.
133133
#[derive(Debug, Clone)]
134-
struct Field {
134+
pub struct Field {
135135
/// Field name
136136
name: String,
137137

138138
/// Field type
139139
ty: Type,
140+
141+
/// Field documentation
142+
documentation: Vec<String>,
143+
144+
/// Field annotation
145+
annotation: Vec<String>,
140146
}
141147

142148
/// Defines an associated type.
@@ -712,6 +718,16 @@ impl Struct {
712718
self
713719
}
714720

721+
/// Push a named field to the struct.
722+
///
723+
/// A struct can either set named fields with this function or tuple fields
724+
/// with `push_tuple_field`, but not both.
725+
pub fn push_field(&mut self, field: Field) -> &mut Self
726+
{
727+
self.fields.push_named(field);
728+
self
729+
}
730+
715731
/// Add a named field to the struct.
716732
///
717733
/// A struct can either set named fields with this function or tuple fields
@@ -1243,31 +1259,63 @@ impl AssociatedType {
12431259
}
12441260
}
12451261

1262+
// ===== impl Field =====
1263+
1264+
impl Field {
1265+
/// Return a field definition with the provided name and type
1266+
pub fn new<T>(name: &str, ty: T) -> Self
1267+
where T: Into<Type>,
1268+
{
1269+
Field {
1270+
name: name.into(),
1271+
ty: ty.into(),
1272+
documentation: Vec::new(),
1273+
annotation: Vec::new(),
1274+
}
1275+
}
1276+
1277+
/// Set field's documentation.
1278+
pub fn doc(&mut self, documentation: Vec<&str>) -> &mut Self {
1279+
self.documentation = documentation.iter().map(|doc| doc.to_string()).collect();
1280+
self
1281+
}
1282+
1283+
/// Set field's annotation.
1284+
pub fn annotation(&mut self, annotation: Vec<&str>) -> &mut Self {
1285+
self.annotation = annotation.iter().map(|ann| ann.to_string()).collect();
1286+
self
1287+
}
1288+
}
1289+
12461290
// ===== impl Fields =====
12471291

12481292
impl Fields {
1249-
fn named<T>(&mut self, name: &str, ty: T) -> &mut Self
1250-
where T: Into<Type>,
1293+
fn push_named(&mut self, field: Field) -> &mut Self
12511294
{
12521295
match *self {
12531296
Fields::Empty => {
1254-
*self = Fields::Named(vec![Field {
1255-
name: name.to_string(),
1256-
ty: ty.into(),
1257-
}]);
1297+
*self = Fields::Named(vec![field]);
12581298
}
12591299
Fields::Named(ref mut fields) => {
1260-
fields.push(Field {
1261-
name: name.to_string(),
1262-
ty: ty.into(),
1263-
});
1300+
fields.push(field);
12641301
}
12651302
_ => panic!("field list is named"),
12661303
}
12671304

12681305
self
12691306
}
12701307

1308+
fn named<T>(&mut self, name: &str, ty: T) -> &mut Self
1309+
where T: Into<Type>,
1310+
{
1311+
self.push_named(Field {
1312+
name: name.to_string(),
1313+
ty: ty.into(),
1314+
documentation: Vec::new(),
1315+
annotation: Vec::new(),
1316+
})
1317+
}
1318+
12711319
fn tuple<T>(&mut self, ty: T) -> &mut Self
12721320
where T: Into<Type>,
12731321
{
@@ -1291,6 +1339,16 @@ impl Fields {
12911339

12921340
fmt.block(|fmt| {
12931341
for f in fields {
1342+
if !f.documentation.is_empty() {
1343+
for doc in &f.documentation {
1344+
write!(fmt, "/// {}\n", doc)?;
1345+
}
1346+
}
1347+
if !f.annotation.is_empty() {
1348+
for ann in &f.annotation {
1349+
write!(fmt, "{}\n", ann)?;
1350+
}
1351+
}
12941352
write!(fmt, "{}: ", f.name)?;
12951353
f.ty.fmt(fmt)?;
12961354
write!(fmt, ",\n")?;
@@ -1366,6 +1424,8 @@ impl Impl {
13661424
self.assoc_tys.push(Field {
13671425
name: name.to_string(),
13681426
ty: ty.into(),
1427+
documentation: Vec::new(),
1428+
annotation: Vec::new(),
13691429
});
13701430

13711431
self
@@ -1517,6 +1577,11 @@ impl Function {
15171577
self.args.push(Field {
15181578
name: name.to_string(),
15191579
ty: ty.into(),
1580+
// While a `Field` is used here, both `documentation`
1581+
// and `annotation` does not make sense for function arguments.
1582+
// Simply use empty strings.
1583+
documentation: Vec::new(),
1584+
annotation: Vec::new(),
15201585
});
15211586

15221587
self

tests/codegen.rs

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
extern crate codegen;
22

3-
use codegen::{Scope, Variant};
4-
3+
use codegen::{Field, Scope, Struct, Variant};
54
#[test]
65
fn empty_scope() {
76
let scope = Scope::new();
@@ -26,6 +25,64 @@ struct Foo {
2625
assert_eq!(scope.to_string(), &expect[1..]);
2726
}
2827

28+
#[test]
29+
fn struct_with_pushed_field() {
30+
let mut scope = Scope::new();
31+
let mut struct_ = Struct::new("Foo");
32+
let mut field = Field::new("one", "usize");
33+
struct_.push_field(field);
34+
scope.push_struct(struct_);
35+
36+
let expect = r#"
37+
struct Foo {
38+
one: usize,
39+
}"#;
40+
41+
assert_eq!(scope.to_string(), &expect[1..]);
42+
}
43+
44+
#[test]
45+
fn single_struct_documented_field() {
46+
let mut scope = Scope::new();
47+
48+
let doc = vec!["Field's documentation", "Second line"];
49+
50+
let mut struct_ = Struct::new("Foo");
51+
52+
let mut field1 = Field::new("one", "usize");
53+
field1.doc(doc.clone());
54+
struct_.push_field(field1);
55+
56+
let mut field2 = Field::new("two", "usize");
57+
field2.annotation(vec![r#"#[serde(rename = "bar")]"#]);
58+
struct_.push_field(field2);
59+
60+
let mut field3 = Field::new("three", "usize");
61+
field3.doc(doc).annotation(vec![
62+
r#"#[serde(skip_serializing)]"#,
63+
r#"#[serde(skip_deserializing)]"#,
64+
]);
65+
struct_.push_field(field3);
66+
67+
scope.push_struct(struct_);
68+
69+
let expect = r#"
70+
struct Foo {
71+
/// Field's documentation
72+
/// Second line
73+
one: usize,
74+
#[serde(rename = "bar")]
75+
two: usize,
76+
/// Field's documentation
77+
/// Second line
78+
#[serde(skip_serializing)]
79+
#[serde(skip_deserializing)]
80+
three: usize,
81+
}"#;
82+
83+
assert_eq!(scope.to_string(), &expect[1..]);
84+
}
85+
2986
#[test]
3087
fn empty_struct() {
3188
let mut scope = Scope::new();

0 commit comments

Comments
 (0)