Use schema include name for keep-prefix (#7469)

This commit is contained in:
Derek Bailey 2022-08-23 21:29:17 -07:00 committed by GitHub
parent 8367664f15
commit fef2ffc4d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 36 deletions

View File

@ -537,6 +537,24 @@ struct ServiceDef : public Definition {
SymbolTable<RPCCall> 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<std::string> GetIncludedFiles() const;
std::vector<IncludedFile> GetIncludedFiles() const;
private:
class ParseDepthGuard;
@ -1043,7 +1061,7 @@ class Parser : public ParserState {
std::string file_extension_;
std::map<uint64_t, std::string> included_files_;
std::map<std::string, std::set<std::string>> files_included_per_file_;
std::map<std::string, std::set<IncludedFile>> files_included_per_file_;
std::vector<std::string> native_included_files_;
std::map<std::string, bool> known_attributes_;

View File

@ -233,37 +233,24 @@ class CppGenerator : public BaseGenerator {
}
// Get the directly included file of the file being parsed.
std::vector<std::string> included_files(parser_.GetIncludedFiles());
std::vector<IncludedFile> 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 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);
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;
}
}
// 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_) + "\"";

View File

@ -2545,7 +2545,7 @@ CheckedError Parser::CheckClash(std::vector<FieldDef *> &fields,
return NoError();
}
std::vector<std::string> Parser::GetIncludedFiles() const {
std::vector<IncludedFile> 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<std::string>();
files_included_per_file_[source_filename] = std::set<IncludedFile>();
} 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<std::string> Parser::GetIncludedFilesRecursive(
// Workaround the lack of const accessor in C++98 maps.
auto &new_files =
(*const_cast<std::map<std::string, std::set<std::string>> *>(
(*const_cast<std::map<std::string, std::set<IncludedFile>> *>(
&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);
}
}