From fb943bf6dcac743b39472d9305464a2effcb64cf Mon Sep 17 00:00:00 2001 From: Greg Tatum Date: Thu, 16 Sep 2021 15:26:43 -0500 Subject: [PATCH] Generate C++ code docs (#85) * drive-by: Add some miscellaneous code docs * Add support for generating C++ comments * Add new snapshots for documentation of C++ structs * Generate documentation for the Deleter structs * Update snapshots for the Deleter comment * Fix misplaced comments in c++ docs * Re-generated the c++ examples --- example/cpp/ICU4XDataProvider.hpp | 7 +++ example/cpp/ICU4XFixedDecimal.hpp | 27 ++++++++++ example/cpp/ICU4XFixedDecimalFormat.hpp | 15 ++++++ .../cpp/ICU4XFixedDecimalFormatOptions.hpp | 3 ++ example/cpp/ICU4XFixedDecimalFormatResult.hpp | 11 ++++ example/cpp/ICU4XLocale.hpp | 7 +++ tool/src/cpp/conversions.rs | 3 ++ tool/src/cpp/mod.rs | 24 ++++++++- ...sions__tests__enum_conversion@Foo.hpp.snap | 3 ++ ...__tests__enum_conversion@MyStruct.hpp.snap | 3 ++ ...tests__method_taking_str@MyStruct.hpp.snap | 3 ++ ...ts__method_writeable_out@MyStruct.hpp.snap | 3 ++ ...simple_non_opaque_struct@MyStruct.hpp.snap | 3 ++ ...ts__simple_opaque_struct@MyStruct.hpp.snap | 3 ++ ...__tests__struct_documentation@Foo.hpp.snap | 53 +++++++++++++++++++ ...s__cross_module_struct_fields@Bar.hpp.snap | 3 ++ ...s__cross_module_struct_fields@Foo.hpp.snap | 3 ++ ...__cross_module_struct_methods@Bar.hpp.snap | 3 ++ ...__cross_module_struct_methods@Foo.hpp.snap | 3 ++ ..._tests__enum_documentation@MyEnum.hpp.snap | 45 ++++++++++++++++ ...ests__option_types@MyOpaqueStruct.hpp.snap | 3 ++ ...pes__tests__option_types@MyStruct.hpp.snap | 3 ++ ...sts__pointer_types@MyOpaqueStruct.hpp.snap | 3 ++ ...es__tests__pointer_types@MyStruct.hpp.snap | 3 ++ ...ests__result_types@MyOpaqueStruct.hpp.snap | 3 ++ ...pes__tests__result_types@MyStruct.hpp.snap | 3 ++ ..._tests__string_reference@MyStruct.hpp.snap | 3 ++ ..._types__tests__unit_type@MyStruct.hpp.snap | 3 ++ ...es__tests__writeable_out@MyStruct.hpp.snap | 3 ++ tool/src/cpp/structs.rs | 36 ++++++++++++- tool/src/cpp/test_util.rs | 14 +++++ tool/src/cpp/util.rs | 15 ++++++ tool/src/main.rs | 1 + 33 files changed, 315 insertions(+), 3 deletions(-) create mode 100644 tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__struct_documentation@Foo.hpp.snap create mode 100644 tool/src/cpp/snapshots/diplomat_tool__cpp__tests__enum_documentation@MyEnum.hpp.snap diff --git a/example/cpp/ICU4XDataProvider.hpp b/example/cpp/ICU4XDataProvider.hpp index 0b39ce5a1..6587980ef 100644 --- a/example/cpp/ICU4XDataProvider.hpp +++ b/example/cpp/ICU4XDataProvider.hpp @@ -15,6 +15,9 @@ namespace capi { class ICU4XDataProvider; +/** + * A destruction policy for using ICU4XDataProvider with std::unique_ptr. + */ struct ICU4XDataProviderDeleter { void operator()(capi::ICU4XDataProvider* l) const noexcept { capi::ICU4XDataProvider_destroy(l); @@ -22,6 +25,10 @@ struct ICU4XDataProviderDeleter { }; class ICU4XDataProvider { public: + + /** + * Construct a [StaticDataProvider](https://unicode-org.github.io/icu4x-docs/doc/icu_testdata/fn.get_static_provider.html). + */ static ICU4XDataProvider new_static(); inline const capi::ICU4XDataProvider* AsFFI() const { return this->inner.get(); } inline capi::ICU4XDataProvider* AsFFIMut() { return this->inner.get(); } diff --git a/example/cpp/ICU4XFixedDecimal.hpp b/example/cpp/ICU4XFixedDecimal.hpp index af89d64bb..ff2adba10 100644 --- a/example/cpp/ICU4XFixedDecimal.hpp +++ b/example/cpp/ICU4XFixedDecimal.hpp @@ -15,6 +15,9 @@ namespace capi { class ICU4XFixedDecimal; +/** + * A destruction policy for using ICU4XFixedDecimal with std::unique_ptr. + */ struct ICU4XFixedDecimalDeleter { void operator()(capi::ICU4XFixedDecimal* l) const noexcept { capi::ICU4XFixedDecimal_destroy(l); @@ -22,10 +25,34 @@ struct ICU4XFixedDecimalDeleter { }; class ICU4XFixedDecimal { public: + + /** + * Construct an [`ICU4XFixedDecimal`] from an integer. + */ static ICU4XFixedDecimal new_(int32_t v); + + /** + * Multiply the [`ICU4XFixedDecimal`] by a given power of ten. + * See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/fixed_decimal/decimal/struct.FixedDecimal.html#method.multiply_pow10) for more information. + */ void multiply_pow10(int16_t power); + + /** + * Invert the sign of the [`ICU4XFixedDecimal`]. + * See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/fixed_decimal/decimal/struct.FixedDecimal.html#method.negate) for more information. + */ void negate(); + + /** + * Format the [`ICU4XFixedDecimal`] as a string. + * See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/fixed_decimal/decimal/struct.FixedDecimal.html#method.write_to) for more information. + */ template diplomat::result to_string_to_writeable(W& to) const; + + /** + * Format the [`ICU4XFixedDecimal`] as a string. + * See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/fixed_decimal/decimal/struct.FixedDecimal.html#method.write_to) for more information. + */ diplomat::result to_string() const; inline const capi::ICU4XFixedDecimal* AsFFI() const { return this->inner.get(); } inline capi::ICU4XFixedDecimal* AsFFIMut() { return this->inner.get(); } diff --git a/example/cpp/ICU4XFixedDecimalFormat.hpp b/example/cpp/ICU4XFixedDecimalFormat.hpp index 52daf7ea0..4bec7df46 100644 --- a/example/cpp/ICU4XFixedDecimalFormat.hpp +++ b/example/cpp/ICU4XFixedDecimalFormat.hpp @@ -19,6 +19,9 @@ struct ICU4XFixedDecimalFormatOptions; struct ICU4XFixedDecimalFormatResult; class ICU4XFixedDecimal; +/** + * A destruction policy for using ICU4XFixedDecimalFormat with std::unique_ptr. + */ struct ICU4XFixedDecimalFormatDeleter { void operator()(capi::ICU4XFixedDecimalFormat* l) const noexcept { capi::ICU4XFixedDecimalFormat_destroy(l); @@ -26,8 +29,20 @@ struct ICU4XFixedDecimalFormatDeleter { }; class ICU4XFixedDecimalFormat { public: + + /** + * Creates a new [`ICU4XFixedDecimalFormat`] from locale data. See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu/decimal/struct.FixedDecimalFormat.html#method.try_new) for more information. + */ static ICU4XFixedDecimalFormatResult try_new(const ICU4XLocale& locale, const ICU4XDataProvider& provider, ICU4XFixedDecimalFormatOptions options); + + /** + * Formats a [`ICU4XFixedDecimal`] to a string. See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu/decimal/struct.FixedDecimalFormat.html#method.format) for more information. + */ template void format_write_to_writeable(const ICU4XFixedDecimal& value, W& write) const; + + /** + * Formats a [`ICU4XFixedDecimal`] to a string. See [the Rust docs](https://unicode-org.github.io/icu4x-docs/doc/icu/decimal/struct.FixedDecimalFormat.html#method.format) for more information. + */ std::string format_write(const ICU4XFixedDecimal& value) const; inline const capi::ICU4XFixedDecimalFormat* AsFFI() const { return this->inner.get(); } inline capi::ICU4XFixedDecimalFormat* AsFFIMut() { return this->inner.get(); } diff --git a/example/cpp/ICU4XFixedDecimalFormatOptions.hpp b/example/cpp/ICU4XFixedDecimalFormatOptions.hpp index 5896b07cc..543b34c3a 100644 --- a/example/cpp/ICU4XFixedDecimalFormatOptions.hpp +++ b/example/cpp/ICU4XFixedDecimalFormatOptions.hpp @@ -17,6 +17,9 @@ namespace capi { #include "ICU4XFixedDecimalSignDisplay.hpp" struct ICU4XFixedDecimalFormatOptions; +/** + * A destruction policy for using ICU4XFixedDecimalFormatOptions with std::unique_ptr. + */ struct ICU4XFixedDecimalFormatOptionsDeleter { void operator()(capi::ICU4XFixedDecimalFormatOptions* l) const noexcept { capi::ICU4XFixedDecimalFormatOptions_destroy(l); diff --git a/example/cpp/ICU4XFixedDecimalFormatResult.hpp b/example/cpp/ICU4XFixedDecimalFormatResult.hpp index cdb96242c..71e42afab 100644 --- a/example/cpp/ICU4XFixedDecimalFormatResult.hpp +++ b/example/cpp/ICU4XFixedDecimalFormatResult.hpp @@ -15,6 +15,9 @@ namespace capi { class ICU4XFixedDecimalFormat; +/** + * A destruction policy for using ICU4XFixedDecimalFormatResult with std::unique_ptr. + */ struct ICU4XFixedDecimalFormatResultDeleter { void operator()(capi::ICU4XFixedDecimalFormatResult* l) const noexcept { capi::ICU4XFixedDecimalFormatResult_destroy(l); @@ -22,7 +25,15 @@ struct ICU4XFixedDecimalFormatResultDeleter { }; struct ICU4XFixedDecimalFormatResult { public: + + /** + * The [`ICU4XFixedDecimalFormat`], exists if creation was successful. + */ std::optional fdf; + + /** + * Whether creating the [`ICU4XFixedDecimalFormat`] was successful. + */ bool success; }; diff --git a/example/cpp/ICU4XLocale.hpp b/example/cpp/ICU4XLocale.hpp index 818c5d0d5..6bf3c338b 100644 --- a/example/cpp/ICU4XLocale.hpp +++ b/example/cpp/ICU4XLocale.hpp @@ -15,6 +15,9 @@ namespace capi { class ICU4XLocale; +/** + * A destruction policy for using ICU4XLocale with std::unique_ptr. + */ struct ICU4XLocaleDeleter { void operator()(capi::ICU4XLocale* l) const noexcept { capi::ICU4XLocale_destroy(l); @@ -22,6 +25,10 @@ struct ICU4XLocaleDeleter { }; class ICU4XLocale { public: + + /** + * Construct an [`ICU4XLocale`] from an locale identifier. + */ static ICU4XLocale new_(const std::string_view name); inline const capi::ICU4XLocale* AsFFI() const { return this->inner.get(); } inline capi::ICU4XLocale* AsFFIMut() { return this->inner.get(); } diff --git a/tool/src/cpp/conversions.rs b/tool/src/cpp/conversions.rs index 854e53435..3037e127a 100644 --- a/tool/src/cpp/conversions.rs +++ b/tool/src/cpp/conversions.rs @@ -147,9 +147,12 @@ pub fn gen_rust_to_cpp( } } +/// Meta information about a [ast::TypeName::Reference]. #[derive(Eq, PartialEq)] pub struct ReferenceMeta { + /// Whether or not the reference is owned. owned: bool, + /// Whether or not the reference is mutable. mutable: bool, } diff --git a/tool/src/cpp/mod.rs b/tool/src/cpp/mod.rs index 053f12363..8e140fe41 100644 --- a/tool/src/cpp/mod.rs +++ b/tool/src/cpp/mod.rs @@ -14,6 +14,8 @@ mod types; mod structs; use structs::*; +use crate::cpp::util::gen_comment_block; + mod conversions; pub mod docs; @@ -66,9 +68,11 @@ pub fn gen_bindings( ast::CustomType::Enum(enm) => { writeln!(out)?; + gen_comment_block(out, &enm.doc_lines)?; writeln!(out, "enum struct {} {{", enm.name)?; let mut enm_indent = indented(out).with_str(" "); - for (name, discriminant, _) in enm.variants.iter() { + for (name, discriminant, doc_lines) in enm.variants.iter() { + gen_comment_block(&mut enm_indent, doc_lines)?; writeln!(&mut enm_indent, "{} = {},", name, discriminant)?; } writeln!(out, "}};")?; @@ -358,4 +362,22 @@ mod tests { } } } + + #[test] + fn test_enum_documentation() { + test_file! { + #[diplomat::bridge] + mod ffi { + /// Documentation for MyEnum. + enum MyEnum { + /// All about A. + A, + /// All about B. + B, + /// All about C. + C + } + } + } + } } diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__conversions__tests__enum_conversion@Foo.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__conversions__tests__enum_conversion@Foo.hpp.snap index 3f353c46f..e0b2f4f06 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__conversions__tests__enum_conversion@Foo.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__conversions__tests__enum_conversion@Foo.hpp.snap @@ -20,6 +20,9 @@ namespace capi { struct MyStruct; +/** + * A destruction policy for using Foo with std::unique_ptr. + */ struct FooDeleter { void operator()(capi::Foo* l) const noexcept { capi::Foo_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__conversions__tests__enum_conversion@MyStruct.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__conversions__tests__enum_conversion@MyStruct.hpp.snap index 695496a65..f9e7f5397 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__conversions__tests__enum_conversion@MyStruct.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__conversions__tests__enum_conversion@MyStruct.hpp.snap @@ -20,6 +20,9 @@ namespace capi { #include "MyEnum.hpp" +/** + * A destruction policy for using MyStruct with std::unique_ptr. + */ struct MyStructDeleter { void operator()(capi::MyStruct* l) const noexcept { capi::MyStruct_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__method_taking_str@MyStruct.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__method_taking_str@MyStruct.hpp.snap index e2f79efbe..b4964ea50 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__method_taking_str@MyStruct.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__method_taking_str@MyStruct.hpp.snap @@ -20,6 +20,9 @@ namespace capi { class MyStruct; +/** + * A destruction policy for using MyStruct with std::unique_ptr. + */ struct MyStructDeleter { void operator()(capi::MyStruct* l) const noexcept { capi::MyStruct_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__method_writeable_out@MyStruct.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__method_writeable_out@MyStruct.hpp.snap index a12c44616..51c64f0f4 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__method_writeable_out@MyStruct.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__method_writeable_out@MyStruct.hpp.snap @@ -19,6 +19,9 @@ namespace capi { } +/** + * A destruction policy for using MyStruct with std::unique_ptr. + */ struct MyStructDeleter { void operator()(capi::MyStruct* l) const noexcept { capi::MyStruct_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__simple_non_opaque_struct@MyStruct.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__simple_non_opaque_struct@MyStruct.hpp.snap index 7b251df5b..0ffc2a85a 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__simple_non_opaque_struct@MyStruct.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__simple_non_opaque_struct@MyStruct.hpp.snap @@ -20,6 +20,9 @@ namespace capi { struct MyStruct; +/** + * A destruction policy for using MyStruct with std::unique_ptr. + */ struct MyStructDeleter { void operator()(capi::MyStruct* l) const noexcept { capi::MyStruct_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__simple_opaque_struct@MyStruct.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__simple_opaque_struct@MyStruct.hpp.snap index d437acb78..ddc1ce288 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__simple_opaque_struct@MyStruct.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__simple_opaque_struct@MyStruct.hpp.snap @@ -20,6 +20,9 @@ namespace capi { class MyStruct; +/** + * A destruction policy for using MyStruct with std::unique_ptr. + */ struct MyStructDeleter { void operator()(capi::MyStruct* l) const noexcept { capi::MyStruct_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__struct_documentation@Foo.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__struct_documentation@Foo.hpp.snap new file mode 100644 index 000000000..e3fe5ab8c --- /dev/null +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__structs__tests__struct_documentation@Foo.hpp.snap @@ -0,0 +1,53 @@ +--- +source: tool/src/cpp/structs.rs +expression: out_texts.get(out).unwrap() + +--- +#ifndef Foo_HPP +#define Foo_HPP +#include +#include +#include +#include +#include +#include +#include +#include "diplomat_runtime.hpp" + +namespace capi { +#include "Foo.h" +} + + +/** + * A destruction policy for using Foo with std::unique_ptr. + */ +struct FooDeleter { + void operator()(capi::Foo* l) const noexcept { + capi::Foo_destroy(l); + } +}; + +/** + * Documentation for Foo. + * Second line. + */ +struct Foo { + public: + + /** + * Documentation for x. + */ + uint8_t x; + + /** + * Documentation for get_x. + */ + uint8_t get_x() const; +}; + + +inline uint8_t Foo::get_x() const { + return capi::Foo_get_x((capi::Foo*) &this); +} +#endif diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_fields@Bar.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_fields@Bar.hpp.snap index 9cb0e5d8e..240c995fa 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_fields@Bar.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_fields@Bar.hpp.snap @@ -20,6 +20,9 @@ namespace capi { struct Foo; +/** + * A destruction policy for using Bar with std::unique_ptr. + */ struct BarDeleter { void operator()(capi::Bar* l) const noexcept { capi::Bar_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_fields@Foo.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_fields@Foo.hpp.snap index 4306393ec..ae17cf7dd 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_fields@Foo.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_fields@Foo.hpp.snap @@ -20,6 +20,9 @@ namespace capi { #include "Bar.hpp" +/** + * A destruction policy for using Foo with std::unique_ptr. + */ struct FooDeleter { void operator()(capi::Foo* l) const noexcept { capi::Foo_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_methods@Bar.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_methods@Bar.hpp.snap index 74c9971b6..7aa6cb0dc 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_methods@Bar.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_methods@Bar.hpp.snap @@ -20,6 +20,9 @@ namespace capi { class Foo; +/** + * A destruction policy for using Bar with std::unique_ptr. + */ struct BarDeleter { void operator()(capi::Bar* l) const noexcept { capi::Bar_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_methods@Foo.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_methods@Foo.hpp.snap index 1222df413..9ab3be3ea 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_methods@Foo.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__cross_module_struct_methods@Foo.hpp.snap @@ -20,6 +20,9 @@ namespace capi { struct Bar; +/** + * A destruction policy for using Foo with std::unique_ptr. + */ struct FooDeleter { void operator()(capi::Foo* l) const noexcept { capi::Foo_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__enum_documentation@MyEnum.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__enum_documentation@MyEnum.hpp.snap new file mode 100644 index 000000000..1a88e1623 --- /dev/null +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__tests__enum_documentation@MyEnum.hpp.snap @@ -0,0 +1,45 @@ +--- +source: tool/src/cpp/mod.rs +expression: out_texts.get(out).unwrap() + +--- +#ifndef MyEnum_HPP +#define MyEnum_HPP +#include +#include +#include +#include +#include +#include +#include +#include "diplomat_runtime.hpp" + +namespace capi { +#include "MyEnum.h" +} + + + +/** + * Documentation for MyEnum. + */ +enum struct MyEnum { + + /** + * All about A. + */ + A = 0, + + /** + * All about B. + */ + B = 1, + + /** + * All about C. + */ + C = 2, +}; + +#endif + diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__option_types@MyOpaqueStruct.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__option_types@MyOpaqueStruct.hpp.snap index db00d1793..b70502b38 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__option_types@MyOpaqueStruct.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__option_types@MyOpaqueStruct.hpp.snap @@ -19,6 +19,9 @@ namespace capi { } +/** + * A destruction policy for using MyOpaqueStruct with std::unique_ptr. + */ struct MyOpaqueStructDeleter { void operator()(capi::MyOpaqueStruct* l) const noexcept { capi::MyOpaqueStruct_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__option_types@MyStruct.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__option_types@MyStruct.hpp.snap index 7640ed30a..aca6233c8 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__option_types@MyStruct.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__option_types@MyStruct.hpp.snap @@ -20,6 +20,9 @@ namespace capi { class MyOpaqueStruct; +/** + * A destruction policy for using MyStruct with std::unique_ptr. + */ struct MyStructDeleter { void operator()(capi::MyStruct* l) const noexcept { capi::MyStruct_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__pointer_types@MyOpaqueStruct.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__pointer_types@MyOpaqueStruct.hpp.snap index db00d1793..b70502b38 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__pointer_types@MyOpaqueStruct.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__pointer_types@MyOpaqueStruct.hpp.snap @@ -19,6 +19,9 @@ namespace capi { } +/** + * A destruction policy for using MyOpaqueStruct with std::unique_ptr. + */ struct MyOpaqueStructDeleter { void operator()(capi::MyOpaqueStruct* l) const noexcept { capi::MyOpaqueStruct_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__pointer_types@MyStruct.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__pointer_types@MyStruct.hpp.snap index d493c30b7..2938bc418 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__pointer_types@MyStruct.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__pointer_types@MyStruct.hpp.snap @@ -21,6 +21,9 @@ namespace capi { class MyOpaqueStruct; struct MyStruct; +/** + * A destruction policy for using MyStruct with std::unique_ptr. + */ struct MyStructDeleter { void operator()(capi::MyStruct* l) const noexcept { capi::MyStruct_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__result_types@MyOpaqueStruct.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__result_types@MyOpaqueStruct.hpp.snap index db00d1793..b70502b38 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__result_types@MyOpaqueStruct.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__result_types@MyOpaqueStruct.hpp.snap @@ -19,6 +19,9 @@ namespace capi { } +/** + * A destruction policy for using MyOpaqueStruct with std::unique_ptr. + */ struct MyOpaqueStructDeleter { void operator()(capi::MyOpaqueStruct* l) const noexcept { capi::MyOpaqueStruct_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__result_types@MyStruct.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__result_types@MyStruct.hpp.snap index 072407015..1cb36830d 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__result_types@MyStruct.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__result_types@MyStruct.hpp.snap @@ -21,6 +21,9 @@ namespace capi { class MyOpaqueStruct; struct MyStruct; +/** + * A destruction policy for using MyStruct with std::unique_ptr. + */ struct MyStructDeleter { void operator()(capi::MyStruct* l) const noexcept { capi::MyStruct_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__string_reference@MyStruct.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__string_reference@MyStruct.hpp.snap index 2ad9f86e0..ef1227153 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__string_reference@MyStruct.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__string_reference@MyStruct.hpp.snap @@ -20,6 +20,9 @@ namespace capi { struct MyStruct; +/** + * A destruction policy for using MyStruct with std::unique_ptr. + */ struct MyStructDeleter { void operator()(capi::MyStruct* l) const noexcept { capi::MyStruct_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__unit_type@MyStruct.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__unit_type@MyStruct.hpp.snap index 42c6b339a..957c41002 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__unit_type@MyStruct.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__unit_type@MyStruct.hpp.snap @@ -19,6 +19,9 @@ namespace capi { } +/** + * A destruction policy for using MyStruct with std::unique_ptr. + */ struct MyStructDeleter { void operator()(capi::MyStruct* l) const noexcept { capi::MyStruct_destroy(l); diff --git a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__writeable_out@MyStruct.hpp.snap b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__writeable_out@MyStruct.hpp.snap index 4bee2cce3..2a5e09b4f 100644 --- a/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__writeable_out@MyStruct.hpp.snap +++ b/tool/src/cpp/snapshots/diplomat_tool__cpp__types__tests__writeable_out@MyStruct.hpp.snap @@ -19,6 +19,9 @@ namespace capi { } +/** + * A destruction policy for using MyStruct with std::unique_ptr. + */ struct MyStructDeleter { void operator()(capi::MyStruct* l) const noexcept { capi::MyStruct_destroy(l); diff --git a/tool/src/cpp/structs.rs b/tool/src/cpp/structs.rs index 238c1a4f4..b8238cf6e 100644 --- a/tool/src/cpp/structs.rs +++ b/tool/src/cpp/structs.rs @@ -4,7 +4,7 @@ use std::{collections::HashMap, fmt}; use diplomat_core::ast; use indenter::indented; -use crate::cpp::util::transform_keyword_ident; +use crate::cpp::util::{gen_comment_block, transform_keyword_ident}; use super::conversions::{gen_cpp_to_rust, gen_rust_to_cpp}; use super::types::gen_type; @@ -17,6 +17,11 @@ pub fn gen_struct( out: &mut W, ) -> fmt::Result { if is_header { + writeln!( + out, + "/**\n * A destruction policy for using {} with std::unique_ptr.\n */", + custom_type.name() + )?; writeln!(out, "struct {}Deleter {{", custom_type.name())?; let mut deleter_body = indented(out).with_str(" "); writeln!( @@ -91,6 +96,7 @@ pub fn gen_struct( ast::CustomType::Struct(strct) => { if is_header { + gen_comment_block(out, &strct.doc_lines)?; writeln!(out, "struct {} {{", strct.name)?; writeln!(out, " public:")?; } @@ -102,7 +108,8 @@ pub fn gen_struct( }; if is_header { - for (name, typ, _) in &strct.fields { + for (name, typ, docs) in &strct.fields { + gen_comment_block(&mut public_body, docs)?; gen_type(typ, in_path, None, env, &mut public_body)?; writeln!(&mut public_body, " {};", name)?; } @@ -152,6 +159,9 @@ fn gen_method( gen_method(enclosing_type, method, in_path, is_header, false, env, out)?; } + if is_header { + gen_comment_block(out, &method.doc_lines)?; + } let params_to_gen = gen_method_interface( method, enclosing_type, @@ -465,4 +475,26 @@ mod tests { } } } + + #[test] + fn test_struct_documentation() { + test_file! { + #[diplomat::bridge] + mod ffi { + /// Documentation for Foo. + /// Second line. + struct Foo { + /// Documentation for x. + x: u8, + } + + impl Foo { + /// Documentation for get_x. + pub fn get_x(&self) -> u8 { + x + } + } + } + } + } } diff --git a/tool/src/cpp/test_util.rs b/tool/src/cpp/test_util.rs index ba39f21c3..903bb002a 100644 --- a/tool/src/cpp/test_util.rs +++ b/tool/src/cpp/test_util.rs @@ -1,3 +1,17 @@ +/// A macro to test that a cpp file matches the output from diplomat. It checks the output +/// against an [insta] snapshot. +/// +/// # Usage +/// ``` +/// test_file! { +/// #[diplomat::bridge] +/// mod ffi { +/// enum MyEnum { +/// A, B, C +/// } +/// } +/// } +/// ``` macro_rules! test_file { ($($file:tt)*) => { let parsed: syn::File = syn::parse_quote! { $($file)* }; diff --git a/tool/src/cpp/util.rs b/tool/src/cpp/util.rs index 4660ffa0e..7226585ec 100644 --- a/tool/src/cpp/util.rs +++ b/tool/src/cpp/util.rs @@ -1,3 +1,5 @@ +use std::fmt; + /// Transforms the given identifier to one that does not clash /// with a keyword if it does. pub fn transform_keyword_ident(ident: &str) -> String { @@ -8,3 +10,16 @@ pub fn transform_keyword_ident(ident: &str) -> String { ident.to_string() } } + +/// Generates a C++ comment block. +pub fn gen_comment_block(out: &mut W, comment: &str) -> fmt::Result { + if !comment.is_empty() { + writeln!(out)?; + writeln!(out, "/**")?; + for line in comment.lines() { + writeln!(out, " * {}", line)?; + } + writeln!(out, " */")?; + } + Ok(()) +} diff --git a/tool/src/main.rs b/tool/src/main.rs index 853745ea6..ba3804d57 100644 --- a/tool/src/main.rs +++ b/tool/src/main.rs @@ -17,6 +17,7 @@ mod js; mod layout; mod util; +/// diplomat-tool CLI options, as parsed by [structopt]. #[derive(Debug, StructOpt)] #[structopt( name = "diplomat-tool",