diff options
author | Wouter van Oortmerssen <aardappel@gmail.com> | 2017-10-02 15:41:34 -0700 |
---|---|---|
committer | Wouter van Oortmerssen <aardappel@gmail.com> | 2017-10-06 16:08:00 -0700 |
commit | 9c3920d0ab90e9442759c6b41c28af577759a692 (patch) | |
tree | 04b84e4d3b60b063b9da05e5a79e4ff9e3d02100 | |
parent | 5b4acf809ecadf408a966555e91c37f32b119d10 (diff) | |
download | flatbuffers-9c3920d0ab90e9442759c6b41c28af577759a692.tar.gz flatbuffers-9c3920d0ab90e9442759c6b41c28af577759a692.tar.bz2 flatbuffers-9c3920d0ab90e9442759c6b41c28af577759a692.zip |
Improved .proto conversion.
- Allowed enums to be declared before use.
- Generalized parsing of `required`.
- Reworked escaping of namespaces.
- Escaping field names that are C++ keywords.
- Many smaller fixes.
Change-Id: Ie580de7b70dc208f676f4f71bb0d061808648b8d
Tested: on Linux.
-rw-r--r-- | include/flatbuffers/idl.h | 18 | ||||
-rw-r--r-- | src/flatc.cpp | 3 | ||||
-rw-r--r-- | src/idl_gen_cpp.cpp | 231 | ||||
-rw-r--r-- | src/idl_gen_fbs.cpp | 41 | ||||
-rw-r--r-- | src/idl_parser.cpp | 116 | ||||
-rw-r--r-- | tests/prototest/test.golden | 8 |
6 files changed, 268 insertions, 149 deletions
diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index d092e44e..4fa401e9 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -199,7 +199,8 @@ template<typename T> class SymbolTable { // A name space, as set in the schema. struct Namespace { - std::vector<std::string> components; + Namespace() : from_table(0) {} + // Given a (potentally unqualified) name, return the "fully qualified" name // which has a full namespaced descriptor. @@ -207,12 +208,15 @@ struct Namespace { // the current namespace has. std::string GetFullyQualifiedName(const std::string &name, size_t max_components = 1000) const; + + std::vector<std::string> components; + size_t from_table; // Part of the namespace corresponds to a message/table. }; // Base class for all definition types (fields, structs_, enums_). struct Definition { Definition() : generated(false), defined_namespace(nullptr), - serialized_location(0), index(-1) {} + serialized_location(0), index(-1), refcount(1) {} flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset< reflection::KeyValue>>> @@ -229,6 +233,7 @@ struct Definition { // For use with Serialize() uoffset_t serialized_location; int index; // Inside the vector it is stored. + int refcount; }; struct FieldDef : public Definition { @@ -271,12 +276,15 @@ struct StructDef : public Definition { const Parser &parser) const; SymbolTable<FieldDef> fields; + bool fixed; // If it's struct, not a table. bool predecl; // If it's used before it was defined. bool sortbysize; // Whether fields come in the declaration or size order. bool has_key; // It has a key field. size_t minalign; // What the whole object needs to be aligned to. size_t bytesize; // Size if fixed. + + std::unique_ptr<std::string> original_location; }; inline bool IsStruct(const Type &type) { @@ -361,7 +369,6 @@ struct IDLOptions { bool generate_all; bool skip_unexpected_fields_in_json; bool generate_name_strings; - bool escape_proto_identifiers; bool generate_object_based_api; std::string cpp_object_api_pointer_type; std::string cpp_object_api_string_type; @@ -417,7 +424,6 @@ struct IDLOptions { generate_all(false), skip_unexpected_fields_in_json(false), generate_name_strings(false), - escape_proto_identifiers(false), generate_object_based_api(false), cpp_object_api_pointer_type("std::unique_ptr"), object_suffix("T"), @@ -568,7 +574,11 @@ class Parser : public ParserState { FLATBUFFERS_CHECKED_ERROR CheckInRange(int64_t val, int64_t min, int64_t max); + StructDef *LookupStruct(const std::string &id) const; + private: + void Message(const std::string &msg); + void Warning(const std::string &msg); FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg); FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val); FLATBUFFERS_CHECKED_ERROR Next(); diff --git a/src/flatc.cpp b/src/flatc.cpp index abc948c2..701f6fb8 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -85,7 +85,6 @@ std::string FlatCompiler::GetUsageString(const char* program_name) const { " --gen-mutable Generate accessors that can mutate buffers in-place.\n" " --gen-onefile Generate single output file for C#.\n" " --gen-name-strings Generate type name functions for C++.\n" - " --escape-proto-ids Disable appending '_' in namespaces names.\n" " --gen-object-api Generate an additional object-based API.\n" " --cpp-ptr-type T Set object API pointer type (default std::unique_ptr)\n" " --cpp-str-type T Set object API string type (default std::string)\n" @@ -228,8 +227,6 @@ int FlatCompiler::Compile(int argc, const char** argv) { binary_files_from = filenames.size(); } else if(arg == "--proto") { opts.proto_mode = true; - } else if(arg == "--escape-proto-ids") { - opts.escape_proto_identifiers = true; } else if(arg == "--schema") { schema_binary = true; } else if(arg == "-M") { diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index ee0c2b58..58b01705 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -39,7 +39,26 @@ class CppGenerator : public BaseGenerator { CppGenerator(const Parser &parser, const std::string &path, const std::string &file_name) : BaseGenerator(parser, path, file_name, "", "::"), - cur_name_space_(nullptr) {} + cur_name_space_(nullptr) { + const char *keywords[] = { + "alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel", + "atomic_commit", "atomic_noexcept", "auto", "bitand", "bitor", "bool", + "break", "case", "catch", "char", "char16_t", "char32_t", "class", + "compl", "concept", "const", "constexpr", "const_cast", "continue", + "co_await", "co_return", "co_yield", "decltype", "default", "delete", + "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", + "extern", "false", "float", "for", "friend", "goto", "if", "import", + "inline", "int", "long", "module", "mutable", "namespace", "new", + "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq", + "private", "protected", "public", "register", "reinterpret_cast", + "requires", "return", "short", "signed", "sizeof", "static", + "static_assert", "static_cast", "struct", "switch", "synchronized", + "template", "this", "thread_local", "throw", "true", "try", "typedef", + "typeid", "typename", "union", "unsigned", "using", "virtual", "void", + "volatile", "wchar_t", "while", "xor", "xor_eq", nullptr + }; + for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw); + } std::string GenIncludeGuard() const { // Generate include guard. @@ -85,6 +104,18 @@ class CppGenerator : public BaseGenerator { if (num_includes) code_ += ""; } + std::string EscapeKeyword(const std::string &name) const { + return keywords_.find(name) == keywords_.end() ? name : name + "_"; + } + + std::string Name(const Definition &def) const { + return EscapeKeyword(def.name); + } + + std::string Name(const EnumVal &ev) const { + return EscapeKeyword(ev.name); + } + // Iterate through all definitions we haven't generate code for (enums, // structs, and tables) and output them to a single file. bool generate() { @@ -115,9 +146,11 @@ class CppGenerator : public BaseGenerator { const auto &struct_def = **it; if (!struct_def.generated) { SetNameSpace(struct_def.defined_namespace); - code_ += "struct " + struct_def.name + ";"; + code_ += "struct " + Name(struct_def) + ";"; if (parser_.opts.generate_object_based_api && !struct_def.fixed) { - code_ += "struct " + NativeName(struct_def.name, &struct_def, parser_.opts) + ";"; + code_ += "struct " + + NativeName(Name(struct_def), &struct_def, parser_.opts) + + ";"; } code_ += ""; } @@ -204,10 +237,10 @@ class CppGenerator : public BaseGenerator { if (parser_.root_struct_def_) { auto &struct_def = *parser_.root_struct_def_; SetNameSpace(struct_def.defined_namespace); - const auto &name = struct_def.name; - const auto qualified_name = + auto name = Name(struct_def); + auto qualified_name = cur_name_space_->GetFullyQualifiedName(name); - const auto cpp_name = TranslateNameSpace(qualified_name); + auto cpp_name = TranslateNameSpace(qualified_name); code_.SetValue("STRUCT_NAME", name); code_.SetValue("CPP_NAME", cpp_name); @@ -307,6 +340,8 @@ class CppGenerator : public BaseGenerator { private: CodeWriter code_; + std::set<std::string> keywords_; + // This tracks the current namespace so we can insert namespace declarations. const Namespace *cur_name_space_; @@ -477,24 +512,24 @@ class CppGenerator : public BaseGenerator { std::string GenEnumDecl(const EnumDef &enum_def) const { const IDLOptions &opts = parser_.opts; - return (opts.scoped_enums ? "enum class " : "enum ") + enum_def.name; + return (opts.scoped_enums ? "enum class " : "enum ") + Name(enum_def); } std::string GenEnumValDecl(const EnumDef &enum_def, const std::string &enum_val) const { const IDLOptions &opts = parser_.opts; - return opts.prefixed_enums ? enum_def.name + "_" + enum_val : enum_val; + return opts.prefixed_enums ? Name(enum_def) + "_" + enum_val : enum_val; } std::string GetEnumValUse(const EnumDef &enum_def, const EnumVal &enum_val) const { const IDLOptions &opts = parser_.opts; if (opts.scoped_enums) { - return enum_def.name + "::" + enum_val.name; + return Name(enum_def) + "::" + Name(enum_val); } else if (opts.prefixed_enums) { - return enum_def.name + "_" + enum_val.name; + return Name(enum_def) + "_" + Name(enum_val); } else { - return enum_val.name; + return Name(enum_val); } } @@ -505,87 +540,87 @@ class CppGenerator : public BaseGenerator { std::string GetUnionElement(const EnumVal &ev, bool wrap, bool actual_type, bool native_type = false) { if (ev.union_type.base_type == BASE_TYPE_STRUCT) { - auto name = actual_type ? ev.union_type.struct_def->name : ev.name; + auto name = actual_type ? ev.union_type.struct_def->name : Name(ev); return wrap ? WrapInNameSpace(ev.union_type.struct_def->defined_namespace, name) : name; } else if (ev.union_type.base_type == BASE_TYPE_STRING) { return actual_type ? (native_type ? "std::string" : "flatbuffers::String") - : ev.name; + : Name(ev); } else { assert(false); - return ev.name; + return Name(ev); } } - static std::string UnionVerifySignature(const EnumDef &enum_def) { - return "bool Verify" + enum_def.name + + std::string UnionVerifySignature(const EnumDef &enum_def) { + return "bool Verify" + Name(enum_def) + "(flatbuffers::Verifier &verifier, const void *obj, " + - enum_def.name + " type)"; + Name(enum_def) + " type)"; } - static std::string UnionVectorVerifySignature(const EnumDef &enum_def) { - return "bool Verify" + enum_def.name + "Vector" + + std::string UnionVectorVerifySignature(const EnumDef &enum_def) { + return "bool Verify" + Name(enum_def) + "Vector" + "(flatbuffers::Verifier &verifier, " + "const flatbuffers::Vector<flatbuffers::Offset<void>> *values, " + "const flatbuffers::Vector<uint8_t> *types)"; } - static std::string UnionUnPackSignature(const EnumDef &enum_def, + std::string UnionUnPackSignature(const EnumDef &enum_def, bool inclass) { return (inclass ? "static " : "") + std::string("void *") + - (inclass ? "" : enum_def.name + "Union::") + - "UnPack(const void *obj, " + enum_def.name + + (inclass ? "" : Name(enum_def) + "Union::") + + "UnPack(const void *obj, " + Name(enum_def) + " type, const flatbuffers::resolver_function_t *resolver)"; } - static std::string UnionPackSignature(const EnumDef &enum_def, bool inclass) { + std::string UnionPackSignature(const EnumDef &enum_def, bool inclass) { return "flatbuffers::Offset<void> " + - (inclass ? "" : enum_def.name + "Union::") + + (inclass ? "" : Name(enum_def) + "Union::") + "Pack(flatbuffers::FlatBufferBuilder &_fbb, " + "const flatbuffers::rehasher_function_t *_rehasher" + (inclass ? " = nullptr" : "") + ") const"; } - static std::string TableCreateSignature(const StructDef &struct_def, + std::string TableCreateSignature(const StructDef &struct_def, bool predecl, const IDLOptions & opts) { - return "flatbuffers::Offset<" + struct_def.name + "> Create" + - struct_def.name + + return "flatbuffers::Offset<" + Name(struct_def) + "> Create" + + Name(struct_def) + "(flatbuffers::FlatBufferBuilder &_fbb, const " + - NativeName(struct_def.name, &struct_def, opts) + + NativeName(Name(struct_def), &struct_def, opts) + " *_o, const flatbuffers::rehasher_function_t *_rehasher" + (predecl ? " = nullptr" : "") + ")"; } - static std::string TablePackSignature(const StructDef &struct_def, + std::string TablePackSignature(const StructDef &struct_def, bool inclass, const IDLOptions & opts) { return std::string(inclass ? "static " : "") + - "flatbuffers::Offset<" + struct_def.name + "> " + - (inclass ? "" : struct_def.name + "::") + + "flatbuffers::Offset<" + Name(struct_def) + "> " + + (inclass ? "" : Name(struct_def) + "::") + "Pack(flatbuffers::FlatBufferBuilder &_fbb, " + - "const " + NativeName(struct_def.name, &struct_def, opts) + "* _o, " + + "const " + NativeName(Name(struct_def), &struct_def, opts) + "* _o, " + "const flatbuffers::rehasher_function_t *_rehasher" + (inclass ? " = nullptr" : "") + ")"; } - static std::string TableUnPackSignature(const StructDef &struct_def, + std::string TableUnPackSignature(const StructDef &struct_def, bool inclass, const IDLOptions & opts) { - return NativeName(struct_def.name, &struct_def, opts) + " *" + - (inclass ? "" : struct_def.name + "::") + + return NativeName(Name(struct_def), &struct_def, opts) + " *" + + (inclass ? "" : Name(struct_def) + "::") + "UnPack(const flatbuffers::resolver_function_t *_resolver" + (inclass ? " = nullptr" : "") + ") const"; } - static std::string TableUnPackToSignature(const StructDef &struct_def, + std::string TableUnPackToSignature(const StructDef &struct_def, bool inclass, const IDLOptions & opts) { - return "void " + (inclass ? "" : struct_def.name + "::") + - "UnPackTo(" + NativeName(struct_def.name, &struct_def, opts) + " *" + + return "void " + (inclass ? "" : Name(struct_def) + "::") + + "UnPackTo(" + NativeName(Name(struct_def), &struct_def, opts) + " *" + "_o, const flatbuffers::resolver_function_t *_resolver" + (inclass ? " = nullptr" : "") + ") const"; } @@ -613,14 +648,14 @@ class CppGenerator : public BaseGenerator { for (auto it = struct_def->fields.vec.begin(); it != struct_def->fields.vec.end(); ++it) { const auto &field = **it; - names.push_back(field.name); + names.push_back(Name(field)); types.push_back(field.value.type); } } else { for (auto it = enum_def->vals.vec.begin(); it != enum_def->vals.vec.end(); ++it) { const auto &ev = **it; - names.push_back(ev.name); + names.push_back(Name(ev)); types.push_back(enum_def->is_union ? ev.union_type : Type(enum_def->underlying_type)); if (static_cast<int64_t>(it - enum_def->vals.vec.begin()) != ev.value) { @@ -728,7 +763,7 @@ class CppGenerator : public BaseGenerator { // an enum string lookup table, // and an enum array of values void GenEnum(const EnumDef &enum_def) { - code_.SetValue("ENUM_NAME", enum_def.name); + code_.SetValue("ENUM_NAME", Name(enum_def)); code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false)); code_.SetValue("SEP", ""); @@ -745,7 +780,7 @@ class CppGenerator : public BaseGenerator { const auto &ev = **it; GenComment(ev.doc_comment, " "); - code_.SetValue("KEY", GenEnumValDecl(enum_def, ev.name)); + code_.SetValue("KEY", GenEnumValDecl(enum_def, Name(ev))); code_.SetValue("VALUE", NumToString(ev.value)); code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\"; code_.SetValue("SEP", ",\n"); @@ -822,7 +857,7 @@ class CppGenerator : public BaseGenerator { while (val++ != ev.value) { code_ += " \"\","; } - code_ += " \"" + ev.name + "\","; + code_ += " \"" + Name(ev) + "\","; } code_ += " nullptr"; code_ += " };"; @@ -868,7 +903,7 @@ class CppGenerator : public BaseGenerator { if (parser_.opts.generate_object_based_api && enum_def.is_union) { // Generate a union type - code_.SetValue("NAME", enum_def.name); + code_.SetValue("NAME", Name(enum_def)); code_.SetValue("NONE", GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE"))); @@ -917,7 +952,7 @@ class CppGenerator : public BaseGenerator { NativeName(GetUnionElement(ev, true, true, true), ev.union_type.struct_def, parser_.opts); code_.SetValue("NATIVE_TYPE", native_type); - code_.SetValue("NATIVE_NAME", ev.name); + code_.SetValue("NATIVE_NAME", Name(ev)); code_.SetValue("NATIVE_ID", GetEnumValUse(enum_def, ev)); code_ += " {{NATIVE_TYPE}} *As{{NATIVE_NAME}}() {"; @@ -947,7 +982,7 @@ class CppGenerator : public BaseGenerator { // verifier function to call, this should be safe even if the union type // has been corrupted, since the verifiers will simply fail when called // on the wrong type. - code_.SetValue("ENUM_NAME", enum_def.name); + code_.SetValue("ENUM_NAME", Name(enum_def)); code_ += "inline " + UnionVerifySignature(enum_def) + " {"; code_ += " switch (type) {"; @@ -989,8 +1024,8 @@ class CppGenerator : public BaseGenerator { code_ += "inline " + UnionVectorVerifySignature(enum_def) + " {"; code_ += " if (values->size() != types->size()) return false;"; code_ += " for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {"; - code_ += " if (!Verify" + enum_def.name + "("; - code_ += " verifier, values->Get(i), types->GetEnum<" + enum_def.name + ">(i))) {"; + code_ += " if (!Verify" + Name(enum_def) + "("; + code_ += " verifier, values->Get(i), types->GetEnum<" + Name(enum_def) + ">(i))) {"; code_ += " return false;"; code_ += " }"; code_ += " }"; @@ -1158,7 +1193,7 @@ class CppGenerator : public BaseGenerator { } std::string GenFieldOffsetName(const FieldDef &field) { - std::string uname = field.name; + std::string uname = Name(field); std::transform(uname.begin(), uname.end(), uname.begin(), ToUpper); return "VT_" + uname; } @@ -1202,7 +1237,7 @@ class CppGenerator : public BaseGenerator { void GenParam(const FieldDef &field, bool direct, const char *prefix) { code_.SetValue("PRE", prefix); - code_.SetValue("PARAM_NAME", field.name); + code_.SetValue("PARAM_NAME", Name(field)); if (direct && field.value.type.base_type == BASE_TYPE_STRING) { code_.SetValue("PARAM_TYPE", "const char *"); code_.SetValue("PARAM_VALUE", "nullptr"); @@ -1227,7 +1262,7 @@ class CppGenerator : public BaseGenerator { auto cpp_type = field.attributes.Lookup("cpp_type"); auto full_type = (cpp_type ? cpp_type->constant + " *" : type + " "); code_.SetValue("FIELD_TYPE", full_type); - code_.SetValue("FIELD_NAME", field.name); + code_.SetValue("FIELD_NAME", Name(field)); code_ += " {{FIELD_TYPE}}{{FIELD_NAME}};"; } } @@ -1247,7 +1282,7 @@ class CppGenerator : public BaseGenerator { if (!initializer_list.empty()) { initializer_list += ",\n "; } - initializer_list += field.name; + initializer_list += Name(field); initializer_list += "(" + GetDefaultScalarValue(field) + ")"; } else if (field.value.type.base_type == BASE_TYPE_STRUCT) { if (IsStruct(field.value.type)) { @@ -1257,14 +1292,14 @@ class CppGenerator : public BaseGenerator { initializer_list += ",\n "; } initializer_list += - field.name + "(" + native_default->constant + ")"; + Name(field) + "(" + native_default->constant + ")"; } } } else if (cpp_type) { if (!initializer_list.empty()) { initializer_list += ",\n "; } - initializer_list += field.name + "(0)"; + initializer_list += Name(field) + "(0)"; } } } @@ -1272,7 +1307,7 @@ class CppGenerator : public BaseGenerator { initializer_list = "\n : " + initializer_list; } - code_.SetValue("NATIVE_NAME", NativeName(struct_def.name, &struct_def, parser_.opts)); + code_.SetValue("NATIVE_NAME", NativeName(Name(struct_def), &struct_def, parser_.opts)); code_.SetValue("INIT_LIST", initializer_list); code_ += " {{NATIVE_NAME}}(){{INIT_LIST}} {"; @@ -1280,8 +1315,8 @@ class CppGenerator : public BaseGenerator { } void GenNativeTable(const StructDef &struct_def) { - const auto native_name = NativeName(struct_def.name, &struct_def, parser_.opts); - code_.SetValue("STRUCT_NAME", struct_def.name); + const auto native_name = NativeName(Name(struct_def), &struct_def, parser_.opts); + code_.SetValue("STRUCT_NAME", Name(struct_def)); code_.SetValue("NATIVE_NAME", native_name); // Generate a C++ object that can hold an unpacked version of this table. @@ -1300,7 +1335,7 @@ class CppGenerator : public BaseGenerator { // Generate the code to call the appropriate Verify function(s) for a field. void GenVerifyCall(const FieldDef &field, const char* prefix) { code_.SetValue("PRE", prefix); - code_.SetValue("NAME", field.name); + code_.SetValue("NAME", Name(field)); code_.SetValue("REQUIRED", field.required ? "Required" : ""); code_.SetValue("SIZE", GenTypeSize(field.value.type)); code_.SetValue("OFFSET", GenFieldOffsetName(field)); @@ -1369,14 +1404,14 @@ class CppGenerator : public BaseGenerator { // type name() const { return GetField<type>(offset, defaultval); } GenComment(struct_def.doc_comment); - code_.SetValue("STRUCT_NAME", struct_def.name); + code_.SetValue("STRUCT_NAME", Name(struct_def)); code_ += "struct {{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS" " : private flatbuffers::Table {"; if (parser_.opts.generate_object_based_api) { code_ += " typedef {{NATIVE_NAME}} NativeTableType;"; } - GenFullyQualifiedNameGetter(struct_def, struct_def.name); + GenFullyQualifiedNameGetter(struct_def, Name(struct_def)); // Generate field id constants. if (struct_def.fields.vec.size() > 0) { @@ -1412,7 +1447,7 @@ class CppGenerator : public BaseGenerator { const bool is_struct = IsStruct(field.value.type); const bool is_scalar = IsScalar(field.value.type.base_type); - code_.SetValue("FIELD_NAME", field.name); + code_.SetValue("FIELD_NAME", Name(field)); // Call a different accessor for pointers, that indirects. std::string accessor = ""; @@ -1458,12 +1493,12 @@ class CppGenerator : public BaseGenerator { auto full_struct_name = GetUnionElement(ev, true, true); // @TODO: Mby make this decisions more universal? How? - code_.SetValue("U_GET_TYPE", field.name + UnionTypeFieldSuffix()); + code_.SetValue("U_GET_TYPE", Name(field) + UnionTypeFieldSuffix()); code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace( u->defined_namespace, GetEnumValUse(*u, ev))); code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *"); code_.SetValue("U_FIELD_NAME", - field.name + "_as_" + ev.name); + Name(field) + "_as_" + Name(ev)); // `const Type *union_name_asType() const` accessor. code_ += " {{U_FIELD_TYPE}}{{U_FIELD_NAME}}() const {"; @@ -1481,7 +1516,7 @@ class CppGenerator : public BaseGenerator { code_.SetValue("OFFSET_NAME", offset_str); code_.SetValue("FIELD_TYPE", GenTypeBasic(field.value.type, true)); code_.SetValue("FIELD_VALUE", - GenUnderlyingCast(field, false, "_" + field.name)); + GenUnderlyingCast(field, false, "_" + Name(field))); code_.SetValue("DEFAULT_VALUE", GenDefaultConstant(field)); code_ += " bool mutate_{{FIELD_NAME}}({{FIELD_TYPE}} " @@ -1506,7 +1541,7 @@ class CppGenerator : public BaseGenerator { std::string qualified_name = parser_.current_namespace_->GetFullyQualifiedName( nested->constant); - auto nested_root = parser_.structs_.Lookup(qualified_name); + auto nested_root = parser_.LookupStruct(qualified_name); assert(nested_root); // Guaranteed to exist by parser. (void)nested_root; code_.SetValue("CPP_NAME", TranslateNameSpace(qualified_name)); @@ -1601,7 +1636,7 @@ class CppGenerator : public BaseGenerator { auto u = field.value.type.enum_def; if (u->uses_type_aliases) continue; - code_.SetValue("FIELD_NAME", field.name); + code_.SetValue("FIELD_NAME", Name(field)); for (auto u_it = u->vals.vec.begin(); u_it != u->vals.vec.end(); ++u_it) { @@ -1617,7 +1652,7 @@ class CppGenerator : public BaseGenerator { code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *"); code_.SetValue("U_ELEMENT_NAME", full_struct_name); code_.SetValue("U_FIELD_NAME", - field.name + "_as_" + ev.name); + Name(field) + "_as_" + Name(ev)); // `template<> const T *union_name_as<T>() const` accessor. code_ += "template<> " @@ -1640,7 +1675,7 @@ class CppGenerator : public BaseGenerator { } void GenBuilders(const StructDef &struct_def) { - code_.SetValue("STRUCT_NAME", struct_def.name); + code_.SetValue("STRUCT_NAME", Name(struct_def)); // Generate a builder struct: code_ += "struct {{STRUCT_NAME}}Builder {"; @@ -1660,16 +1695,16 @@ class CppGenerator : public BaseGenerator { } std::string offset = GenFieldOffsetName(field); - std::string name = GenUnderlyingCast(field, false, field.name); + std::string name = GenUnderlyingCast(field, false, Name(field)); std::string value = is_scalar ? GenDefaultConstant(field) : ""; // Generate accessor functions of the form: // void add_name(type name) { // fbb_.AddElement<type>(offset, name, default); // } - code_.SetValue("FIELD_NAME", field.name); + code_.SetValue("FIELD_NAME", Name(field)); code_.SetValue("FIELD_TYPE", GenTypeWire(field.value.type, " ", true)); - code_.SetValue("ADD_OFFSET", struct_def.name + "::" + offset); + code_.SetValue("ADD_OFFSET", Name(struct_def) + "::" + offset); code_.SetValue("ADD_NAME", name); code_.SetValue("ADD_VALUE", value); if (is_scalar) { @@ -1711,7 +1746,7 @@ class CppGenerator : public BaseGenerator { it != struct_def.fields.vec.end(); ++it) { const auto &field = **it; if (!field.deprecated && field.required) { - code_.SetValue("FIELD_NAME", field.name); + code_.SetValue("FIELD_NAME", Name(field)); code_.SetValue("OFFSET_NAME", GenFieldOffsetName(field)); code_ += " fbb_.Required(o, {{STRUCT_NAME}}::{{OFFSET_NAME}});"; } @@ -1743,7 +1778,7 @@ class CppGenerator : public BaseGenerator { const auto &field = **it; if (!field.deprecated && (!struct_def.sortbysize || size == SizeOf(field.value.type.base_type))) { - code_.SetValue("FIELD_NAME", field.name); + code_.SetValue("FIELD_NAME", Name(field)); code_ += " builder_.add_{{FIELD_NAME}}({{FIELD_NAME}});"; } } @@ -1776,7 +1811,7 @@ class CppGenerator : public BaseGenerator { it != struct_def.fields.vec.end(); ++it) { const auto &field = **it; if (!field.deprecated) { - code_.SetValue("FIELD_NAME", field.name); + code_.SetValue("FIELD_NAME", Name(field)); if (field.value.type.base_type == BASE_TYPE_STRING) { code_ += ",\n {{FIELD_NAME}} ? " @@ -1800,7 +1835,7 @@ class CppGenerator : public BaseGenerator { const char *vec_elem_access, const char *vec_type_access) { return afield.value.type.enum_def->name + "Union::UnPack(" + "_e" + - vec_elem_access + ", " + afield.name + UnionTypeFieldSuffix() + + vec_elem_access + ", " + Name(afield) + UnionTypeFieldSuffix() + "()" + vec_type_access + ", _resolver)"; } @@ -1860,9 +1895,9 @@ class CppGenerator : public BaseGenerator { // for (uoffset_t i = 0; i < _e->size(); ++i) { // _o->field.push_back(_e->Get(_i)); // } - auto name = field.name; + auto name = Name(field); if (field.value.type.element == BASE_TYPE_UTYPE) { - name = StripUnionType(field.name); + name = StripUnionType(Name(field)); } auto access = field.value.type.element == BASE_TYPE_UTYPE ? ".type" @@ -1888,7 +1923,7 @@ class CppGenerator : public BaseGenerator { case BASE_TYPE_UNION: { // Generate code that sets the union value, of the form: // _o->field.value = Union::Unpack(_e, field_type(), resolver); - code += "_o->" + field.name + ".value = "; + code += "_o->" + Name(field) + ".value = "; code += GenUnionUnpackVal(field, "", ""); code += ";"; break; @@ -1903,14 +1938,14 @@ class CppGenerator : public BaseGenerator { // _o->field = nullptr; code += "if (_resolver) "; code += "(*_resolver)"; - code += "(reinterpret_cast<void **>(&_o->" + field.name + "), "; + code += "(reinterpret_cast<void **>(&_o->" + Name(field) + "), "; code += "static_cast<flatbuffers::hash_value_t>(_e));"; code += " else "; - code += "_o->" + field.name + " = nullptr;"; + code += "_o->" + Name(field) + " = nullptr;"; } else { // Generate code for assigning the value, of the form: // _o->field = value; - code += "_o->" + field.name + " = "; + code += "_o->" + Name(field) + " = "; code += GenUnpackVal(field.value.type, "_e", false, field) + ";"; } break; @@ -1922,10 +1957,10 @@ class CppGenerator : public BaseGenerator { std::string GenCreateParam(const FieldDef &field) { std::string value = "_o->"; if (field.value.type.base_type == BASE_TYPE_UTYPE) { - value += StripUnionType(field.name); + value += StripUnionType(Name(field)); value += ".type"; } else { - value += field.name; + value += Name(field); } if (field.attributes.Lookup("cpp_type")) { auto type = GenTypeBasic(field.value.type, false); @@ -2062,8 +2097,8 @@ class CppGenerator : public BaseGenerator { // Generate code for tables that needs to come after the regular definition. void GenTablePost(const StructDef &struct_def) { - code_.SetValue("STRUCT_NAME", struct_def.name); - code_.SetValue("NATIVE_NAME", NativeName(struct_def.name, &struct_def, parser_.opts)); + code_.SetValue("STRUCT_NAME", Name(struct_def)); + code_.SetValue("NATIVE_NAME", NativeName(Name(struct_def), &struct_def, parser_.opts)); if (parser_.opts.generate_object_based_api) { // Generate the X::UnPack() method. @@ -2092,7 +2127,7 @@ class CppGenerator : public BaseGenerator { const auto statement = GenUnpackFieldStatement(field, is_union ? *(it + 1) : nullptr); - code_.SetValue("FIELD_NAME", field.name); + code_.SetValue("FIELD_NAME", Name(field)); auto prefix = " { auto _e = {{FIELD_NAME}}(); "; auto check = IsScalar(field.value.type.base_type) ? "" : "if (_e) "; auto postfix = " };"; @@ -2117,7 +2152,7 @@ class CppGenerator : public BaseGenerator { " struct _VectorArgs " "{ flatbuffers::FlatBufferBuilder *__fbb; " "const " + - NativeName(struct_def.name, &struct_def, parser_.opts) + + NativeName(Name(struct_def), &struct_def, parser_.opts) + "* __o; " "const flatbuffers::rehasher_function_t *__rehasher; } _va = { " "&_fbb, _o, _rehasher}; (void)_va;"; @@ -2128,7 +2163,7 @@ class CppGenerator : public BaseGenerator { if (field.deprecated) { continue; } - code_ += " auto _" + field.name + " = " + GenCreateParam(field) + ";"; + code_ += " auto _" + Name(field) + " = " + GenCreateParam(field) + ";"; } // Need to call "Create" with the struct namespace. const auto qualified_create_name = struct_def.defined_namespace->GetFullyQualifiedName("Create"); @@ -2156,9 +2191,9 @@ class CppGenerator : public BaseGenerator { // Call the CreateX function using values from |_o|. if (pass_by_address) { - code_ += ",\n &_" + field.name + "\\"; + code_ += ",\n &_" + Name(field) + "\\"; } else { - code_ += ",\n _" + field.name + "\\"; + code_ += ",\n _" + Name(field) + "\\"; } } code_ += ");"; @@ -2204,7 +2239,7 @@ class CppGenerator : public BaseGenerator { // platforms. GenComment(struct_def.doc_comment); code_.SetValue("ALIGN", NumToString(struct_def.minalign)); - code_.SetValue("STRUCT_NAME", struct_def.name); + code_.SetValue("STRUCT_NAME", Name(struct_def)); code_ += "MANUALLY_ALIGNED_STRUCT({{ALIGN}}) " "{{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS {"; @@ -2216,7 +2251,7 @@ class CppGenerator : public BaseGenerator { const auto &field = **it; code_.SetValue("FIELD_TYPE", GenTypeGet(field.value.type, " ", "", " ", false)); - code_.SetValue("FIELD_NAME", field.name); + code_.SetValue("FIELD_NAME", Name(field)); code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}_;"; if (field.padding) { @@ -2229,7 +2264,7 @@ class CppGenerator : public BaseGenerator { // Generate GetFullyQualifiedName code_ += ""; code_ += " public:"; - GenFullyQualifiedNameGetter(struct_def, struct_def.name); + GenFullyQualifiedNameGetter(struct_def, Name(struct_def)); // Generate a default constructor. code_ += " {{STRUCT_NAME}}() {"; @@ -2248,8 +2283,8 @@ class CppGenerator : public BaseGenerator { for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { const auto &field = **it; - const auto member_name = field.name + "_"; - const auto arg_name = "_" + field.name; + const auto member_name = Name(field) + "_"; + const auto arg_name = "_" + Name(field); const auto arg_type = GenTypeGet(field.value.type, " ", "const ", " &", true); @@ -2295,11 +2330,11 @@ class CppGenerator : public BaseGenerator { auto field_type = GenTypeGet(field.value.type, " ", "const ", " &", true); auto is_scalar = IsScalar(field.value.type.base_type); - auto member = field.name + "_"; + auto member = Name(field) + "_"; auto value = is_scalar ? "flatbuffers::EndianScalar(" + member + ")" : member; - code_.SetValue("FIELD_NAME", field.name); + code_.SetValue("FIELD_NAME", Name(field)); code_.SetValue("FIELD_TYPE", field_type); code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, value)); @@ -2314,7 +2349,7 @@ class CppGenerator : public BaseGenerator { if (is_scalar) { code_.SetValue("ARG", GenTypeBasic(field.value.type, true)); code_.SetValue("FIELD_VALUE", - GenUnderlyingCast(field, false, "_" + field.name)); + GenUnderlyingCast(field, false, "_" + Name(field))); code_ += " void mutate_{{FIELD_NAME}}({{ARG}} _{{FIELD_NAME}}) {"; code_ += " flatbuffers::WriteScalar(&{{FIELD_NAME}}_, " diff --git a/src/idl_gen_fbs.cpp b/src/idl_gen_fbs.cpp index c7762c12..2ef70dab 100644 --- a/src/idl_gen_fbs.cpp +++ b/src/idl_gen_fbs.cpp @@ -23,18 +23,20 @@ namespace flatbuffers { -static std::string GenType(const Type &type) { +static std::string GenType(const Type &type, bool underlying = false) { switch (type.base_type) { case BASE_TYPE_STRUCT: return type.struct_def->defined_namespace->GetFullyQualifiedName( type.struct_def->name); - case BASE_TYPE_UNION: - return type.enum_def->defined_namespace->GetFullyQualifiedName( - type.enum_def->name); case BASE_TYPE_VECTOR: return "[" + GenType(type.VectorType()) + "]"; default: - return kTypeNames[type.base_type]; + if (type.enum_def && !underlying) { + return type.enum_def->defined_namespace->GetFullyQualifiedName( + type.enum_def->name); + } else { + return kTypeNames[type.base_type]; + } } } @@ -54,14 +56,13 @@ static void GenNameSpace(const Namespace &name_space, std::string *_schema, // Generate a flatbuffer schema from the Parser's internal representation. std::string GenerateFBS(const Parser &parser, const std::string &file_name) { - // Proto namespaces may clash with table names, so we have to prefix all: - if (!parser.opts.escape_proto_identifiers) { - for (auto it = parser.namespaces_.begin(); it != parser.namespaces_.end(); - ++it) { - for (auto comp = (*it)->components.begin(); comp != (*it)->components.end(); - ++comp) { - (*comp) = "_" + (*comp); - } + // Proto namespaces may clash with table names, escape the ones that were + // generated from a table: + for (auto it = parser.namespaces_.begin(); it != parser.namespaces_.end(); + ++it) { + auto &ns = **it; + for (size_t i = 0; i < ns.from_table; i++) { + ns.components[ns.components.size() - 1 - i] += "_"; } } @@ -90,7 +91,7 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) { GenNameSpace(*enum_def.defined_namespace, &schema, &last_namespace); GenComment(enum_def.doc_comment, &schema, nullptr); schema += "enum " + enum_def.name + " : "; - schema += GenType(enum_def.underlying_type) + " {\n"; + schema += GenType(enum_def.underlying_type, true) + " {\n"; for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); ++it) { auto &ev = **it; @@ -109,11 +110,13 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) { for (auto field_it = struct_def.fields.vec.begin(); field_it != struct_def.fields.vec.end(); ++field_it) { auto &field = **field_it; - GenComment(field.doc_comment, &schema, nullptr, " "); - schema += " " + field.name + ":" + GenType(field.value.type); - if (field.value.constant != "0") schema += " = " + field.value.constant; - if (field.required) schema += " (required)"; - schema += ";\n"; + if (field.value.type.base_type != BASE_TYPE_UTYPE) { + GenComment(field.doc_comment, &schema, nullptr, " "); + schema += " " + field.name + ":" + GenType(field.value.type); + if (field.value.constant != "0") schema += " = " + field.value.constant; + if (field.required) schema += " (required)"; + schema += ";\n"; + } } schema += "}\n\n"; } diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index b919c3c5..cc58a1cd 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -75,7 +75,7 @@ static bool ValidateUTF8(const std::string &str) { return true; } -CheckedError Parser::Error(const std::string &msg) { +void Parser::Message(const std::string &msg) { error_ = file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : ""; #ifdef _WIN32 error_ += "(" + NumToString(line_) + ")"; // MSVC alike @@ -83,7 +83,15 @@ CheckedError Parser::Error(const std::string &msg) { if (file_being_parsed_.length()) error_ += ":"; error_ += NumToString(line_) + ":0"; // gcc alike #endif - error_ += ": error: " + msg; + error_ += ": " + msg; +} + +void Parser::Warning(const std::string &msg) { + Message("warning: " + msg); +} + +CheckedError Parser::Error(const std::string &msg) { + Message("error: " + msg); return CheckedError(true); } @@ -454,6 +462,12 @@ EnumDef *Parser::LookupEnum(const std::string &id) { return nullptr; } +StructDef *Parser::LookupStruct(const std::string &id) const { + auto sd = structs_.Lookup(id); + if (sd) sd->refcount++; + return sd; +} + CheckedError Parser::ParseTypeIdent(Type &type) { std::string id = attribute_; EXPECT(kTokenIdentifier); @@ -557,7 +571,7 @@ CheckedError Parser::AddField(StructDef &struct_def, const std::string &name, CheckedError Parser::ParseField(StructDef &struct_def) { std::string name = attribute_; - if (structs_.Lookup(name)) + if (LookupStruct(name)) return Error("field name can not be the same as table/struct name"); std::vector<std::string> dc = doc_comment_; @@ -610,7 +624,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) { !type.enum_def->attributes.Lookup("bit_flags") && !type.enum_def->ReverseLookup(static_cast<int>( StringToInt(field->value.constant.c_str())))) - return Error("enum " + type.enum_def->name + + Warning("enum " + type.enum_def->name + " does not have a declaration for this field\'s default of " + field->value.constant); @@ -682,7 +696,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) { // Keep a pointer to StructDef in FieldDef to simplify re-use later auto nested_qualified_name = current_namespace_->GetFullyQualifiedName(nested->constant); - field->nested_flatbuffer = structs_.Lookup(nested_qualified_name); + field->nested_flatbuffer = LookupStruct(nested_qualified_name); } if (field->attributes.Lookup("flexbuffer")) { @@ -1326,7 +1340,7 @@ StructDef *Parser::LookupCreateStruct(const std::string &name, bool create_if_new, bool definition) { std::string qualified_name = current_namespace_->GetFullyQualifiedName(name); // See if it exists pre-declared by an unqualified use. - auto struct_def = structs_.Lookup(name); + auto struct_def = LookupStruct(name); if (struct_def && struct_def->predecl) { if (definition) { // Make sure it has the current namespace, and is registered under its @@ -1337,7 +1351,7 @@ StructDef *Parser::LookupCreateStruct(const std::string &name, return struct_def; } // See if it exists pre-declared by an qualified use. - struct_def = structs_.Lookup(qualified_name); + struct_def = LookupStruct(qualified_name); if (struct_def && struct_def->predecl) { if (definition) { // Make sure it has the current namespace. @@ -1349,7 +1363,7 @@ StructDef *Parser::LookupCreateStruct(const std::string &name, // Search thru parent namespaces. for (size_t components = current_namespace_->components.size(); components && !struct_def; components--) { - struct_def = structs_.Lookup( + struct_def = LookupStruct( current_namespace_->GetFullyQualifiedName(name, components - 1)); } } @@ -1363,12 +1377,13 @@ StructDef *Parser::LookupCreateStruct(const std::string &name, // Not a definition. // Rather than failing, we create a "pre declared" StructDef, due to // circular references, and check for errors at the end of parsing. - // It is defined in the root namespace, since we don't know what the + // It is defined in the current namespace, as the best guess what the // final namespace will be. - // TODO: maybe safer to use special namespace? structs_.Add(name, struct_def); struct_def->name = name; - struct_def->defined_namespace = empty_namespace_; + struct_def->defined_namespace = current_namespace_; + struct_def->original_location.reset(new std::string(file_being_parsed_ + + ":" + NumToString(line_))); } } return struct_def; @@ -1655,9 +1670,9 @@ CheckedError Parser::ParseService() { } bool Parser::SetRootType(const char *name) { - root_struct_def_ = structs_.Lookup(name); + root_struct_def_ = LookupStruct(name); if (!root_struct_def_) - root_struct_def_ = structs_.Lookup( + root_struct_def_ = LookupStruct( current_namespace_->GetFullyQualifiedName(name)); return root_struct_def_ != nullptr; } @@ -1735,6 +1750,7 @@ CheckedError Parser::ParseProtoDecl() { *ns = *current_namespace_; // But with current message name. ns->components.push_back(name); + ns->from_table++; parent_namespace = current_namespace_; current_namespace_ = UniqueNamespace(ns); } @@ -1797,9 +1813,8 @@ CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend, EXPECT(';'); } else if (IsIdent("reserved")) { // Skip these. NEXT(); - EXPECT(kTokenIntegerConstant); - while (Is(',')) { NEXT(); EXPECT(kTokenIntegerConstant); } - EXPECT(';'); + while (!Is(';')) { NEXT(); } // A variety of formats, just skip. + NEXT(); } else { std::vector<std::string> field_comment = doc_comment_; // Parse the qualifier. @@ -1837,6 +1852,13 @@ CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend, if (repeated) { type.element = type.base_type; type.base_type = BASE_TYPE_VECTOR; + if (type.element == BASE_TYPE_VECTOR) { + // We have a vector or vectors, which FlatBuffers doesn't support. + // For now make it a vector of string (since the source is likely + // "repeated bytes"). + // TODO(wvo): A better solution would be to wrap this in a table. + type.element = BASE_TYPE_STRING; + } } std::string name = attribute_; EXPECT(kTokenIdentifier); @@ -2088,11 +2110,63 @@ CheckedError Parser::ParseRoot(const char *source, const char **include_paths, ECHECK(DoParse(source, include_paths, source_filename, nullptr)); // Check that all types were defined. - for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { - if ((*it)->predecl) { - return Error("type referenced but not defined (check namespace): " + - (*it)->name); + for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ) { + auto &struct_def = **it; + if (struct_def.predecl) { + if (opts.proto_mode) { + // Protos allow enums to be used before declaration, so check if that + // is the case here. + EnumDef *enum_def = nullptr; + for (size_t components = struct_def.defined_namespace-> + components.size() + 1; + components && !enum_def; components--) { + auto qualified_name = struct_def.defined_namespace-> + GetFullyQualifiedName(struct_def.name, + components - 1); + enum_def = LookupEnum(qualified_name); + } + if (enum_def) { + // This is pretty slow, but a simple solution for now. + auto initial_count = struct_def.refcount; + for (auto struct_it = structs_.vec.begin(); + struct_it != structs_.vec.end(); + ++struct_it) { + auto &sd = **struct_it; + for (auto field_it = sd.fields.vec.begin(); + field_it != sd.fields.vec.end(); + ++field_it) { + auto &field = **field_it; + if (field.value.type.struct_def == &struct_def) { + field.value.type.struct_def = nullptr; + field.value.type.enum_def = enum_def; + auto &bt = field.value.type.base_type == BASE_TYPE_VECTOR + ? field.value.type.element + : field.value.type.base_type; + assert(bt == BASE_TYPE_STRUCT); + bt = enum_def->underlying_type.base_type; + struct_def.refcount--; + enum_def->refcount++; + } + } + } + if (struct_def.refcount) + return Error("internal: " + NumToString(struct_def.refcount) + "/" + + NumToString(initial_count) + + " use(s) of pre-declaration enum not accounted for: " + + enum_def->name); + structs_.dict.erase(structs_.dict.find(struct_def.name)); + it = structs_.vec.erase(it); + delete &struct_def; + continue; // Skip error. + } + } + auto err = "type referenced but not defined (check namespace): " + + struct_def.name; + if (struct_def.original_location) + err += ", originally at: " + *struct_def.original_location; + return Error(err); } + ++it; } // This check has to happen here and not earlier, because only now do we @@ -2433,7 +2507,7 @@ std::string Parser::ConformTo(const Parser &base) { auto &struct_def = **sit; auto qualified_name = struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name); - auto struct_def_base = base.structs_.Lookup(qualified_name); + auto struct_def_base = base.LookupStruct(qualified_name); if (!struct_def_base) continue; for (auto fit = struct_def.fields.vec.begin(); fit != struct_def.fields.vec.end(); ++fit) { diff --git a/tests/prototest/test.golden b/tests/prototest/test.golden index f8142498..389133d6 100644 --- a/tests/prototest/test.golden +++ b/tests/prototest/test.golden @@ -1,6 +1,6 @@ // Generated from test.proto -namespace _proto._test; +namespace proto.test; /// Enum doc comment. enum ProtoEnum : int { @@ -33,12 +33,12 @@ table ProtoMessage { /// lines l:string (required); m:[ubyte]; - n:_proto._test._ProtoMessage.OtherMessage; + n:proto.test.ProtoMessage_.OtherMessage; o:[string]; - z:_proto._test.ImportedMessage; + z:proto.test.ImportedMessage; } -namespace _proto._test._ProtoMessage; +namespace proto.test.ProtoMessage_; table OtherMessage { a:double; |