Add support for yang type descriptions
Change-Id: I1fd070fb975aa82b2d4c1aa4165c5ab0153ff49f
diff --git a/src/interpreter.cpp b/src/interpreter.cpp
index f1682bf..aaa0595 100644
--- a/src/interpreter.cpp
+++ b/src/interpreter.cpp
@@ -127,6 +127,7 @@
std::string Interpreter::buildTypeInfo(const std::string& path) const
{
std::ostringstream ss;
+ std::string typeDescription;
switch (m_datastore.schema()->nodeType(path)) {
case yang::NodeTypes::Container:
ss << "container";
@@ -156,6 +157,10 @@
ss << " [" + *leafType.m_units + "]";
}
+ if (leafType.m_description) {
+ typeDescription = "\nType description: " + *leafType.m_description;
+ }
+
if (m_datastore.schema()->leafIsKey(path)) {
ss << " (key)";
}
@@ -184,24 +189,29 @@
}
if (!m_datastore.schema()->isConfig(path)) {
- ss << " (ro)";
+ ss << " (ro)\n";
}
- return ss.str();
-}
-
-void Interpreter::operator()(const describe_& describe) const
-{
- auto path = pathToString(toCanonicalPath(describe.m_path));
auto status = m_datastore.schema()->status(path);
auto statusStr = status == yang::Status::Deprecated ? " (deprecated)" :
status == yang::Status::Obsolete ? " (obsolete)" :
"";
- std::cout << path << ": " << buildTypeInfo(path) << statusStr << std::endl;
+ ss << statusStr;
+
if (auto description = m_datastore.schema()->description(path)) {
- std::cout << std::endl << *description << std::endl;
+ ss << std::endl << *description << std::endl;
}
+
+ ss << typeDescription;
+ return ss.str();
+}
+
+void Interpreter::operator()(const describe_& describe) const
+{
+ auto fullPath = pathToString(toCanonicalPath(describe.m_path));
+
+ std::cout << pathToString(describe.m_path) << ": " << buildTypeInfo(fullPath) << std::endl;
}
void Interpreter::operator()(const move_& move) const
diff --git a/src/leaf_data_type.cpp b/src/leaf_data_type.cpp
index fe6fe04..f97e382 100644
--- a/src/leaf_data_type.cpp
+++ b/src/leaf_data_type.cpp
@@ -10,11 +10,12 @@
namespace yang {
bool TypeInfo::operator==(const TypeInfo& other) const
{
- return this->m_type == other.m_type && this->m_units == other.m_units;
+ return std::tie(this->m_type, this->m_units, this->m_description) == std::tie(other.m_type, other.m_units, other.m_description);
}
-TypeInfo::TypeInfo(const yang::LeafDataType& type, const std::optional<std::string> units)
+TypeInfo::TypeInfo(const yang::LeafDataType& type, const std::optional<std::string> units, const std::optional<std::string> description)
: m_type(type)
, m_units(units)
+ , m_description(description)
{
}
Enum::Enum(std::set<enum_>&& values)
diff --git a/src/leaf_data_type.hpp b/src/leaf_data_type.hpp
index 98cb12e..35a2961 100644
--- a/src/leaf_data_type.hpp
+++ b/src/leaf_data_type.hpp
@@ -105,9 +105,12 @@
std::vector<TypeInfo> m_unionTypes;
};
struct TypeInfo {
- TypeInfo(const yang::LeafDataType& type, const std::optional<std::string> units = std::nullopt);
+ TypeInfo(const yang::LeafDataType& type,
+ const std::optional<std::string> units = std::nullopt,
+ const std::optional<std::string> description = std::nullopt);
bool operator==(const TypeInfo& other) const;
yang::LeafDataType m_type;
std::optional<std::string> m_units;
+ std::optional<std::string> m_description;
};
}
diff --git a/src/yang_schema.cpp b/src/yang_schema.cpp
index 7f27711..7e5bb9f 100644
--- a/src/yang_schema.cpp
+++ b/src/yang_schema.cpp
@@ -284,7 +284,19 @@
}
}
- return yang::TypeInfo(resType, resUnits);
+ std::optional<std::string> resDescription;
+
+ // checking for parentTypedef->type()->der() means I'm going to enter inside base types like "string". These
+ // also have a description, but it isn't too helpful ("human-readable string")
+ for (auto parentTypedef = type->der(); parentTypedef && parentTypedef->type()->der(); parentTypedef = parentTypedef->type()->der()) {
+ auto dsc = parentTypedef->dsc();
+ if (dsc) {
+ resDescription = dsc;
+ break;
+ }
+ }
+
+ return yang::TypeInfo(resType, resUnits, resDescription);
};
return resolveType(leaf->type());
}
diff --git a/tests/example-schema.yang b/tests/example-schema.yang
index 6c546d3..0db4c4f 100644
--- a/tests/example-schema.yang
+++ b/tests/example-schema.yang
@@ -88,6 +88,16 @@
}
}
+ typedef myType {
+ type int32;
+ description "My type.";
+ }
+
+ leaf typedefedLeaf {
+ type myType;
+ description "This is a typedefed leaf.";
+ }
+
grouping upAndDown {
leaf up {
type boolean;
diff --git a/tests/pretty_printers.hpp b/tests/pretty_printers.hpp
index 1c7154b..7f19a8e 100644
--- a/tests/pretty_printers.hpp
+++ b/tests/pretty_printers.hpp
@@ -96,7 +96,9 @@
std::ostream& operator<<(std::ostream& s, const yang::TypeInfo& type)
{
- s << type.m_type << (type.m_units ? " units: " + *type.m_units : "");
+ s << type.m_type;
+ s << " units: " << (type.m_units ? *type.m_units : "std::nullopt");
+ s << " description: " << (type.m_description ? *type.m_description : "std::nullopt");
return s;
}
diff --git a/tests/yang.cpp b/tests/yang.cpp
index 1ec6507..699a05c 100644
--- a/tests/yang.cpp
+++ b/tests/yang.cpp
@@ -171,6 +171,7 @@
enum lol;
enum data;
}
+ description "This is a restricted enum typedef.";
}
leaf leafEnumTypedef {
@@ -518,6 +519,7 @@
SECTION("leafType")
{
yang::LeafDataType type;
+ std::optional<std::string> expectedDescription;
SECTION("leafString")
{
@@ -622,6 +624,7 @@
node.first = "example-schema";
node.second = "leafEnumTypedefRestricted2";
type = createEnum({"lol", "data"});
+ expectedDescription = "This is a restricted enum typedef.";
}
SECTION("pizzaSize")
@@ -736,7 +739,7 @@
}
- REQUIRE(ys.leafType(path, node) == type);
+ REQUIRE(ys.leafType(path, node) == yang::TypeInfo(type, std::nullopt, expectedDescription));
}
SECTION("availableNodes")
{
@@ -1072,6 +1075,16 @@
REQUIRE(ys.leafType(pathToSchemaString(path, Prefixes::WhenNeeded)) == yang::TypeInfo{expectedType, expectedUnits});
}
+ SECTION("type description")
+ {
+ yang::LeafDataType expectedType = createEnum({"lol", "data"});
+ std::optional<std::string> expectedDescription;
+
+ path.m_nodes.emplace_back(module_{"example-schema"}, leaf_("leafEnumTypedefRestricted2"));
+ expectedDescription = "This is a restricted enum typedef.";
+ REQUIRE(ys.leafType(pathToSchemaString(path, Prefixes::WhenNeeded)) == yang::TypeInfo{expectedType, std::nullopt, expectedDescription});
+ }
+
SECTION("nodeType")
{
yang::NodeTypes expected;