Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use schema include name for keep-prefix #7469

Merged
merged 1 commit into from Aug 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 20 additions & 2 deletions include/flatbuffers/idl.h
Expand Up @@ -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++
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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_;
Expand Down
39 changes: 13 additions & 26 deletions src/idl_gen_cpp.cpp
Expand Up @@ -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 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_) + "\"";
Expand Down
24 changes: 15 additions & 9 deletions src/idl_parser.cpp
Expand Up @@ -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 {}; }

Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
}
}

Expand Down