From 411c8e616ed881229708a3b2267005adfac398dd Mon Sep 17 00:00:00 2001 From: Nicolas Bigaouette Date: Fri, 5 Jan 2018 21:43:44 -0500 Subject: [PATCH 01/13] Let `Field` be public --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 26368cb..b2fabc3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -128,7 +128,7 @@ enum Fields { /// Defines a struct field. #[derive(Debug, Clone)] -struct Field { +pub struct Field { /// Field name name: String, From 7d187d17f7166d1eba77b31f05cd56844196852e Mon Sep 17 00:00:00 2001 From: Nicolas Bigaouette Date: Fri, 5 Jan 2018 21:45:06 -0500 Subject: [PATCH 02/13] Add `Struct::push_field()` to push a field to a struct with named fields --- src/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index b2fabc3..883291d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -582,6 +582,16 @@ impl Struct { self } + /// Push a named field to the struct. + /// + /// A struct can either set named fields with this function or tuple fields + /// with `push_tuple_field`, but not both. + pub fn push_field(&mut self, field: Field) -> &mut Self + { + self.fields.push_named(field); + self + } + /// Add a named field to the struct. /// /// A struct can either set named fields with this function or tuple fields From 40842616f9822f9b3cc5fb4c5b0e148d26947eb1 Mon Sep 17 00:00:00 2001 From: Nicolas Bigaouette Date: Fri, 5 Jan 2018 21:46:27 -0500 Subject: [PATCH 03/13] Add `Field::new()` impl --- src/lib.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 883291d..1767493 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1083,6 +1083,21 @@ impl AssociatedType { } } +// ===== impl Field ===== + +impl Field { + /// Return a field definition with the provided name and type + pub fn new(name: &str, ty: T) -> Self + where T: Into, + { + Field { + name: name.into(), + ty: ty.into(), + } + } + +} + // ===== impl Fields ===== impl Fields { From 6093af4a03a362d3677cf39d9a94e6dc00cd28a8 Mon Sep 17 00:00:00 2001 From: Nicolas Bigaouette Date: Fri, 5 Jan 2018 21:48:03 -0500 Subject: [PATCH 04/13] Split `Fields::named()` into `named()` and `push_named()` --- src/lib.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1767493..530cbb8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1101,28 +1101,30 @@ impl Field { // ===== impl Fields ===== impl Fields { - fn named(&mut self, name: &str, ty: T) -> &mut Self - where T: Into, + fn push_named(&mut self, field: Field) -> &mut Self { match *self { Fields::Empty => { - *self = Fields::Named(vec![Field { - name: name.to_string(), - ty: ty.into(), - }]); + *self = Fields::Named(vec![field]); } Fields::Named(ref mut fields) => { - fields.push(Field { - name: name.to_string(), - ty: ty.into(), - }); + fields.push(field); } _ => panic!("field list is named"), - } + }; self } + fn named(&mut self, name: &str, ty: T) -> &mut Self + where T: Into, + { + self.push_named(Field { + name: name.to_string(), + ty: ty.into(), + }) + } + fn tuple(&mut self, ty: T) -> &mut Self where T: Into, { From 911dbc81d5d00c584eb0064002ce240f91ca1c14 Mon Sep 17 00:00:00 2001 From: Nicolas Bigaouette Date: Fri, 5 Jan 2018 21:52:04 -0500 Subject: [PATCH 05/13] Add test adding `Field` to `Struct` --- tests/codegen.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/codegen.rs b/tests/codegen.rs index 0a4f7c9..70e4442 100644 --- a/tests/codegen.rs +++ b/tests/codegen.rs @@ -1,6 +1,6 @@ extern crate codegen; -use codegen::Scope; +use codegen::{Field, Scope, Struct}; #[test] fn empty_scope() { @@ -26,6 +26,22 @@ struct Foo { assert_eq!(scope.to_string(), &expect[1..]); } +#[test] +fn struct_with_pushed_field() { + let mut scope = Scope::new(); + let mut struct_ = Struct::new("Foo"); + let mut field = Field::new("one", "usize"); + struct_.push_field(field); + scope.push_struct(struct_); + + let expect = r#" +struct Foo { + one: usize, +}"#; + + assert_eq!(scope.to_string(), &expect[1..]); +} + #[test] fn empty_struct() { let mut scope = Scope::new(); From 3981c19b76ac7e5e7bc9ec5427d382007ca8c218 Mon Sep 17 00:00:00 2001 From: Nicolas Bigaouette Date: Fri, 5 Jan 2018 21:54:45 -0500 Subject: [PATCH 06/13] Add a `documentation` field to `Field` and `with_documentation()` fn --- src/lib.rs | 16 ++++++++++++++++ tests/codegen.rs | 22 ++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 530cbb8..11d4d21 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -134,6 +134,9 @@ pub struct Field { /// Field type ty: Type, + + /// Field documentation + documentation: String, } /// Defines an associated type. @@ -1093,9 +1096,16 @@ impl Field { Field { name: name.into(), ty: ty.into(), + documentation: String::new(), } } + /// Set field's documentation. + pub fn with_documentation(&mut self, documentation: &str) -> &mut Self { + self.documentation = documentation.into(); + self + } + } // ===== impl Fields ===== @@ -1122,6 +1132,7 @@ impl Fields { self.push_named(Field { name: name.to_string(), ty: ty.into(), + documentation: String::new(), }) } @@ -1148,6 +1159,9 @@ impl Fields { fmt.block(|fmt| { for f in fields { + if !f.documentation.is_empty() { + write!(fmt, "/// {}\n", f.documentation)?; + } write!(fmt, "{}: ", f.name)?; f.ty.fmt(fmt)?; write!(fmt, ",\n")?; @@ -1223,6 +1237,7 @@ impl Impl { self.assoc_tys.push(Field { name: name.to_string(), ty: ty.into(), + documentation: String::new(), }); self @@ -1367,6 +1382,7 @@ impl Function { self.args.push(Field { name: name.to_string(), ty: ty.into(), + documentation: String::new(), }); self diff --git a/tests/codegen.rs b/tests/codegen.rs index 70e4442..bde215d 100644 --- a/tests/codegen.rs +++ b/tests/codegen.rs @@ -42,6 +42,28 @@ struct Foo { assert_eq!(scope.to_string(), &expect[1..]); } +#[test] +fn single_struct_documented_field() { + let mut scope = Scope::new(); + + let doc = "Field's documentation"; + + let mut struct_ = Struct::new("Foo"); + + let mut field1 = Field::new("one", "usize"); + field1.with_documentation(doc); + + scope.push_struct(struct_); + + let expect = r#" +struct Foo { + /// Field's documentation + one: usize, +}"#; + + assert_eq!(scope.to_string(), &expect[1..]); +} + #[test] fn empty_struct() { let mut scope = Scope::new(); From 3e44fb60bb2b2261830586e674a84f883ec6b414 Mon Sep 17 00:00:00 2001 From: Nicolas Bigaouette Date: Fri, 5 Jan 2018 21:55:13 -0500 Subject: [PATCH 07/13] Add a `annotation` field to `Field` and `with_annotation()` fn --- src/lib.rs | 18 ++++++++++++++++++ tests/codegen.rs | 15 +++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 11d4d21..f3a0a99 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -137,6 +137,9 @@ pub struct Field { /// Field documentation documentation: String, + + /// Field annotation + annotation: String, } /// Defines an associated type. @@ -1097,6 +1100,7 @@ impl Field { name: name.into(), ty: ty.into(), documentation: String::new(), + annotation: String::new(), } } @@ -1106,6 +1110,11 @@ impl Field { self } + /// Set field's annotation. + pub fn with_annotation(&mut self, annotation: &str) -> &mut Self { + self.annotation = annotation.into(); + self + } } // ===== impl Fields ===== @@ -1133,6 +1142,7 @@ impl Fields { name: name.to_string(), ty: ty.into(), documentation: String::new(), + annotation: String::new(), }) } @@ -1162,6 +1172,9 @@ impl Fields { if !f.documentation.is_empty() { write!(fmt, "/// {}\n", f.documentation)?; } + if !f.annotation.is_empty() { + write!(fmt, "{}\n", f.annotation)?; + } write!(fmt, "{}: ", f.name)?; f.ty.fmt(fmt)?; write!(fmt, ",\n")?; @@ -1238,6 +1251,7 @@ impl Impl { name: name.to_string(), ty: ty.into(), documentation: String::new(), + annotation: String::new(), }); self @@ -1382,7 +1396,11 @@ impl Function { self.args.push(Field { name: name.to_string(), ty: ty.into(), + // While a `Field` is used here, both `documentation` + // and `annotation` does not make sense for function arguments. + // Simply use empty strings. documentation: String::new(), + annotation: String::new(), }); self diff --git a/tests/codegen.rs b/tests/codegen.rs index bde215d..7ea0d65 100644 --- a/tests/codegen.rs +++ b/tests/codegen.rs @@ -47,11 +47,21 @@ fn single_struct_documented_field() { let mut scope = Scope::new(); let doc = "Field's documentation"; + let anot = r#"#[serde(rename = "bar")]"#; let mut struct_ = Struct::new("Foo"); let mut field1 = Field::new("one", "usize"); field1.with_documentation(doc); + struct_.push_field(field1); + + let mut field2 = Field::new("two", "usize"); + field2.with_annotation(anot); + struct_.push_field(field2); + + let mut field3 = Field::new("three", "usize"); + field3.with_documentation(doc).with_annotation(anot); + struct_.push_field(field3); scope.push_struct(struct_); @@ -59,6 +69,11 @@ fn single_struct_documented_field() { struct Foo { /// Field's documentation one: usize, + #[serde(rename = "bar")] + two: usize, + /// Field's documentation + #[serde(rename = "bar")] + three: usize, }"#; assert_eq!(scope.to_string(), &expect[1..]); From 2d8d4b04fcbd15e1751c0d4f5447b2af49bde515 Mon Sep 17 00:00:00 2001 From: Nicolas Bigaouette Date: Mon, 8 Jan 2018 13:42:09 -0500 Subject: [PATCH 08/13] Review: Rename `with_documentation()` to `doc()` --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index f3a0a99..3ad8397 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1105,7 +1105,7 @@ impl Field { } /// Set field's documentation. - pub fn with_documentation(&mut self, documentation: &str) -> &mut Self { + pub fn doc(&mut self, documentation: &str) -> &mut Self { self.documentation = documentation.into(); self } From 5aafce792fb06138bdf741ad70d13ba24a32956c Mon Sep 17 00:00:00 2001 From: Nicolas Bigaouette Date: Mon, 8 Jan 2018 13:42:26 -0500 Subject: [PATCH 09/13] Review: Rename `with_annotation()` to `annotation()` --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 3ad8397..848d20a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1111,7 +1111,7 @@ impl Field { } /// Set field's annotation. - pub fn with_annotation(&mut self, annotation: &str) -> &mut Self { + pub fn annotation(&mut self, annotation: &str) -> &mut Self { self.annotation = annotation.into(); self } From 3d032ea68c80a7488d3287e11d21ce89636671e2 Mon Sep 17 00:00:00 2001 From: Nicolas Bigaouette Date: Mon, 8 Jan 2018 13:44:55 -0500 Subject: [PATCH 10/13] Review: Fix tests --- tests/codegen.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/codegen.rs b/tests/codegen.rs index 7ea0d65..8e87164 100644 --- a/tests/codegen.rs +++ b/tests/codegen.rs @@ -52,15 +52,15 @@ fn single_struct_documented_field() { let mut struct_ = Struct::new("Foo"); let mut field1 = Field::new("one", "usize"); - field1.with_documentation(doc); + field1.doc(doc); struct_.push_field(field1); let mut field2 = Field::new("two", "usize"); - field2.with_annotation(anot); + field2.annotation(anot); struct_.push_field(field2); let mut field3 = Field::new("three", "usize"); - field3.with_documentation(doc).with_annotation(anot); + field3.doc(doc).annotation(anot); struct_.push_field(field3); scope.push_struct(struct_); From 95b6673dae4268f9db39b6ee76c02571e29761e0 Mon Sep 17 00:00:00 2001 From: Nicolas Bigaouette Date: Mon, 8 Jan 2018 13:46:16 -0500 Subject: [PATCH 11/13] Review: Delete useless semicolon --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 848d20a..798e349 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1130,7 +1130,7 @@ impl Fields { fields.push(field); } _ => panic!("field list is named"), - }; + } self } From 6e17dc251c40eb8729b819287fc533c68ff60030 Mon Sep 17 00:00:00 2001 From: Nicolas Bigaouette Date: Fri, 20 Apr 2018 10:11:32 -0400 Subject: [PATCH 12/13] Let `Field.annotation` be a `Vec` instead of `String` for multi-line annotation --- src/lib.rs | 18 ++++++++++-------- tests/codegen.rs | 11 +++++++---- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 798e349..5403ccb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -139,7 +139,7 @@ pub struct Field { documentation: String, /// Field annotation - annotation: String, + annotation: Vec, } /// Defines an associated type. @@ -1100,7 +1100,7 @@ impl Field { name: name.into(), ty: ty.into(), documentation: String::new(), - annotation: String::new(), + annotation: Vec::new(), } } @@ -1111,8 +1111,8 @@ impl Field { } /// Set field's annotation. - pub fn annotation(&mut self, annotation: &str) -> &mut Self { - self.annotation = annotation.into(); + pub fn annotation(&mut self, annotation: Vec<&str>) -> &mut Self { + self.annotation = annotation.iter().map(|ann| ann.to_string()).collect(); self } } @@ -1142,7 +1142,7 @@ impl Fields { name: name.to_string(), ty: ty.into(), documentation: String::new(), - annotation: String::new(), + annotation: Vec::new(), }) } @@ -1173,7 +1173,9 @@ impl Fields { write!(fmt, "/// {}\n", f.documentation)?; } if !f.annotation.is_empty() { - write!(fmt, "{}\n", f.annotation)?; + for ann in &f.annotation { + write!(fmt, "{}\n", ann)?; + } } write!(fmt, "{}: ", f.name)?; f.ty.fmt(fmt)?; @@ -1251,7 +1253,7 @@ impl Impl { name: name.to_string(), ty: ty.into(), documentation: String::new(), - annotation: String::new(), + annotation: Vec::new(), }); self @@ -1400,7 +1402,7 @@ impl Function { // and `annotation` does not make sense for function arguments. // Simply use empty strings. documentation: String::new(), - annotation: String::new(), + annotation: Vec::new(), }); self diff --git a/tests/codegen.rs b/tests/codegen.rs index 8e87164..e25ff88 100644 --- a/tests/codegen.rs +++ b/tests/codegen.rs @@ -47,7 +47,6 @@ fn single_struct_documented_field() { let mut scope = Scope::new(); let doc = "Field's documentation"; - let anot = r#"#[serde(rename = "bar")]"#; let mut struct_ = Struct::new("Foo"); @@ -56,11 +55,14 @@ fn single_struct_documented_field() { struct_.push_field(field1); let mut field2 = Field::new("two", "usize"); - field2.annotation(anot); + field2.annotation(vec![r#"#[serde(rename = "bar")]"#]); struct_.push_field(field2); let mut field3 = Field::new("three", "usize"); - field3.doc(doc).annotation(anot); + field3.doc(doc).annotation(vec![ + r#"#[serde(skip_serializing)]"#, + r#"#[serde(skip_deserializing)]"#, + ]); struct_.push_field(field3); scope.push_struct(struct_); @@ -72,7 +74,8 @@ struct Foo { #[serde(rename = "bar")] two: usize, /// Field's documentation - #[serde(rename = "bar")] + #[serde(skip_serializing)] + #[serde(skip_deserializing)] three: usize, }"#; From 2528d99d53cbd6638b1a73bc73740bbdffaa99cd Mon Sep 17 00:00:00 2001 From: Nicolas Bigaouette Date: Sun, 17 Jun 2018 10:56:18 -0400 Subject: [PATCH 13/13] Let `Field.documentation` be a `Vec` instead of `String` for multi-line documentation --- src/lib.rs | 18 ++++++++++-------- tests/codegen.rs | 6 ++++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5403ccb..396fc6b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -136,7 +136,7 @@ pub struct Field { ty: Type, /// Field documentation - documentation: String, + documentation: Vec, /// Field annotation annotation: Vec, @@ -1099,14 +1099,14 @@ impl Field { Field { name: name.into(), ty: ty.into(), - documentation: String::new(), + documentation: Vec::new(), annotation: Vec::new(), } } /// Set field's documentation. - pub fn doc(&mut self, documentation: &str) -> &mut Self { - self.documentation = documentation.into(); + pub fn doc(&mut self, documentation: Vec<&str>) -> &mut Self { + self.documentation = documentation.iter().map(|doc| doc.to_string()).collect(); self } @@ -1141,7 +1141,7 @@ impl Fields { self.push_named(Field { name: name.to_string(), ty: ty.into(), - documentation: String::new(), + documentation: Vec::new(), annotation: Vec::new(), }) } @@ -1170,7 +1170,9 @@ impl Fields { fmt.block(|fmt| { for f in fields { if !f.documentation.is_empty() { - write!(fmt, "/// {}\n", f.documentation)?; + for doc in &f.documentation { + write!(fmt, "/// {}\n", doc)?; + } } if !f.annotation.is_empty() { for ann in &f.annotation { @@ -1252,7 +1254,7 @@ impl Impl { self.assoc_tys.push(Field { name: name.to_string(), ty: ty.into(), - documentation: String::new(), + documentation: Vec::new(), annotation: Vec::new(), }); @@ -1401,7 +1403,7 @@ impl Function { // While a `Field` is used here, both `documentation` // and `annotation` does not make sense for function arguments. // Simply use empty strings. - documentation: String::new(), + documentation: Vec::new(), annotation: Vec::new(), }); diff --git a/tests/codegen.rs b/tests/codegen.rs index e25ff88..2f68dbc 100644 --- a/tests/codegen.rs +++ b/tests/codegen.rs @@ -46,12 +46,12 @@ struct Foo { fn single_struct_documented_field() { let mut scope = Scope::new(); - let doc = "Field's documentation"; + let doc = vec!["Field's documentation", "Second line"]; let mut struct_ = Struct::new("Foo"); let mut field1 = Field::new("one", "usize"); - field1.doc(doc); + field1.doc(doc.clone()); struct_.push_field(field1); let mut field2 = Field::new("two", "usize"); @@ -70,10 +70,12 @@ fn single_struct_documented_field() { let expect = r#" struct Foo { /// Field's documentation + /// Second line one: usize, #[serde(rename = "bar")] two: usize, /// Field's documentation + /// Second line #[serde(skip_serializing)] #[serde(skip_deserializing)] three: usize,