mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-03 20:31:23 +00:00
Add the file a symbol is declared in to Reflection (#6613)
* Add the file a symbol is declared in to Reflection If we move a code-generator to depend on Reflection, it may need to know which file something was declared in to properly name generated files. * Doc comments in reflection, and more precise tests * Add --project-root flag to flatc, normalize declaraion_file to this root * fix --project-root stuff * posixpath * fix scripts * format * rename --project-root to --bfbs-filenames Also, make it optional, rather than defaulting to `./`, if its not specified, then don't serialize the filenames. * bfbs generation * fix some tests * uncomment a thing * add to project root directory conditionally * fix * git clang format * Added help description and removed != nullptr * " * Remove accidental change to docs * Remove accidental change to docs * Pool strings Co-authored-by: Casper Neo <cneo@google.com>
This commit is contained in:
@@ -158,6 +158,10 @@ CheckedError Parser::RecurseError() {
|
||||
" reached");
|
||||
}
|
||||
|
||||
const std::string &Parser::GetPooledString(const std::string &s) const {
|
||||
return *(string_cache_.insert(s).first);
|
||||
}
|
||||
|
||||
class Parser::ParseDepthGuard {
|
||||
public:
|
||||
explicit ParseDepthGuard(Parser *parser_not_null)
|
||||
@@ -2281,13 +2285,18 @@ struct EnumValBuilder {
|
||||
bool user_value;
|
||||
};
|
||||
|
||||
CheckedError Parser::ParseEnum(const bool is_union, EnumDef **dest) {
|
||||
CheckedError Parser::ParseEnum(const bool is_union, EnumDef **dest,
|
||||
const char *filename) {
|
||||
std::vector<std::string> enum_comment = doc_comment_;
|
||||
NEXT();
|
||||
std::string enum_name = attribute_;
|
||||
EXPECT(kTokenIdentifier);
|
||||
EnumDef *enum_def;
|
||||
ECHECK(StartEnum(enum_name, is_union, &enum_def));
|
||||
if (filename != nullptr && !opts.project_root.empty()) {
|
||||
enum_def->declaration_file =
|
||||
&GetPooledString(RelativeToRootPath(opts.project_root, filename));
|
||||
}
|
||||
enum_def->doc_comment = enum_comment;
|
||||
if (!is_union && !opts.proto_mode) {
|
||||
// Give specialized error message, since this type spec used to
|
||||
@@ -2516,7 +2525,7 @@ static bool compareFieldDefs(const FieldDef *a, const FieldDef *b) {
|
||||
return a_id < b_id;
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseDecl() {
|
||||
CheckedError Parser::ParseDecl(const char *filename) {
|
||||
std::vector<std::string> dc = doc_comment_;
|
||||
bool fixed = IsIdent("struct");
|
||||
if (!fixed && !IsIdent("table")) return Error("declaration expected");
|
||||
@@ -2527,6 +2536,10 @@ CheckedError Parser::ParseDecl() {
|
||||
ECHECK(StartStruct(name, &struct_def));
|
||||
struct_def->doc_comment = dc;
|
||||
struct_def->fixed = fixed;
|
||||
if (filename && !opts.project_root.empty()) {
|
||||
struct_def->declaration_file =
|
||||
&GetPooledString(RelativeToRootPath(opts.project_root, filename));
|
||||
}
|
||||
ECHECK(ParseMetaData(&struct_def->attributes));
|
||||
struct_def->sortbysize =
|
||||
struct_def->attributes.Lookup("original_order") == nullptr && !fixed;
|
||||
@@ -2606,7 +2619,7 @@ CheckedError Parser::ParseDecl() {
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseService() {
|
||||
CheckedError Parser::ParseService(const char *filename) {
|
||||
std::vector<std::string> service_comment = doc_comment_;
|
||||
NEXT();
|
||||
auto service_name = attribute_;
|
||||
@@ -2616,6 +2629,10 @@ CheckedError Parser::ParseService() {
|
||||
service_def.file = file_being_parsed_;
|
||||
service_def.doc_comment = service_comment;
|
||||
service_def.defined_namespace = current_namespace_;
|
||||
if (filename != nullptr && !opts.project_root.empty()) {
|
||||
service_def.declaration_file =
|
||||
&GetPooledString(RelativeToRootPath(opts.project_root, filename));
|
||||
}
|
||||
if (services_.Add(current_namespace_->GetFullyQualifiedName(service_name),
|
||||
&service_def))
|
||||
return Error("service already exists: " + service_name);
|
||||
@@ -2731,7 +2748,7 @@ CheckedError Parser::ParseProtoDecl() {
|
||||
} else if (IsIdent("enum")) {
|
||||
// These are almost the same, just with different terminator:
|
||||
EnumDef *enum_def;
|
||||
ECHECK(ParseEnum(false, &enum_def));
|
||||
ECHECK(ParseEnum(false, &enum_def, nullptr));
|
||||
if (Is(';')) NEXT();
|
||||
// Temp: remove any duplicates, as .fbs files can't handle them.
|
||||
enum_def->RemoveDuplicates();
|
||||
@@ -3371,9 +3388,9 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
||||
} else if (token_ == '{') {
|
||||
return NoError();
|
||||
} else if (IsIdent("enum")) {
|
||||
ECHECK(ParseEnum(false, nullptr));
|
||||
ECHECK(ParseEnum(false, nullptr, source_filename));
|
||||
} else if (IsIdent("union")) {
|
||||
ECHECK(ParseEnum(true, nullptr));
|
||||
ECHECK(ParseEnum(true, nullptr, source_filename));
|
||||
} else if (IsIdent("root_type")) {
|
||||
NEXT();
|
||||
auto root_type = attribute_;
|
||||
@@ -3412,9 +3429,9 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
||||
EXPECT(';');
|
||||
known_attributes_[name] = false;
|
||||
} else if (IsIdent("rpc_service")) {
|
||||
ECHECK(ParseService());
|
||||
ECHECK(ParseService(source_filename));
|
||||
} else {
|
||||
ECHECK(ParseDecl());
|
||||
ECHECK(ParseDecl(source_filename));
|
||||
}
|
||||
}
|
||||
return NoError();
|
||||
@@ -3491,32 +3508,44 @@ void Parser::Serialize() {
|
||||
AssignIndices(structs_.vec);
|
||||
AssignIndices(enums_.vec);
|
||||
std::vector<Offset<reflection::Object>> object_offsets;
|
||||
std::set<std::string> files;
|
||||
for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) {
|
||||
auto offset = (*it)->Serialize(&builder_, *this);
|
||||
object_offsets.push_back(offset);
|
||||
(*it)->serialized_location = offset.o;
|
||||
const std::string *file = (*it)->declaration_file;
|
||||
if (file) files.insert(*file);
|
||||
}
|
||||
std::vector<Offset<reflection::Enum>> enum_offsets;
|
||||
for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) {
|
||||
auto offset = (*it)->Serialize(&builder_, *this);
|
||||
enum_offsets.push_back(offset);
|
||||
(*it)->serialized_location = offset.o;
|
||||
const std::string *file = (*it)->declaration_file;
|
||||
if (file) files.insert(*file);
|
||||
}
|
||||
std::vector<Offset<reflection::Service>> service_offsets;
|
||||
for (auto it = services_.vec.begin(); it != services_.vec.end(); ++it) {
|
||||
auto offset = (*it)->Serialize(&builder_, *this);
|
||||
service_offsets.push_back(offset);
|
||||
(*it)->serialized_location = offset.o;
|
||||
const std::string *file = (*it)->declaration_file;
|
||||
if (file) files.insert(*file);
|
||||
}
|
||||
auto objs__ = builder_.CreateVectorOfSortedTables(&object_offsets);
|
||||
auto enum__ = builder_.CreateVectorOfSortedTables(&enum_offsets);
|
||||
auto fiid__ = builder_.CreateString(file_identifier_);
|
||||
auto fext__ = builder_.CreateString(file_extension_);
|
||||
auto serv__ = builder_.CreateVectorOfSortedTables(&service_offsets);
|
||||
auto schema_offset = reflection::CreateSchema(
|
||||
// TODO(caspern): CreateVectorOfSharedStrings
|
||||
std::vector<Offset<flatbuffers::String>> file_offsets;
|
||||
for (auto it = files.begin(); it != files.end(); it++) {
|
||||
file_offsets.push_back(builder_.CreateSharedString(*it));
|
||||
}
|
||||
|
||||
const auto objs__ = builder_.CreateVectorOfSortedTables(&object_offsets);
|
||||
const auto enum__ = builder_.CreateVectorOfSortedTables(&enum_offsets);
|
||||
const auto fiid__ = builder_.CreateString(file_identifier_);
|
||||
const auto fext__ = builder_.CreateString(file_extension_);
|
||||
const auto serv__ = builder_.CreateVectorOfSortedTables(&service_offsets);
|
||||
const auto files__ = builder_.CreateVector(file_offsets);
|
||||
const auto schema_offset = reflection::CreateSchema(
|
||||
builder_, objs__, enum__, fiid__, fext__,
|
||||
(root_struct_def_ ? root_struct_def_->serialized_location : 0), serv__,
|
||||
static_cast<reflection::AdvancedFeatures>(advanced_features_));
|
||||
static_cast<reflection::AdvancedFeatures>(advanced_features_), files__);
|
||||
if (opts.size_prefixed) {
|
||||
builder_.FinishSizePrefixed(schema_offset, reflection::SchemaIdentifier());
|
||||
} else {
|
||||
@@ -3557,16 +3586,18 @@ Offset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder,
|
||||
field_offsets.push_back((*it)->Serialize(
|
||||
builder, static_cast<uint16_t>(it - fields.vec.begin()), parser));
|
||||
}
|
||||
auto qualified_name = defined_namespace->GetFullyQualifiedName(name);
|
||||
auto name__ = builder->CreateString(qualified_name);
|
||||
auto flds__ = builder->CreateVectorOfSortedTables(&field_offsets);
|
||||
auto attr__ = SerializeAttributes(builder, parser);
|
||||
auto docs__ = parser.opts.binary_schema_comments
|
||||
? builder->CreateVectorOfStrings(doc_comment)
|
||||
: 0;
|
||||
return reflection::CreateObject(*builder, name__, flds__, fixed,
|
||||
static_cast<int>(minalign),
|
||||
static_cast<int>(bytesize), attr__, docs__);
|
||||
const auto qualified_name = defined_namespace->GetFullyQualifiedName(name);
|
||||
const auto name__ = builder->CreateString(qualified_name);
|
||||
const auto flds__ = builder->CreateVectorOfSortedTables(&field_offsets);
|
||||
const auto attr__ = SerializeAttributes(builder, parser);
|
||||
const auto docs__ = parser.opts.binary_schema_comments
|
||||
? builder->CreateVectorOfStrings(doc_comment)
|
||||
: 0;
|
||||
std::string decl_file_in_project = declaration_file ? *declaration_file : "";
|
||||
const auto file__ = builder->CreateSharedString(decl_file_in_project);
|
||||
return reflection::CreateObject(
|
||||
*builder, name__, flds__, fixed, static_cast<int>(minalign),
|
||||
static_cast<int>(bytesize), attr__, docs__, file__);
|
||||
}
|
||||
|
||||
bool StructDef::Deserialize(Parser &parser, const reflection::Object *object) {
|
||||
@@ -3685,14 +3716,17 @@ Offset<reflection::Service> ServiceDef::Serialize(FlatBufferBuilder *builder,
|
||||
for (auto it = calls.vec.begin(); it != calls.vec.end(); ++it) {
|
||||
servicecall_offsets.push_back((*it)->Serialize(builder, parser));
|
||||
}
|
||||
auto qualified_name = defined_namespace->GetFullyQualifiedName(name);
|
||||
auto name__ = builder->CreateString(qualified_name);
|
||||
auto call__ = builder->CreateVector(servicecall_offsets);
|
||||
auto attr__ = SerializeAttributes(builder, parser);
|
||||
auto docs__ = parser.opts.binary_schema_comments
|
||||
? builder->CreateVectorOfStrings(doc_comment)
|
||||
: 0;
|
||||
return reflection::CreateService(*builder, name__, call__, attr__, docs__);
|
||||
const auto qualified_name = defined_namespace->GetFullyQualifiedName(name);
|
||||
const auto name__ = builder->CreateString(qualified_name);
|
||||
const auto call__ = builder->CreateVector(servicecall_offsets);
|
||||
const auto attr__ = SerializeAttributes(builder, parser);
|
||||
const auto docs__ = parser.opts.binary_schema_comments
|
||||
? builder->CreateVectorOfStrings(doc_comment)
|
||||
: 0;
|
||||
std::string decl_file_in_project = declaration_file ? *declaration_file : "";
|
||||
const auto file__ = builder->CreateSharedString(decl_file_in_project);
|
||||
return reflection::CreateService(*builder, name__, call__, attr__, docs__,
|
||||
file__);
|
||||
}
|
||||
|
||||
bool ServiceDef::Deserialize(Parser &parser,
|
||||
@@ -3719,16 +3753,18 @@ Offset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder,
|
||||
for (auto it = vals.vec.begin(); it != vals.vec.end(); ++it) {
|
||||
enumval_offsets.push_back((*it)->Serialize(builder, parser));
|
||||
}
|
||||
auto qualified_name = defined_namespace->GetFullyQualifiedName(name);
|
||||
auto name__ = builder->CreateString(qualified_name);
|
||||
auto vals__ = builder->CreateVector(enumval_offsets);
|
||||
auto type__ = underlying_type.Serialize(builder);
|
||||
auto attr__ = SerializeAttributes(builder, parser);
|
||||
auto docs__ = parser.opts.binary_schema_comments
|
||||
? builder->CreateVectorOfStrings(doc_comment)
|
||||
: 0;
|
||||
const auto qualified_name = defined_namespace->GetFullyQualifiedName(name);
|
||||
const auto name__ = builder->CreateString(qualified_name);
|
||||
const auto vals__ = builder->CreateVector(enumval_offsets);
|
||||
const auto type__ = underlying_type.Serialize(builder);
|
||||
const auto attr__ = SerializeAttributes(builder, parser);
|
||||
const auto docs__ = parser.opts.binary_schema_comments
|
||||
? builder->CreateVectorOfStrings(doc_comment)
|
||||
: 0;
|
||||
std::string decl_file_in_project = declaration_file ? *declaration_file : "";
|
||||
const auto file__ = builder->CreateSharedString(decl_file_in_project);
|
||||
return reflection::CreateEnum(*builder, name__, vals__, is_union, type__,
|
||||
attr__, docs__);
|
||||
attr__, docs__, file__);
|
||||
}
|
||||
|
||||
bool EnumDef::Deserialize(Parser &parser, const reflection::Enum *_enum) {
|
||||
|
||||
Reference in New Issue
Block a user