Fixup help contents source_file

Stop empty source files `""` from being exported to json.
Move source path fixing to a separate function.
`ContentListing::to_json` now takes the source root, recursively calling the source path fixup function on all source paths in the content listing.
This commit is contained in:
Krystine Sherwin
2026-07-09 16:05:15 +12:00
parent 0e763f320b
commit 53d1e7615b
3 changed files with 46 additions and 21 deletions
+34 -5
View File
@@ -21,16 +21,45 @@
USING_YOSYS_NAMESPACE USING_YOSYS_NAMESPACE
Json ContentListing::to_json() const { std::filesystem::path Yosys::fixup_source_path (const char* source_file,
const std::filesystem::path &source_root, bool* skip_source_group)
{
std::filesystem::path source_path(source_file);
if (source_path.is_absolute()) {
// using proximate instead of relative means that we
// still get the source path if they aren't relative
auto proximate_path = std::filesystem::proximate(source_path, source_root);
if (proximate_path == proximate_path.lexically_normal()) {
// we're only interested if it's a subpath of our root dir
// if the normal form differs, then the proximate path includes ".."
return proximate_path;
} else if (skip_source_group != nullptr) {
// don't try to group external paths
*skip_source_group = true;
}
}
return source_path;
}
Json ContentListing::to_json(const std::filesystem::path &source_root) const {
Json::object object; Json::object object;
object["type"] = type; object["type"] = type;
if (body.length()) object["body"] = body; if (body.length())
if (strcmp(source_file, "unknown") != 0) object["source_file"] = source_file; object["body"] = body;
if (source_line != 0) object["source_line"] = source_line;
if (has_source())
object["source_file"] = fixup_source_path(source_file, source_root).string();
if (source_line != 0)
object["source_line"] = source_line;
object["options"] = Json(options); object["options"] = Json(options);
Json::array content_array; Json::array content_array;
for (auto child : _content) content_array.push_back(child.to_json()); for (auto child : _content)
content_array.push_back(child.to_json(source_root));
object["content"] = content_array; object["content"] = content_array;
return object; return object;
} }
+7 -1
View File
@@ -22,9 +22,14 @@
#include "kernel/yosys_common.h" #include "kernel/yosys_common.h"
#include "kernel/json.h" #include "kernel/json.h"
#include <filesystem>
#include <string_view>
YOSYS_NAMESPACE_BEGIN YOSYS_NAMESPACE_BEGIN
std::filesystem::path fixup_source_path (const char* source_file,
const std::filesystem::path &source_root, bool* skip_source_group = nullptr);
class ContentListing { class ContentListing {
vector<ContentListing> _content; vector<ContentListing> _content;
public: public:
@@ -49,6 +54,7 @@ public:
_content.push_back({type, body, location}); _content.push_back({type, body, location});
} }
bool has_source() const { return strlen(source_file) && strcmp(source_file, "unknown") != 0; }
bool has_content() const { return _content.size() != 0; } bool has_content() const { return _content.size() != 0; }
vector<ContentListing>::const_iterator begin() const { return _content.cbegin(); } vector<ContentListing>::const_iterator begin() const { return _content.cbegin(); }
@@ -90,7 +96,7 @@ public:
const source_location location = source_location::current() const source_location location = source_location::current()
); );
Json to_json() const; Json to_json(const std::filesystem::path &source_root) const;
}; };
class PrettyHelp class PrettyHelp
+5 -15
View File
@@ -921,20 +921,10 @@ struct HelpPass : public Pass {
string source_file = pass->location.file_name(); string source_file = pass->location.file_name();
bool has_source = source_file.compare("unknown") != 0; bool has_source = source_file.compare("unknown") != 0;
std::filesystem::path source_path; std::filesystem::path source_path;
auto no_source_group = false; auto skip_source_group = false;
if (has_source) { if (has_source) {
source_path = std::filesystem::path(pass->location.file_name()); source_path = fixup_source_path(pass->location.file_name(), source_root, &skip_source_group);
if (source_path.is_absolute()) {
// using proximate instead of relative means that we
// still get the source path if they aren't relative
auto proximate_path = std::filesystem::proximate(source_path, source_root);
if (proximate_path == std::filesystem::weakly_canonical(proximate_path))
// we're only interested if it's a subpath of our root dir
source_path = proximate_path;
else
// don't try to group external paths
no_source_group = true;
}
source_file = source_path.string(); source_file = source_path.string();
} }
@@ -947,7 +937,7 @@ struct HelpPass : public Pass {
else if (source_file.find("frontends/") == 0 || (!has_source && name.find("write_") == 0)) else if (source_file.find("frontends/") == 0 || (!has_source && name.find("write_") == 0))
cmd_help.group = "frontends"; cmd_help.group = "frontends";
else if (has_source) { else if (has_source) {
if (source_path.has_parent_path() && !no_source_group) if (source_path.has_parent_path() && !skip_source_group)
cmd_help.group = source_path.parent_path().string(); cmd_help.group = source_path.parent_path().string();
} }
// implicit !has_source // implicit !has_source
@@ -973,7 +963,7 @@ struct HelpPass : public Pass {
json.entry("title", title); json.entry("title", title);
json.name("content"); json.begin_array(); json.name("content"); json.begin_array();
for (auto &content : cmd_help) for (auto &content : cmd_help)
json.value(content.to_json()); json.value(content.to_json(source_root));
json.end_array(); json.end_array();
json.entry("group", cmd_help.group); json.entry("group", cmd_help.group);
json.entry("source_file", source_file); json.entry("source_file", source_file);