Move documentation generation to DocumentationEngine

Split Verifiers documentation method into documentation and type
This commit is contained in:
Alexander Bock
2016-09-15 18:58:22 +02:00
parent f22f01ce95
commit 75651224a7
6 changed files with 113 additions and 65 deletions

View File

@@ -56,7 +56,7 @@ struct DocumentationEntry {
Optional optional = Optional::No);
std::string key;
std::shared_ptr<Verifier> tester;
std::shared_ptr<Verifier> verifier;
bool optional;
std::string documentation;
};
@@ -76,8 +76,6 @@ TestResult testSpecification(const Documentation& d, const ghoul::Dictionary& di
void testSpecificationAndThrow(const Documentation& doc,
const ghoul::Dictionary& dictionary, std::string component);
std::string generateDocumentation(const Documentation& d);
} // namespace documentation
using documentation::Documentation;

View File

@@ -36,7 +36,8 @@ struct Verifier {
virtual bool test(const ghoul::Dictionary& dict, const std::string& key) const;
virtual std::string documentation() const = 0;
virtual std::string type() const = 0;
virtual std::string documentation() const;
};
// General verifiers
@@ -48,25 +49,25 @@ struct TemplateVerifier : public Verifier {
struct BoolVerifier : public TemplateVerifier<bool> {
bool test(const ghoul::Dictionary& dict, const std::string& key) const override;
std::string documentation() const override;
std::string type() const override;
};
struct DoubleVerifier : public TemplateVerifier<double> {
bool test(const ghoul::Dictionary& dict, const std::string& key) const override;
std::string documentation() const override;
std::string type() const override;
};
struct IntVerifier : public TemplateVerifier<int> {
bool test(const ghoul::Dictionary& dict, const std::string& key) const override;
std::string documentation() const override;
std::string type() const override;
};
struct StringVerifier : public TemplateVerifier<std::string> {
bool test(const ghoul::Dictionary& dict, const std::string& key) const override;
std::string documentation() const override;
std::string type() const override;
};
struct TableVerifier : public TemplateVerifier<ghoul::Dictionary> {
@@ -74,7 +75,7 @@ struct TableVerifier : public TemplateVerifier<ghoul::Dictionary> {
TestResult operator()(const ghoul::Dictionary& dict, const std::string& key) const override;
std::string documentation() const override;
std::string type() const override;
std::vector<DocumentationEntry> doc;
};
@@ -85,21 +86,21 @@ template <typename T>
struct Vector2Verifier : public TemplateVerifier<glm::tvec2<T>>, public VectorVerifier {
bool test(const ghoul::Dictionary& dict, const std::string& key) const override;
std::string documentation() const override;
std::string type() const override;
};
template <typename T>
struct Vector3Verifier : public TemplateVerifier<glm::tvec3<T>>, public VectorVerifier {
bool test(const ghoul::Dictionary& dict, const std::string& key) const override;
std::string documentation() const override;
std::string type() const override;
};
template <typename T>
struct Vector4Verifier : public TemplateVerifier<glm::tvec4<T>>, public VectorVerifier {
bool test(const ghoul::Dictionary& dict, const std::string& key) const override;
std::string documentation() const override;
std::string type() const override;
};
// Operator Verifiers
@@ -277,6 +278,7 @@ struct AndVerifier : public Verifier {
bool test(const ghoul::Dictionary& dict, const std::string& key) const override;
std::string type() const override;
std::string documentation() const override;
std::shared_ptr<Verifier> a;
@@ -288,6 +290,7 @@ struct OrVerifier : public Verifier {
bool test(const ghoul::Dictionary& dict, const std::string& key) const override;
std::string type() const override;
std::string documentation() const override;
std::shared_ptr<Verifier> a;

View File

@@ -37,10 +37,10 @@ bool Vector2Verifier<T>::test(const ghoul::Dictionary& d, const std::string& k)
}
template <typename T>
std::string Vector2Verifier<T>::documentation() const {
std::string Vector2Verifier<T>::type() const {
using namespace std::string_literals;
return "Type: Vector2<"s + typeid(T).name() + ">";
return "Vector2<"s + typeid(T).name() + ">";
}
template <typename T>
@@ -49,10 +49,10 @@ bool Vector3Verifier<T>::test(const ghoul::Dictionary& d, const std::string& k)
}
template <typename T>
std::string Vector3Verifier<T>::documentation() const {
std::string Vector3Verifier<T>::type() const {
using namespace std::string_literals;
return "Type: Vector3<"s + typeid(T).name() + ">";
return "Vector3<"s + typeid(T).name() + ">";
}
template <typename T>
@@ -61,10 +61,10 @@ bool Vector4Verifier<T>::test(const ghoul::Dictionary& d, const std::string& k)
}
template <typename T>
std::string Vector4Verifier<T>::documentation() const {
std::string Vector4Verifier<T>::type() const {
using namespace std::string_literals;
return "Type: Vector4<"s + typeid(T).name() + ">";
return "Vector4<"s + typeid(T).name() + ">";
}
template <typename T>
@@ -80,7 +80,7 @@ bool LessVerifier<T>::test(const ghoul::Dictionary& dict, const std::string& key
template <typename T>
std::string LessVerifier<T>::documentation() const {
return T::documentation() + '\n' + "Less than: " + std::to_string(value);
return "Less than: " + std::to_string(value);
}
@@ -96,7 +96,7 @@ bool LessEqualVerifier<T>::test(const ghoul::Dictionary& dict, const std::string
template <typename T>
std::string LessEqualVerifier<T>::documentation() const {
return T::documentation() + '\n' + "Less or equal to: " + std::to_string(value);
return "Less or equal to: " + std::to_string(value);
}
template <typename T>
@@ -111,7 +111,7 @@ bool GreaterVerifier<T>::test(const ghoul::Dictionary& dict, const std::string&
template <typename T>
std::string GreaterVerifier<T>::documentation() const {
return T::documentation() + '\n' + "Greater than: " + std::to_string(value);
return "Greater than: " + std::to_string(value);
}
template <typename T>
@@ -126,7 +126,7 @@ bool GreaterEqualVerifier<T>::test(const ghoul::Dictionary& dict, const std::str
template <typename T>
std::string GreaterEqualVerifier<T>::documentation() const {
return T::documentation() + '\n' + "Greater or equal to: " + std::to_string(value);
return "Greater or equal to: " + std::to_string(value);
}
template <typename T>
@@ -141,7 +141,7 @@ bool EqualVerifier<T>::test(const ghoul::Dictionary& dict, const std::string& ke
template <typename T>
std::string EqualVerifier<T>::documentation() const {
return T::documentation() + '\n' + "Equal to: " + std::to_string(value);
return "Equal to: " + std::to_string(value);
}
template <typename T>
@@ -156,7 +156,7 @@ bool UnequalVerifier<T>::test(const ghoul::Dictionary& dict, const std::string&
template <typename T>
std::string UnequalVerifier<T>::documentation() const {
return T::documentation() + '\n' + "Unequal to: " + std::to_string(value);
return "Unequal to: " + std::to_string(value);
}
template <typename T>
@@ -179,7 +179,7 @@ bool InListVerifier<T>::test(const ghoul::Dictionary& dict, const std::string& k
template <typename T>
std::string InListVerifier<T>::documentation() const {
std::string result = T::documentation() + '\n' + "In list {";
std::string result = "In list { ";
std::stringstream s;
std::copy(values.begin(), values.end(), std::ostream_iterator<typename T::Type>(s, ","));
@@ -188,7 +188,7 @@ std::string InListVerifier<T>::documentation() const {
// We need to remove a trailing ',' at the end of the string
result += joined.substr(0, joined.size() - 1);
result += "}";
result += " }";
return result;
}
@@ -212,7 +212,7 @@ bool NotInListVerifier<T>::test(const ghoul::Dictionary& dict, const std::string
template <typename T>
std::string NotInListVerifier<T>::documentation() const {
std::string result = T::documentation() + '\n' + "Not in list {";
std::string result = "Not in list { ";
std::stringstream s;
std::copy(values.begin(), values.end(), std::ostream_iterator<typename T::Type>(s, ","));
@@ -222,7 +222,7 @@ std::string NotInListVerifier<T>::documentation() const {
result += joined.substr(0, joined.size() - 1);
result += "}";
result += " }";
return result;
}
@@ -247,8 +247,8 @@ bool InRangeVerifier<T>::test(const ghoul::Dictionary& d, const std::string& key
template <typename T>
std::string InRangeVerifier<T>::documentation() const {
return T::documentation() + '\n' + "In range: (" + std::to_string(lower) + "," +
std::to_string(upper) + ")";
return "In range: ( " + std::to_string(lower) + "," +
std::to_string(upper) + " )";
}
template <typename T>
@@ -272,8 +272,8 @@ bool NotInRangeVerifier<T>::test(const ghoul::Dictionary& d, const std::string&
template <typename T>
std::string NotInRangeVerifier<T>::documentation() const {
return T::documentation() + '\n' + "Not in range: (" + std::to_string(lower) + "," +
std::to_string(upper) + ")";
return "Not in range: ( " + std::to_string(lower) + "," +
std::to_string(upper) + " )";
}
@@ -291,7 +291,7 @@ bool AnnotationVerifier<T>::test(const ghoul::Dictionary& dict,
template <typename T>
std::string AnnotationVerifier<T>::documentation() const {
return T::documentation() + '\n' + annotation;
return annotation;
}
} // namespace documentation

View File

@@ -48,7 +48,7 @@ SpecificationError::SpecificationError(TestResult result, std::string component)
DocumentationEntry::DocumentationEntry(std::string key, Verifier* t, std::string doc,
Optional optional)
: key(std::move(key))
, tester(std::move(t))
, verifier(std::move(t))
, documentation(std::move(doc))
, optional(optional) {}
@@ -66,7 +66,7 @@ TestResult testSpecification(const Documentation& d, const ghoul::Dictionary& di
for (const auto& p : d.entries) {
if (p.key == Wildcard) {
for (const std::string& key : dictionary.keys()) {
Verifier& verifier = *(p.tester);
Verifier& verifier = *(p.verifier);
TestResult res = verifier(dictionary, key);
if (!res.success) {
result.success = false;
@@ -84,7 +84,7 @@ TestResult testSpecification(const Documentation& d, const ghoul::Dictionary& di
// if the key exists, it has to be correct, however
continue;
}
Verifier& verifier = *(p.tester);
Verifier& verifier = *(p.verifier);
TestResult res = verifier(dictionary, p.key);
if (!res.success) {
result.success = false;
@@ -124,22 +124,5 @@ void testSpecificationAndThrow(const Documentation& doc,
}
}
std::string generateDocumentation(const Documentation& d) {
using namespace std::string_literals;
std::string result;
result += "Name: "s + d.name + '\n';
for (const auto& p : d.entries) {
result += p.key + '\n';
result += "Optional: "s + (p.optional ? "true" : "false") + '\n';
result += p.tester->documentation() + '\n';
result += '\n';
result += p.documentation + '\n';
}
return result;
}
} // namespace documentation
} // namespace openspace

View File

@@ -24,6 +24,8 @@
#include <openspace/documentation/documentationengine.h>
#include <openspace/documentation/verifier.h>
#include <ghoul/misc/assert.h>
#include <fstream>
@@ -31,6 +33,47 @@
namespace openspace {
namespace documentation {
std::string generateTextDocumentation(const Documentation& d, int& indentLevel) {
using namespace std::string_literals;
auto indentMessage = [&indentLevel](std::string prefix, std::string msg) {
if (msg.empty()) {
return ""s;
}
else {
return std::string(indentLevel, '\t') + prefix + ": " + msg + '\n';
}
};
std::string result;
result += indentMessage("Name", d.name);
if (!d.name.empty()) {
++indentLevel;
}
for (const auto& p : d.entries) {
result += indentMessage("Key", (p.key == "*") ? p.key : "\"" + p.key + "\"");
result += indentMessage("Optional", (p.optional ? "true" : "false"));
result += indentMessage("Type", p.verifier->type());
result += indentMessage("Restrictions", p.verifier->documentation());
TableVerifier* tv = dynamic_cast<TableVerifier*>(p.verifier.get());
if (tv) {
// We have a TableVerifier, so we need to recurse
++indentLevel;
result += generateTextDocumentation(tv->doc, indentLevel);
result = result.substr(0, result.size() - 2);
--indentLevel;
}
result += indentMessage("Documentation", p.documentation);
result += "\n\n";
}
if (!d.name.empty()) {
--indentLevel;
}
return result;
}
void DocumentationEngine::writeDocumentation(const std::string& f, const std::string& t) {
if (t == "text") {
std::ofstream file;
@@ -38,7 +81,8 @@ void DocumentationEngine::writeDocumentation(const std::string& f, const std::st
file.open(f);
for (const Documentation& d : _documentations) {
file << documentation::generateDocumentation(d) << std::endl << std::endl;
int indent = 0;
file << documentation::generateTextDocumentation(d, indent) << std::endl << std::endl;
}
}
}

View File

@@ -90,20 +90,24 @@ bool Verifier::test(const ghoul::Dictionary& dict, const std::string& key) const
return false;
};
std::string Verifier::documentation() const {
return "";
}
bool BoolVerifier::test(const ghoul::Dictionary& dict, const std::string& key) const {
return dict.hasKeyAndValue<Type>(key);
}
std::string BoolVerifier::documentation() const {
return "Type: Boolean";
std::string BoolVerifier::type() const {
return "Boolean";
}
bool DoubleVerifier::test(const ghoul::Dictionary & dict, const std::string & key) const {
return dict.hasKeyAndValue<Type>(key);
}
std::string DoubleVerifier::documentation() const {
return "Type: Double";
std::string DoubleVerifier::type() const {
return "Double";
}
bool IntVerifier::test(const ghoul::Dictionary & dict, const std::string & key) const {
@@ -124,16 +128,16 @@ bool IntVerifier::test(const ghoul::Dictionary & dict, const std::string & key)
}
}
std::string IntVerifier::documentation() const {
return "Type: Integer";
std::string IntVerifier::type() const {
return "Integer";
}
bool StringVerifier::test(const ghoul::Dictionary & dict, const std::string & key) const {
return dict.hasKeyAndValue<Type>(key);
}
std::string StringVerifier::documentation() const {
return "Type: String";
std::string StringVerifier::type() const {
return "String";
}
TableVerifier::TableVerifier(std::vector<DocumentationEntry> d)
@@ -156,19 +160,26 @@ TestResult TableVerifier::operator()(const ghoul::Dictionary& dict,
return { dict.hasKeyAndValue<Type>(key), { key } };
}
std::string TableVerifier::documentation() const {
return "Type: Table" + '\n' + generateDocumentation(doc);
std::string TableVerifier::type() const {
return "Table";
}
AndVerifier::AndVerifier(Verifier* a, Verifier* b)
: a(a)
, b(b)
{}
{
ghoul_assert(a->type() == b->type(), "Cannot use AndVerifier with different types");
}
bool AndVerifier::test(const ghoul::Dictionary& dict, const std::string& key) const {
return a->test(dict, key) && b->test(dict, key);
}
std::string AndVerifier::type() const {
// It does not matter which type we choose as they both have to be the same
return a->type();
}
std::string AndVerifier::documentation() const {
return a->documentation() + " and " + b->documentation();
}
@@ -182,6 +193,15 @@ bool OrVerifier::test(const ghoul::Dictionary& dict, const std::string& key) con
return a->test(dict, key) || b->test(dict, key);
}
std::string OrVerifier::type() const {
if (a->type() != b->type()) {
return a->type() + " or " + b->type();
}
else {
return a->type();
}
}
std::string OrVerifier::documentation() const {
return a->documentation() + " or " + b->documentation();
}