diff --git a/docs/source/Compiler.md b/docs/source/Compiler.md index 6d881cc8f..a155df468 100755 --- a/docs/source/Compiler.md +++ b/docs/source/Compiler.md @@ -114,6 +114,8 @@ Additional options: to the reflection/reflection.fbs schema. Loading this binary file is the basis for reflection functionality. +- `--bfbs-comments`: Add doc comments to the binary schema files. + - `--conform FILE` : Specify a schema the following schemas should be an evolution of. Gives errors if not. Useful to check if schema modifications don't break schema evolution rules. diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 2e09b39a5..5b7a72a3c 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -356,6 +356,7 @@ struct IDLOptions { bool union_value_namespacing; bool allow_non_utf8; std::string include_prefix; + bool binary_schema_comments; // Possible options for the more general generator below. enum Language { @@ -396,6 +397,7 @@ struct IDLOptions { cpp_object_api_pointer_type("std::unique_ptr"), union_value_namespacing(true), allow_non_utf8(false), + binary_schema_comments(false), lang(IDLOptions::kJava), lang_to_generate(0) {} }; diff --git a/include/flatbuffers/reflection_generated.h b/include/flatbuffers/reflection_generated.h index df745f231..8379dcf52 100644 --- a/include/flatbuffers/reflection_generated.h +++ b/include/flatbuffers/reflection_generated.h @@ -294,7 +294,8 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_VALUES = 6, VT_IS_UNION = 8, VT_UNDERLYING_TYPE = 10, - VT_ATTRIBUTES = 12 + VT_ATTRIBUTES = 12, + VT_DOCUMENTATION = 14 }; const flatbuffers::String *name() const { return GetPointer(VT_NAME); @@ -317,6 +318,9 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const flatbuffers::Vector> *attributes() const { return GetPointer> *>(VT_ATTRIBUTES); } + const flatbuffers::Vector> *documentation() const { + return GetPointer> *>(VT_DOCUMENTATION); + } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyFieldRequired(verifier, VT_NAME) && @@ -330,6 +334,9 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyField(verifier, VT_ATTRIBUTES) && verifier.Verify(attributes()) && verifier.VerifyVectorOfTables(attributes()) && + VerifyField(verifier, VT_DOCUMENTATION) && + verifier.Verify(documentation()) && + verifier.VerifyVectorOfStrings(documentation()) && verifier.EndTable(); } }; @@ -352,13 +359,16 @@ struct EnumBuilder { void add_attributes(flatbuffers::Offset>> attributes) { fbb_.AddOffset(Enum::VT_ATTRIBUTES, attributes); } + void add_documentation(flatbuffers::Offset>> documentation) { + fbb_.AddOffset(Enum::VT_DOCUMENTATION, documentation); + } EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } EnumBuilder &operator=(const EnumBuilder &); flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_, 5); + const auto end = fbb_.EndTable(start_, 6); auto o = flatbuffers::Offset(end); fbb_.Required(o, Enum::VT_NAME); fbb_.Required(o, Enum::VT_VALUES); @@ -373,8 +383,10 @@ inline flatbuffers::Offset CreateEnum( flatbuffers::Offset>> values = 0, bool is_union = false, flatbuffers::Offset underlying_type = 0, - flatbuffers::Offset>> attributes = 0) { + flatbuffers::Offset>> attributes = 0, + flatbuffers::Offset>> documentation = 0) { EnumBuilder builder_(_fbb); + builder_.add_documentation(documentation); builder_.add_attributes(attributes); builder_.add_underlying_type(underlying_type); builder_.add_values(values); @@ -389,14 +401,16 @@ inline flatbuffers::Offset CreateEnumDirect( const std::vector> *values = nullptr, bool is_union = false, flatbuffers::Offset underlying_type = 0, - const std::vector> *attributes = nullptr) { + const std::vector> *attributes = nullptr, + const std::vector> *documentation = nullptr) { return reflection::CreateEnum( _fbb, name ? _fbb.CreateString(name) : 0, values ? _fbb.CreateVector>(*values) : 0, is_union, underlying_type, - attributes ? _fbb.CreateVector>(*attributes) : 0); + attributes ? _fbb.CreateVector>(*attributes) : 0, + documentation ? _fbb.CreateVector>(*documentation) : 0); } struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { @@ -410,7 +424,8 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_DEPRECATED = 16, VT_REQUIRED = 18, VT_KEY = 20, - VT_ATTRIBUTES = 22 + VT_ATTRIBUTES = 22, + VT_DOCUMENTATION = 24 }; const flatbuffers::String *name() const { return GetPointer(VT_NAME); @@ -448,6 +463,9 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const flatbuffers::Vector> *attributes() const { return GetPointer> *>(VT_ATTRIBUTES); } + const flatbuffers::Vector> *documentation() const { + return GetPointer> *>(VT_DOCUMENTATION); + } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyFieldRequired(verifier, VT_NAME) && @@ -464,6 +482,9 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyField(verifier, VT_ATTRIBUTES) && verifier.Verify(attributes()) && verifier.VerifyVectorOfTables(attributes()) && + VerifyField(verifier, VT_DOCUMENTATION) && + verifier.Verify(documentation()) && + verifier.VerifyVectorOfStrings(documentation()) && verifier.EndTable(); } }; @@ -501,13 +522,16 @@ struct FieldBuilder { void add_attributes(flatbuffers::Offset>> attributes) { fbb_.AddOffset(Field::VT_ATTRIBUTES, attributes); } + void add_documentation(flatbuffers::Offset>> documentation) { + fbb_.AddOffset(Field::VT_DOCUMENTATION, documentation); + } FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } FieldBuilder &operator=(const FieldBuilder &); flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_, 10); + const auto end = fbb_.EndTable(start_, 11); auto o = flatbuffers::Offset(end); fbb_.Required(o, Field::VT_NAME); fbb_.Required(o, Field::VT_TYPE); @@ -526,10 +550,12 @@ inline flatbuffers::Offset CreateField( bool deprecated = false, bool required = false, bool key = false, - flatbuffers::Offset>> attributes = 0) { + flatbuffers::Offset>> attributes = 0, + flatbuffers::Offset>> documentation = 0) { FieldBuilder builder_(_fbb); builder_.add_default_real(default_real); builder_.add_default_integer(default_integer); + builder_.add_documentation(documentation); builder_.add_attributes(attributes); builder_.add_type(type); builder_.add_name(name); @@ -552,7 +578,8 @@ inline flatbuffers::Offset CreateFieldDirect( bool deprecated = false, bool required = false, bool key = false, - const std::vector> *attributes = nullptr) { + const std::vector> *attributes = nullptr, + const std::vector> *documentation = nullptr) { return reflection::CreateField( _fbb, name ? _fbb.CreateString(name) : 0, @@ -564,7 +591,8 @@ inline flatbuffers::Offset CreateFieldDirect( deprecated, required, key, - attributes ? _fbb.CreateVector>(*attributes) : 0); + attributes ? _fbb.CreateVector>(*attributes) : 0, + documentation ? _fbb.CreateVector>(*documentation) : 0); } struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { @@ -574,7 +602,8 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_IS_STRUCT = 8, VT_MINALIGN = 10, VT_BYTESIZE = 12, - VT_ATTRIBUTES = 14 + VT_ATTRIBUTES = 14, + VT_DOCUMENTATION = 16 }; const flatbuffers::String *name() const { return GetPointer(VT_NAME); @@ -600,6 +629,9 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const flatbuffers::Vector> *attributes() const { return GetPointer> *>(VT_ATTRIBUTES); } + const flatbuffers::Vector> *documentation() const { + return GetPointer> *>(VT_DOCUMENTATION); + } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyFieldRequired(verifier, VT_NAME) && @@ -613,6 +645,9 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyField(verifier, VT_ATTRIBUTES) && verifier.Verify(attributes()) && verifier.VerifyVectorOfTables(attributes()) && + VerifyField(verifier, VT_DOCUMENTATION) && + verifier.Verify(documentation()) && + verifier.VerifyVectorOfStrings(documentation()) && verifier.EndTable(); } }; @@ -638,13 +673,16 @@ struct ObjectBuilder { void add_attributes(flatbuffers::Offset>> attributes) { fbb_.AddOffset(Object::VT_ATTRIBUTES, attributes); } + void add_documentation(flatbuffers::Offset>> documentation) { + fbb_.AddOffset(Object::VT_DOCUMENTATION, documentation); + } ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } ObjectBuilder &operator=(const ObjectBuilder &); flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_, 6); + const auto end = fbb_.EndTable(start_, 7); auto o = flatbuffers::Offset(end); fbb_.Required(o, Object::VT_NAME); fbb_.Required(o, Object::VT_FIELDS); @@ -659,8 +697,10 @@ inline flatbuffers::Offset CreateObject( bool is_struct = false, int32_t minalign = 0, int32_t bytesize = 0, - flatbuffers::Offset>> attributes = 0) { + flatbuffers::Offset>> attributes = 0, + flatbuffers::Offset>> documentation = 0) { ObjectBuilder builder_(_fbb); + builder_.add_documentation(documentation); builder_.add_attributes(attributes); builder_.add_bytesize(bytesize); builder_.add_minalign(minalign); @@ -677,7 +717,8 @@ inline flatbuffers::Offset CreateObjectDirect( bool is_struct = false, int32_t minalign = 0, int32_t bytesize = 0, - const std::vector> *attributes = nullptr) { + const std::vector> *attributes = nullptr, + const std::vector> *documentation = nullptr) { return reflection::CreateObject( _fbb, name ? _fbb.CreateString(name) : 0, @@ -685,7 +726,8 @@ inline flatbuffers::Offset CreateObjectDirect( is_struct, minalign, bytesize, - attributes ? _fbb.CreateVector>(*attributes) : 0); + attributes ? _fbb.CreateVector>(*attributes) : 0, + documentation ? _fbb.CreateVector>(*documentation) : 0); } struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { diff --git a/reflection/reflection.fbs b/reflection/reflection.fbs index 57f234c6a..76ccf85cc 100644 --- a/reflection/reflection.fbs +++ b/reflection/reflection.fbs @@ -51,6 +51,7 @@ table Enum { is_union:bool = false; underlying_type:Type (required); attributes:[KeyValue]; + documentation:[string]; } table Field { @@ -64,6 +65,7 @@ table Field { required:bool = false; key:bool = false; attributes:[KeyValue]; + documentation:[string]; } table Object { // Used for both tables and structs. @@ -73,6 +75,7 @@ table Object { // Used for both tables and structs. minalign:int; bytesize:int; // For structs. attributes:[KeyValue]; + documentation:[string]; } table Schema { diff --git a/src/flatc.cpp b/src/flatc.cpp index 053f112b1..ed13c2ad5 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -93,6 +93,7 @@ std::string FlatCompiler::GetUsageString(const char* program_name) const { " --proto Input is a .proto, translate to .fbs.\n" " --grpc Generate GRPC interfaces for the specified languages\n" " --schema Serialize schemas instead of JSON (use with -b)\n" + " --bfbs-comments Add doc comments to the binary schema files.\n" " --conform FILE Specify a schema the following schemas should be\n" " an evolution of. Gives errors if not.\n" " --conform-includes Include path for the schema given with --conform\n" @@ -204,6 +205,8 @@ int FlatCompiler::Compile(int argc, const char** argv) { exit(0); } else if(arg == "--grpc") { grpc_enabled = true; + } else if(arg == "--bfbs-comments") { + opts.binary_schema_comments = true; } else { for (size_t i = 0; i < params_.num_generators; ++i) { if (arg == params_.generators[i].generator_opt_long || diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 454abd308..7adfcca24 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -2086,7 +2086,11 @@ Offset StructDef::Serialize(FlatBufferBuilder *builder, fixed, static_cast(minalign), static_cast(bytesize), - SerializeAttributes(builder, parser)); + SerializeAttributes(builder, parser), + parser.opts.binary_schema_comments + ? builder->CreateVectorOfStrings( + doc_comment) + : 0); } Offset FieldDef::Serialize(FlatBufferBuilder *builder, @@ -2106,7 +2110,10 @@ Offset FieldDef::Serialize(FlatBufferBuilder *builder, deprecated, required, key, - SerializeAttributes(builder, parser)); + SerializeAttributes(builder, parser), + parser.opts.binary_schema_comments + ? builder->CreateVectorOfStrings(doc_comment) + : 0); // TODO: value.constant is almost always "0", we could save quite a bit of // space by sharing it. Same for common values of value.type. } @@ -2123,7 +2130,10 @@ Offset EnumDef::Serialize(FlatBufferBuilder *builder, builder->CreateVector(enumval_offsets), is_union, underlying_type.Serialize(builder), - SerializeAttributes(builder, parser)); + SerializeAttributes(builder, parser), + parser.opts.binary_schema_comments + ? builder->CreateVectorOfStrings(doc_comment) + : 0); } Offset EnumVal::Serialize(FlatBufferBuilder *builder) const diff --git a/tests/generate_code.sh b/tests/generate_code.sh index 0510b01d2..a5354ebce 100755 --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@ -17,6 +17,7 @@ ../flatc --cpp --java --csharp --go --binary --python --js --php --grpc --gen-mutable --gen-object-api --no-includes monster_test.fbs monsterdata_test.json ../flatc --cpp --java --csharp --go --binary --python --js --php --gen-mutable -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs ../flatc --cpp -o union_vector ./union_vector/union_vector.fbs +../flatc -b --schema --bfbs-comments monster_test.fbs cd ../samples ../flatc --cpp --gen-mutable --gen-object-api monster.fbs cd ../reflection diff --git a/tests/monster_test.bfbs b/tests/monster_test.bfbs index 41d9edb1c..21f3c0008 100644 Binary files a/tests/monster_test.bfbs and b/tests/monster_test.bfbs differ