From e50696ad9e9622ef7aa9f16d56df5a4ae8aa8d12 Mon Sep 17 00:00:00 2001 From: Derek Bailey Date: Tue, 23 Aug 2022 21:06:12 -0700 Subject: [PATCH] Use schema include name for keep-prefix --- include/flatbuffers/idl.h | 22 ++++++++++++++++++++-- src/idl_gen_cpp.cpp | 39 +++++++++++++-------------------------- src/idl_parser.cpp | 24 +++++++++++++++--------- 3 files changed, 48 insertions(+), 37 deletions(-) diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 03de2a6926b..c27c1c154da 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -537,6 +537,24 @@ struct ServiceDef : public Definition { SymbolTable calls; }; +struct IncludedFile { + // The name of the schema file being included, as defined in the .fbs file. + // This includes the prefix (e.g., include "foo/bar/baz.fbs" would mean this + // value is "foo/bar/baz.fbs"). + std::string schema_name; + + // The filename of where the included file was found, after searching the + // relative paths plus any other paths included with `flatc -I ...`. Note, + // while this is sometimes the same as schema_name, it is not always, since it + // can be defined relative to where flatc was invoked. + std::string filename; +}; + +// Since IncludedFile is contained within a std::set, need to provide ordering. +inline bool operator<(const IncludedFile &a, const IncludedFile &b) { + return a.filename < b.filename; +} + // Container of options that may apply to any of the source/text generators. struct IDLOptions { // field case style options for C++ @@ -914,7 +932,7 @@ class Parser : public ParserState { // Get the set of included files that are directly referenced by the file // being parsed. This does not include files that are transitively included by // others includes. - std::vector GetIncludedFiles() const; + std::vector GetIncludedFiles() const; private: class ParseDepthGuard; @@ -1043,7 +1061,7 @@ class Parser : public ParserState { std::string file_extension_; std::map included_files_; - std::map> files_included_per_file_; + std::map> files_included_per_file_; std::vector native_included_files_; std::map known_attributes_; diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index dadd474ab41..db5a814ae85 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -233,37 +233,24 @@ class CppGenerator : public BaseGenerator { } // Get the directly included file of the file being parsed. - std::vector included_files(parser_.GetIncludedFiles()); + std::vector included_files(parser_.GetIncludedFiles()); // We are safe to sort them alphabetically, since there shouldn't be any // interdependence between them. std::stable_sort(included_files.begin(), included_files.end()); - // The absolute path of the file being parsed. - const std::string parsed_path = - flatbuffers::StripFileName(AbsolutePath(parser_.file_being_parsed_)); - - for (const std::string &included_file : included_files) { - // The base name of the file, without path or extensions. - std::string basename = - flatbuffers::StripPath(flatbuffers::StripExtension(included_file)); - - // If we are keeping the prefix - if (opts_.keep_prefix) { - // The absolute path of the included file. - const std::string included_path = - flatbuffers::StripFileName(AbsolutePath(included_file)); - - // The relative path of the parsed file to the included file. - const std::string relative_path = - RelativeToRootPath(parsed_path, included_path).substr(2); - - // Only consider cases where the included path is a subdirectory of the - // parsed path. - if (strncmp("..", relative_path.c_str(), 2) != 0) { - basename = relative_path + kPathSeparator + basename; - } - } + for (const IncludedFile &included_file : included_files) { + // Get the name of the included file as defined by the schema, and strip + // the .fbs extension. + const std::string name_without_ext = + flatbuffers::StripExtension(included_file.schema_name); + + // If we are told to keep the prefix of the included schema, leave it + // unchanged, otherwise strip the leading path off so just the "basename" + // of the include is retained. + const std::string basename = + opts_.keep_prefix ? name_without_ext + : flatbuffers::StripPath(name_without_ext); code_ += "#include \"" + GeneratedFileName(opts_.include_prefix, basename, opts_) + "\""; diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 4360948f37d..247152fa89a 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -2545,7 +2545,7 @@ CheckedError Parser::CheckClash(std::vector &fields, return NoError(); } -std::vector Parser::GetIncludedFiles() const { +std::vector Parser::GetIncludedFiles() const { const auto it = files_included_per_file_.find(file_being_parsed_); if (it == files_included_per_file_.end()) { return {}; } @@ -3435,7 +3435,7 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths, if (included_files_.find(source_hash) == included_files_.end()) { included_files_[source_hash] = include_filename ? include_filename : ""; - files_included_per_file_[source_filename] = std::set(); + files_included_per_file_[source_filename] = std::set(); } else { return NoError(); } @@ -3483,8 +3483,12 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths, } if (filepath.empty()) return Error("unable to locate include file: " + name); - if (source_filename) - files_included_per_file_[source_filename].insert(filepath); + if (source_filename) { + IncludedFile included_file; + included_file.filename = filepath; + included_file.schema_name = name; + files_included_per_file_[source_filename].insert(included_file); + } std::string contents; bool file_loaded = LoadFile(filepath.c_str(), true, &contents); @@ -3621,11 +3625,11 @@ std::set Parser::GetIncludedFilesRecursive( // Workaround the lack of const accessor in C++98 maps. auto &new_files = - (*const_cast> *>( + (*const_cast> *>( &files_included_per_file_))[current]; for (auto it = new_files.begin(); it != new_files.end(); ++it) { - if (included_files.find(*it) == included_files.end()) - to_process.push_back(*it); + if (included_files.find(it->filename) == included_files.end()) + to_process.push_back(it->filename); } } @@ -3675,7 +3679,7 @@ void Parser::Serialize() { RelativeToRootPath(opts.project_root, f->first)); for (auto i = f->second.begin(); i != f->second.end(); i++) { included_files.push_back(builder_.CreateSharedString( - RelativeToRootPath(opts.project_root, *i))); + RelativeToRootPath(opts.project_root, i->filename))); } const auto included_files__ = builder_.CreateVector(included_files); included_files.clear(); @@ -4107,7 +4111,9 @@ bool Parser::Deserialize(const reflection::Schema *schema) { ++s) { for (auto f = s->included_filenames()->begin(); f != s->included_filenames()->end(); ++f) { - files_included_per_file_[s->filename()->str()].insert(f->str()); + IncludedFile included_file; + included_file.filename = f->str(); + files_included_per_file_[s->filename()->str()].insert(included_file); } }