Skip to content

Commit

Permalink
Adding all hyde values under a top-level hyde YAML key (#80)
Browse files Browse the repository at this point in the history
* adding all `hyde` values under a top-level `hyde` YAML key

* adding `fixup-hyde-subfield` flag

* fixes to the merge logic
  • Loading branch information
fosterbrereton committed Jun 21, 2023
1 parent 471b03f commit c05cd67
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 40 deletions.
69 changes: 56 additions & 13 deletions emitters/yaml_base_emitter.cpp
Expand Up @@ -171,6 +171,11 @@ YAML::Node json_to_yaml_ordered(hyde::json j) {
move_key("methods");
move_key("overloads");

if (j.count("hyde")) {
result["hyde"] = json_to_yaml_ordered(j["hyde"]);
j.erase("hyde");
}

// copy over the remainder of the keys.
for (auto it = j.begin(); it != j.end(); ++it) {
result[it.key()] = json_to_yaml(it.value());
Expand All @@ -179,6 +184,31 @@ YAML::Node json_to_yaml_ordered(hyde::json j) {
return result;
}

/**************************************************************************************************/
// See Issue #75 and PR #80. Take the relevant hyde fields and move them under a top-level
// `hyde` subfield. Only do this when we're asked to, in case this has already been done and those
// high-level fields are used by something else. When we do this fixup, we don't know which fields
// hyde actually uses, so this will move _all_ fields that are not `layout` and `title`.
hyde::json fixup_hyde_subfield(hyde::json&& j) {
hyde::json result;

if (j.count("layout")) {
result["layout"] = std::move(j.at("layout"));
j.erase("layout");
}

if (j.count("title")) {
result["title"] = std::move(j.at("title"));
j.erase("title");
}

result["hyde"] = std::move(j);

std::string result_str = result.dump(4);

return result;
}

/**************************************************************************************************/

static const std::string front_matter_delimiter_k("---\n");
Expand All @@ -202,9 +232,10 @@ json yaml_base_emitter::base_emitter_node(std::string layout, std::string title,

node["layout"] = std::move(layout);
node["title"] = std::move(title);
node["owner"] = tag_value_missing_k;
node["tags"].emplace_back(std::move(tag));
node["brief"] = tag_value_missing_k;

node["hyde"]["owner"] = tag_value_missing_k;
node["hyde"]["tags"].emplace_back(std::move(tag));
node["hyde"]["brief"] = tag_value_missing_k;

return node;
}
Expand All @@ -215,7 +246,7 @@ void yaml_base_emitter::insert_typedefs(const json& j, json& node) {
if (j.count("typedefs")) {
for (const auto& type_def : j["typedefs"]) {
const std::string& key = type_def["name"];
auto& type_node = node["typedefs"][key];
auto& type_node = node["hyde"]["typedefs"][key];
type_node["definition"] = static_cast<const std::string&>(type_def["type"]);
type_node["description"] = tag_value_missing_k;
maybe_annotate(type_def, type_node);
Expand All @@ -225,7 +256,7 @@ void yaml_base_emitter::insert_typedefs(const json& j, json& node) {
if (j.count("typealiases")) {
for (const auto& type_def : j["typealiases"]) {
const std::string& key = type_def["name"];
auto& type_node = node["typedefs"][key];
auto& type_node = node["hyde"]["typedefs"][key];
type_node["definition"] = static_cast<const std::string&>(type_def["type"]);
type_node["description"] = tag_value_missing_k;
maybe_annotate(type_def, type_node);
Expand Down Expand Up @@ -890,11 +921,18 @@ std::pair<bool, json> yaml_base_emitter::merge(const std::string& filepath,
} else {
failure |= check_scalar(filepath, have, expected, "", merged, "title");
}
failure |= check_editable_scalar(filepath, have, expected, "", merged, "owner");
failure |= check_editable_scalar(filepath, have, expected, "", merged, "brief");
failure |= check_scalar_array(filepath, have, expected, "", merged, "tags");

failure |= do_merge(filepath, have, expected, merged);
{
auto& expected_hyde = expected.at("hyde");
auto& have_hyde = have.at("hyde");
auto& merged_hyde = merged["hyde"];

failure |= check_editable_scalar(filepath, have_hyde, expected_hyde, "", merged_hyde, "owner");
failure |= check_editable_scalar(filepath, have_hyde, expected_hyde, "", merged_hyde, "brief");
failure |= check_scalar_array(filepath, have_hyde, expected_hyde, "", merged_hyde, "tags");

failure |= do_merge(filepath, have_hyde, expected_hyde, merged_hyde);
}

return std::make_pair(failure, std::move(merged));
}
Expand Down Expand Up @@ -1071,6 +1109,11 @@ bool yaml_base_emitter::reconcile(json expected,
have_contents.erase(front_matter_pos, front_matter_end + front_matter_delimiter_k.size());
std::string remainder = std::move(have_contents);
json have = yaml_to_json(load_yaml(path));

if (_mode == yaml_mode::update && _options._fixup_hyde_subfield) {
have = fixup_hyde_subfield(std::move(have));
}

json merged;

std::tie(failure, merged) = merge(relative_path, have, expected);
Expand Down Expand Up @@ -1144,14 +1187,14 @@ void yaml_base_emitter::maybe_annotate(const json& j, json& node) {
const std::string& access = j["access"];

if (access != "public") {
node["annotation"].push_back(access);
node["hyde"]["annotation"].push_back(access);
}
}

if (j.count("default") && j["default"])
node["annotation"].push_back("default");
node["hyde"]["annotation"].push_back("default");
else if (j.count("delete") && j["delete"])
node["annotation"].push_back("delete");
node["hyde"]["annotation"].push_back("delete");

if (j.count("deprecated") && j["deprecated"]) {
std::string deprecated("deprecated");
Expand All @@ -1163,7 +1206,7 @@ void yaml_base_emitter::maybe_annotate(const json& j, json& node) {
.append(")");
}
}
node["annotation"].push_back(deprecated);
node["hyde"]["annotation"].push_back(deprecated);
}
}

Expand Down
10 changes: 3 additions & 7 deletions emitters/yaml_base_emitter_fwd.hpp
Expand Up @@ -55,13 +55,9 @@ static inline bool is_tag(const std::string& s) {
/**************************************************************************************************/

struct emit_options {
attribute_category _tested_by;
bool _ignore_extraneous_files;

emit_options() :
_tested_by(attribute_category::disabled),
_ignore_extraneous_files(false)
{}
attribute_category _tested_by{attribute_category::disabled};
bool _ignore_extraneous_files{false};
bool _fixup_hyde_subfield{false};
};

/**************************************************************************************************/
Expand Down
12 changes: 6 additions & 6 deletions emitters/yaml_class_emitter.cpp
Expand Up @@ -66,24 +66,24 @@ bool yaml_class_emitter::do_merge(const std::string& filepath,

bool yaml_class_emitter::emit(const json& j, json& out_emitted) {
json node = base_emitter_node("class", j["name"], "class");
node["defined_in_file"] = defined_in_file(j["defined_in_file"], _src_root);
node["hyde"]["defined_in_file"] = defined_in_file(j["defined_in_file"], _src_root);
maybe_annotate(j, node);

std::string declaration = format_template_parameters(j, true) + '\n' +
static_cast<const std::string&>(j["kind"]) + " " +
static_cast<const std::string&>(j["qualified_name"]) + ";";
node["declaration"] = std::move(declaration);
node["hyde"]["declaration"] = std::move(declaration);

for (const auto& ns : j["namespaces"])
node["namespace"].push_back(static_cast<const std::string&>(ns));
node["hyde"]["namespace"].push_back(static_cast<const std::string&>(ns));

if (j.count("ctor")) node["ctor"] = static_cast<const std::string&>(j["ctor"]);
if (j.count("dtor")) node["dtor"] = static_cast<const std::string&>(j["dtor"]);
if (j.count("ctor")) node["hyde"]["ctor"] = static_cast<const std::string&>(j["ctor"]);
if (j.count("dtor")) node["hyde"]["dtor"] = static_cast<const std::string&>(j["dtor"]);

if (j.count("fields")) {
for (const auto& field : j["fields"]) {
const std::string& key = field["name"];
auto& field_node = node["fields"][key];
auto& field_node = node["hyde"]["fields"][key];
field_node["type"] = static_cast<const std::string&>(field["type"]);
field_node["description"] = tag_value_missing_k;
maybe_annotate(field, field_node);
Expand Down
6 changes: 3 additions & 3 deletions emitters/yaml_enum_emitter.cpp
Expand Up @@ -56,13 +56,13 @@ bool yaml_enum_emitter::emit(const json& j, json& out_emitted) {
if (j["values"].empty()) return true;

json node = base_emitter_node("enumeration", j["name"], "enumeration");
node["defined_in_file"] = defined_in_file(j["defined_in_file"], _src_root);
node["hyde"]["defined_in_file"] = defined_in_file(j["defined_in_file"], _src_root);
maybe_annotate(j, node);

std::string filename;
for (const auto& ns : j["namespaces"]) {
const std::string& namespace_str = ns;
node["namespace"].push_back(namespace_str);
node["hyde"]["namespace"].push_back(namespace_str);
filename += namespace_str + "::";
}
filename = filename_filter(std::move(filename) + name) + ".md";
Expand All @@ -71,7 +71,7 @@ bool yaml_enum_emitter::emit(const json& j, json& out_emitted) {
json cur_value;
cur_value["name"] = value["name"];
cur_value["description"] = tag_value_missing_k;
node["values"].push_back(std::move(cur_value));
node["hyde"]["values"].push_back(std::move(cur_value));
}

return reconcile(std::move(node), _dst_root, dst_path(j) / filename, out_emitted);
Expand Down
10 changes: 5 additions & 5 deletions emitters/yaml_function_emitter.cpp
Expand Up @@ -122,17 +122,17 @@ bool yaml_function_emitter::emit(const json& jsn, json& out_emitted) {

json node = base_emitter_node(_as_methods ? "method" : "function", name,
_as_methods ? "method" : "function");
node["defined_in_file"] = defined_path;
node["hyde"]["defined_in_file"] = defined_path;

if (!_as_methods && jsn.size() > 0) {
// All overloads will have the same namespace
for (const auto& ns : jsn.front()["namespaces"])
node["namespace"].push_back(static_cast<const std::string&>(ns));
node["hyde"]["namespace"].push_back(static_cast<const std::string&>(ns));
}

node["overloads"] = std::move(overloads);
if (is_ctor) node["is_ctor"] = true;
if (is_dtor) node["is_dtor"] = true;
node["hyde"]["overloads"] = std::move(overloads);
if (is_ctor) node["hyde"]["is_ctor"] = true;
if (is_dtor) node["hyde"]["is_dtor"] = true;

return reconcile(std::move(node), _dst_root, dst / (filename + ".md"), out_emitted);
}
Expand Down
8 changes: 4 additions & 4 deletions emitters/yaml_library_emitter.cpp
Expand Up @@ -39,10 +39,10 @@ bool yaml_library_emitter::do_merge(const std::string& filepath,

bool yaml_library_emitter::emit(const json&, json& out_emitted) {
json node = base_emitter_node("library", tag_value_missing_k, "library");
node["library-type"] = "library";
node["icon"] = tag_value_missing_k;
node["tab"] = tag_value_missing_k;
node["short_title"] = tag_value_optional_k;
node["hyde"]["library-type"] = "library";
node["hyde"]["icon"] = tag_value_missing_k;
node["hyde"]["tab"] = tag_value_missing_k;
node["hyde"]["short_title"] = tag_value_optional_k;

return reconcile(std::move(node), _dst_root, _dst_root / index_filename_k, out_emitted);
}
Expand Down
2 changes: 1 addition & 1 deletion emitters/yaml_sourcefile_emitter.cpp
Expand Up @@ -38,7 +38,7 @@ bool yaml_sourcefile_emitter::do_merge(const std::string& filepath,
bool yaml_sourcefile_emitter::emit(const json& j, json& out_emitted) {
const auto sub_path = subcomponent(static_cast<const std::string&>(j["paths"]["src_path"]), _src_root);
json node = base_emitter_node("library", sub_path.string(), "sourcefile");
node["library-type"] = "sourcefile";
node["hyde"]["library-type"] = "sourcefile";

insert_typedefs(j, node);

Expand Down
9 changes: 8 additions & 1 deletion sources/main.cpp
Expand Up @@ -127,6 +127,12 @@ static cl::opt<bool> EmitJson(
cl::cat(MyToolCategory),
cl::ValueDisallowed);

static cl::opt<bool> FixupHydeSubfield(
"fixup-hyde-subfield",
cl::desc("Fix-up preexisting documentation; move all fields except `layout` and `title` into a `hyde` subfield. `hyde-update` mode only."),
cl::cat(MyToolCategory),
cl::ValueDisallowed);

static cl::opt<hyde::attribute_category> TestedBy(
"hyde-tested-by",
cl::values(
Expand Down Expand Up @@ -595,7 +601,8 @@ int main(int argc, const char** argv) try {
hyde::emit_options emit_options;
emit_options._tested_by = TestedBy;
emit_options._ignore_extraneous_files = IgnoreExtraneousFiles;

emit_options._fixup_hyde_subfield = FixupHydeSubfield;

auto out_emitted = hyde::json::object();
output_yaml(std::move(result), std::move(src_root), std::move(dst_root), out_emitted,
ToolMode == ToolModeYAMLValidate ? hyde::yaml_mode::validate :
Expand Down

0 comments on commit c05cd67

Please sign in to comment.