Skip to content

Commit 3c86c1a

Browse files
Comment Support in JSON output (#79)
* wip * wip * wip * first pass at a fleshed out `ProcessComment` * roll up paragraph comments into their parents * comments now included in standard declaration json as `inline_comments` * removing uncessary calls * tweak * more post-processing of commands for json output * formatting * adding all `hyde` values under a top-level `hyde` YAML key * starting to inject some doxygen comments into the YAML * wip * enumerations appear to be documented well enough at this point. * incorporating inline support throughout the emitters * progress into better docs for classes * support for compiler-provided (implicit) implementation annotations among other tweaks * more tweaks to example files; also cdor/dtor briefs are optional * ownership inheritance and brief/description function roll-up * tweak * parameter directions and another sample file to flex the kinds of inline documentation we may see. Support should be extended to some of these commands more formally (e.g., throw or warning.) * more sample documentation * more ease-of-use features around implicit routines and ownership bubble-up * idempotency: making sure the second in two back-to-back updates changes nothing * formatting * more bug fixes * better `have` YAML processing * working on =default or =delete -> optional instead of required * better compiler-managed (implicit, `=default`, `=delete`) routine handling * Moving the fixup functionality to its own standalone mode
1 parent d15fda8 commit 3c86c1a

39 files changed

+1383
-308
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,17 @@ To validate pre-existing YAML:
8383

8484
To output updated YAML:
8585
```./hyde -use-system-clang -hyde-yaml-dir=/path/to/output -hyde-update ../test_files/classes.cpp```
86+
87+
# Hyde 1 to Hyde 2 Format Conversion
88+
89+
As of the Hyde 2 work, all subfields in the YAML output (except the Jekyll-required `layout` and `title` fields) must go under a top-level `hyde` subfield. This allows for other tools to include additional (possibly same-named) fields under their own top-level subfields in the YAML.
90+
91+
Here is an example of updating from Hyde 1 to Hyde 2 formatted docs by scanning a directory for markdown-formatted files and passing them to `hyde` with the new `-hyde-fixup-subfield` mode:
92+
93+
find . -name '*.md' | xargs -I % -L 1 /path/to/hyde -hyde-fixup-subfield % --
94+
95+
# Sass Updates
96+
97+
Sometimes it may be necessary to clean up or "lint" the sass files. You can do so with:
98+
99+
bundle exec sass-convert -i /path/to/file.scss

docs/libraries/index.md

Lines changed: 0 additions & 12 deletions
This file was deleted.

emitters/yaml_base_emitter.cpp

Lines changed: 335 additions & 109 deletions
Large diffs are not rendered by default.

emitters/yaml_base_emitter.hpp

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ NOTICE: Adobe permits you to use, modify, and distribute this file in
66
accordance with the terms of the Adobe license agreement accompanying
77
it. If you have received this file from a source other than Adobe,
88
then your use, modification, or distribution of it requires the prior
9-
written permission of Adobe.
9+
written permission of Adobe.
1010
*/
1111

1212
#pragma once
@@ -47,36 +47,58 @@ struct file_checker {
4747

4848
/**************************************************************************************************/
4949

50+
inline bool has_json_flag(const json& j, const char* k) {
51+
return j.count(k) && j.at(k).get<bool>();
52+
}
53+
54+
/**************************************************************************************************/
55+
5056
struct yaml_base_emitter {
5157
public:
5258
yaml_base_emitter(std::filesystem::path src_root,
5359
std::filesystem::path dst_root,
5460
yaml_mode mode,
5561
emit_options options,
5662
bool editable_title = false)
57-
: _src_root(std::move(src_root)), _dst_root(std::move(dst_root)), _mode(mode), _options(std::move(options)), _editable_title{editable_title} {}
63+
: _src_root(std::move(src_root)), _dst_root(std::move(dst_root)), _mode(mode),
64+
_options(std::move(options)), _editable_title{editable_title} {}
5865

59-
virtual bool emit(const json& j, json& out_emitted) = 0;
66+
/// @param matched The json given to us by the matcher engine
67+
/// @param output The resulting output of this call
68+
/// @param inherited Any inherited fields from parent constructs, e.g., passing
69+
/// the owner of a class to its members
70+
/// @return `true` if an error took place during emit; `false` otherwise.
71+
virtual bool emit(const json& matched, json& output, const json& inherited) = 0;
6072

6173
protected:
62-
json base_emitter_node(std::string layout, std::string title, std::string tag);
74+
json base_emitter_node(std::string layout, std::string title, std::string tag, bool implicit);
6375

64-
bool reconcile(json node, std::filesystem::path root_path, std::filesystem::path path, json& out_reconciled);
76+
bool reconcile(json node,
77+
std::filesystem::path root_path,
78+
std::filesystem::path path,
79+
json& out_reconciled);
6580

66-
std::string defined_in_file(const std::string& src_path,
67-
const std::filesystem::path& src_root);
81+
std::string defined_in_file(const std::string& src_path, const std::filesystem::path& src_root);
6882

6983
std::filesystem::path subcomponent(const std::filesystem::path& src_path,
70-
const std::filesystem::path& src_root);
84+
const std::filesystem::path& src_root);
7185

72-
void maybe_annotate(const json& j, json& node); // make out arg?
86+
// For some reason nlohmann's JSON types aren't happy with my moving them about
87+
// (they always seem to show up null (~) in the final YAML output)
88+
// so converting these to out-arg-based routines will have to wait until I can
89+
// sort that out.
90+
void insert_inherited(const json& inherited, json& node); // make out arg?
91+
void insert_annotations(const json& j, json& node); // make out arg?
92+
void insert_doxygen(const json& j, json& node); // make out arg?
7393

7494
std::string format_template_parameters(const json& json, bool with_types);
7595

7696
std::string filename_filter(std::string f);
7797
std::string filename_truncate(std::string s);
7898

79-
void insert_typedefs(const json& j, json& node);
99+
void insert_typedefs(const json& j, json& node, const json& inherited);
100+
101+
void check_inline_comments(const json& expected, json& out_merged);
80102

81103
bool check_typedefs(const std::string& filepath,
82104
const json& have_node,
@@ -143,6 +165,8 @@ struct yaml_base_emitter {
143165
const std::string& key,
144166
const check_proc& proc);
145167

168+
static bool has_inline_field(const json& j, const char* field);
169+
146170
private:
147171
template <typename Arg, typename... Args>
148172
std::filesystem::path dst_path_append(std::filesystem::path p, Arg&& arg, Args&&... args);
@@ -206,7 +230,9 @@ std::filesystem::path yaml_base_emitter::dst_path(const json& j, Args&&... args)
206230
/**************************************************************************************************/
207231

208232
template <typename Arg, typename... Args>
209-
std::filesystem::path yaml_base_emitter::dst_path_append(std::filesystem::path p, Arg&& arg, Args&&... args) {
233+
std::filesystem::path yaml_base_emitter::dst_path_append(std::filesystem::path p,
234+
Arg&& arg,
235+
Args&&... args) {
210236
return dst_path_append(dst_path_append(std::move(p), arg), std::forward<Args>(args)...);
211237
}
212238

emitters/yaml_base_emitter_fwd.hpp

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,19 @@ NOTICE: Adobe permits you to use, modify, and distribute this file in
66
accordance with the terms of the Adobe license agreement accompanying
77
it. If you have received this file from a source other than Adobe,
88
then your use, modification, or distribution of it requires the prior
9-
written permission of Adobe.
9+
written permission of Adobe.
1010
*/
1111

1212
#pragma once
1313

1414
// stdc++
15+
#include <filesystem>
1516
#include <stdexcept>
1617
#include <string>
1718

19+
// application
20+
#include "json.hpp"
21+
1822
/**************************************************************************************************/
1923

2024
namespace hyde {
@@ -24,16 +28,12 @@ namespace hyde {
2428
static constexpr char const* tag_value_missing_k = "__MISSING__";
2529
static constexpr char const* tag_value_optional_k = "__OPTIONAL__";
2630
static constexpr char const* tag_value_deprecated_k = "__DEPRECATED__";
31+
static constexpr char const* tag_value_inlined_k = "__INLINED__";
2732
static constexpr char const* index_filename_k = "index.md";
2833

2934
/**************************************************************************************************/
3035

31-
enum class attribute_category {
32-
disabled,
33-
required,
34-
optional,
35-
deprecated
36-
};
36+
enum class attribute_category { disabled, required, optional, deprecated, inlined };
3737

3838
static constexpr char const* get_tag(attribute_category c) {
3939
switch (c) {
@@ -43,25 +43,37 @@ static constexpr char const* get_tag(attribute_category c) {
4343
return tag_value_optional_k;
4444
case attribute_category::deprecated:
4545
return tag_value_deprecated_k;
46+
case attribute_category::inlined:
47+
return tag_value_inlined_k;
4648
default:
4749
throw std::invalid_argument("unexpected attribute category");
4850
}
4951
}
5052

51-
static inline bool is_tag(const std::string& s) {
52-
return s.substr(0, 2) == "__";
53-
}
53+
static inline bool is_tag(const std::string& s) { return s.substr(0, 2) == "__"; }
5454

5555
/**************************************************************************************************/
5656

5757
struct emit_options {
5858
attribute_category _tested_by{attribute_category::disabled};
5959
bool _ignore_extraneous_files{false};
60-
bool _fixup_hyde_subfield{false};
6160
};
6261

6362
/**************************************************************************************************/
6463

64+
struct documentation {
65+
json _json;
66+
std::string _remainder;
67+
bool _error{false};
68+
};
69+
70+
documentation parse_documentation(const std::filesystem::path& path, bool fixup_subfield);
71+
72+
/// @return `true` on failure to write, `false` otherwise.
73+
bool write_documentation(const documentation& docs, const std::filesystem::path& path);
74+
75+
/**************************************************************************************************/
76+
6577
} // namespace hyde
6678

6779
/**************************************************************************************************/

emitters/yaml_class_emitter.cpp

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ NOTICE: Adobe permits you to use, modify, and distribute this file in
66
accordance with the terms of the Adobe license agreement accompanying
77
it. If you have received this file from a source other than Adobe,
88
then your use, modification, or distribution of it requires the prior
9-
written permission of Adobe.
9+
written permission of Adobe.
1010
*/
1111

1212
// identity
@@ -43,14 +43,18 @@ bool yaml_class_emitter::do_merge(const std::string& filepath,
4343
bool failure{false};
4444

4545
failure |= check_scalar(filepath, have, expected, nodepath, out_merged, "type");
46-
failure |= check_editable_scalar(filepath, have, expected, nodepath, out_merged, "description");
47-
failure |= check_scalar_array(filepath, have, expected, nodepath, out_merged, "annotation");
46+
failure |= check_editable_scalar(filepath, have, expected, nodepath, out_merged,
47+
"description");
48+
failure |=
49+
check_scalar_array(filepath, have, expected, nodepath, out_merged, "annotation");
50+
51+
check_inline_comments(expected, out_merged);
4852

4953
return failure;
5054
});
5155

5256
failure |= check_typedefs(filepath, have, expected, "", out_merged);
53-
57+
5458
failure |= check_object_array(
5559
filepath, have, expected, "", out_merged, "methods", "title",
5660
[this](const std::string& filepath, const json& have, const json& expected,
@@ -59,15 +63,20 @@ bool yaml_class_emitter::do_merge(const std::string& filepath,
5963
return function_emitter.do_merge(filepath, have, expected, out_merged);
6064
});
6165

66+
check_inline_comments(expected, out_merged);
67+
6268
return failure;
6369
}
6470

6571
/**************************************************************************************************/
6672

67-
bool yaml_class_emitter::emit(const json& j, json& out_emitted) {
68-
json node = base_emitter_node("class", j["name"], "class");
73+
bool yaml_class_emitter::emit(const json& j, json& out_emitted, const json& inherited) {
74+
json node = base_emitter_node("class", j["name"], "class", has_json_flag(j, "implicit"));
6975
node["hyde"]["defined_in_file"] = defined_in_file(j["defined_in_file"], _src_root);
70-
maybe_annotate(j, node);
76+
77+
insert_inherited(inherited, node["hyde"]);
78+
insert_annotations(j, node["hyde"]);
79+
insert_doxygen(j, node["hyde"]);
7180

7281
std::string declaration = format_template_parameters(j, true) + '\n' +
7382
static_cast<const std::string&>(j["kind"]) + " " +
@@ -84,26 +93,31 @@ bool yaml_class_emitter::emit(const json& j, json& out_emitted) {
8493
for (const auto& field : j["fields"]) {
8594
const std::string& key = field["name"];
8695
auto& field_node = node["hyde"]["fields"][key];
96+
insert_annotations(field, field_node);
97+
insert_doxygen(field, field_node);
98+
8799
field_node["type"] = static_cast<const std::string&>(field["type"]);
88-
field_node["description"] = tag_value_missing_k;
89-
maybe_annotate(field, field_node);
100+
const bool inline_description_exists =
101+
field_node.count("inline") && field_node["inline"].count("description");
102+
field_node["description"] =
103+
inline_description_exists ? tag_value_inlined_k : tag_value_missing_k;
90104
}
91105
}
92106

93-
insert_typedefs(j, node);
107+
insert_typedefs(j, node, inherited);
94108

95-
auto dst = dst_path(j,
96-
static_cast<const std::string&>(j["name"]));
109+
auto dst = dst_path(j, static_cast<const std::string&>(j["name"]));
97110

98-
bool failure = reconcile(std::move(node), _dst_root, std::move(dst) / index_filename_k, out_emitted);
111+
bool failure =
112+
reconcile(std::move(node), _dst_root, std::move(dst) / index_filename_k, out_emitted);
99113

100114
const auto& methods = j["methods"];
101115
yaml_function_emitter function_emitter(_src_root, _dst_root, _mode, _options, true);
102116

103117
for (auto it = methods.begin(); it != methods.end(); ++it) {
104118
function_emitter.set_key(it.key());
105119
auto function_emitted = hyde::json::object();
106-
failure |= function_emitter.emit(it.value(), function_emitted);
120+
failure |= function_emitter.emit(it.value(), function_emitted, out_emitted.at("hyde"));
107121
out_emitted["methods"].push_back(std::move(function_emitted));
108122
}
109123

emitters/yaml_class_emitter.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ NOTICE: Adobe permits you to use, modify, and distribute this file in
66
accordance with the terms of the Adobe license agreement accompanying
77
it. If you have received this file from a source other than Adobe,
88
then your use, modification, or distribution of it requires the prior
9-
written permission of Adobe.
9+
written permission of Adobe.
1010
*/
1111

1212
#pragma once
@@ -28,7 +28,7 @@ struct yaml_class_emitter : public yaml_base_emitter {
2828
emit_options options)
2929
: yaml_base_emitter(std::move(src_root), std::move(dst_root), mode, std::move(options)) {}
3030

31-
bool emit(const json& j, json& out_emitted) override;
31+
bool emit(const json& matched, json& output, const json& inherited) override;
3232

3333
bool do_merge(const std::string& filepath,
3434
const json& have,

0 commit comments

Comments
 (0)