Add enum completion
Change-Id: I5ee7d6359812535d0eef9f70e1b66e205d93cf39
diff --git a/src/ast_handlers.hpp b/src/ast_handlers.hpp
index 943af19..7eed8be 100644
--- a/src/ast_handlers.hpp
+++ b/src/ast_handlers.hpp
@@ -569,3 +569,22 @@
_pass(context) = false;
}
};
+
+struct createEnumSuggestions_class {
+ template <typename T, typename Iterator, typename Context>
+ void on_success(Iterator const& begin, Iterator const&, T&, Context const& context)
+ {
+ auto& parserContext = x3::get<parser_context_tag>(context);
+ parserContext.m_completionIterator = begin;
+ const Schema& schema = parserContext.m_schema;
+
+ boost::optional<std::string> module;
+ if (parserContext.m_curPath.m_nodes.back().m_prefix)
+ module = parserContext.m_curPath.m_nodes.back().m_prefix.value().m_name;
+
+ leaf_ leaf = boost::get<leaf_>(parserContext.m_curPath.m_nodes.back().m_suffix);
+ schemaPath_ location = pathWithoutLastNode(parserContext.m_curPath);
+
+ parserContext.m_suggestions = schema.enumValues(location, {module, leaf.m_name});
+ }
+};
diff --git a/src/grammars.hpp b/src/grammars.hpp
index 3742e35..c12f922 100644
--- a/src/grammars.hpp
+++ b/src/grammars.hpp
@@ -59,6 +59,7 @@
x3::rule<suggestKeysEnd_class, x3::unused_type> const suggestKeysEnd = "suggestKeysEnd";
x3::rule<createCommandSuggestions_class, x3::unused_type> const createCommandSuggestions = "createCommandSuggestions";
x3::rule<completing_class, x3::unused_type> const completing = "completing";
+x3::rule<createEnumSuggestions_class, x3::unused_type> const createEnumSuggestions = "createEnumSuggestions";
#if __clang__
#pragma GCC diagnostic push
@@ -174,8 +175,11 @@
auto const leafPath_def =
dataPath;
+auto const createEnumSuggestions_def =
+ x3::eps;
+
auto const leaf_data_enum_def =
- +char_;
+ createEnumSuggestions >> +char_;
auto const leaf_data_decimal_def =
double_;
@@ -234,7 +238,7 @@
get_::name >> -(space_separator >> (dataPathListEnd | dataPath));
auto const set_def =
- set_::name >> space_separator > leafPath > leaf_data;
+ set_::name >> space_separator > leafPath > space_separator > leaf_data;
auto const commit_def =
commit_::name >> x3::attr(commit_());
@@ -296,3 +300,4 @@
BOOST_SPIRIT_DEFINE(suggestKeysEnd)
BOOST_SPIRIT_DEFINE(createCommandSuggestions)
BOOST_SPIRIT_DEFINE(completing)
+BOOST_SPIRIT_DEFINE(createEnumSuggestions)
diff --git a/src/schema.hpp b/src/schema.hpp
index e1f019f..c55e659 100644
--- a/src/schema.hpp
+++ b/src/schema.hpp
@@ -79,6 +79,7 @@
virtual bool nodeExists(const std::string& location, const std::string& node) const = 0;
virtual const std::set<std::string> listKeys(const schemaPath_& location, const ModuleNodePair& node) const = 0;
virtual yang::LeafDataTypes leafType(const schemaPath_& location, const ModuleNodePair& node) const = 0;
+ virtual const std::set<std::string> enumValues(const schemaPath_& location, const ModuleNodePair& node) const = 0;
virtual std::set<std::string> childNodes(const schemaPath_& path, const Recursion recursion) const = 0;
private:
diff --git a/src/static_schema.cpp b/src/static_schema.cpp
index 9be7751..d80ac7b 100644
--- a/src/static_schema.cpp
+++ b/src/static_schema.cpp
@@ -121,12 +121,8 @@
bool StaticSchema::leafEnumHasValue(const schemaPath_& location, const ModuleNodePair& node, const std::string& value) const
{
- std::string locationString = pathToAbsoluteSchemaString(location);
- assert(isLeaf(location, node));
-
- const auto& child = children(locationString).at(fullNodeName(location, node));
- const auto& list = boost::get<yang::leaf>(child);
- return list.m_enumValues.find(value) != list.m_enumValues.end();
+ auto enums = enumValues(location, node);
+ return enums.find(value) != enums.end();
}
bool StaticSchema::isLeaf(const schemaPath_& location, const ModuleNodePair& node) const
@@ -145,6 +141,16 @@
return boost::get<yang::leaf>(children(locationString).at(fullNodeName(location, node))).m_type;
}
+const std::set<std::string> StaticSchema::enumValues(const schemaPath_& location, const ModuleNodePair& node) const
+{
+ std::string locationString = pathToAbsoluteSchemaString(location);
+ assert(isLeaf(location, node));
+
+ const auto& child = children(locationString).at(fullNodeName(location, node));
+ const auto& leaf = boost::get<yang::leaf>(child);
+ return leaf.m_enumValues;
+}
+
// We do not test StaticSchema, so we don't need to implement recursive childNodes
// for this class.
std::set<std::string> StaticSchema::childNodes(const schemaPath_& path, const Recursion) const
diff --git a/src/static_schema.hpp b/src/static_schema.hpp
index 7326120..d07852e 100644
--- a/src/static_schema.hpp
+++ b/src/static_schema.hpp
@@ -33,6 +33,7 @@
bool nodeExists(const std::string& location, const std::string& node) const override;
const std::set<std::string> listKeys(const schemaPath_& location, const ModuleNodePair& node) const override;
yang::LeafDataTypes leafType(const schemaPath_& location, const ModuleNodePair& node) const override;
+ const std::set<std::string> enumValues(const schemaPath_& location, const ModuleNodePair& node) const override;
std::set<std::string> childNodes(const schemaPath_& path, const Recursion) const override;
void addContainer(const std::string& location, const std::string& name, yang::ContainerTraits isPresence = yang::ContainerTraits::None);
diff --git a/src/yang_schema.cpp b/src/yang_schema.cpp
index 522e58a..8b870fc 100644
--- a/src/yang_schema.cpp
+++ b/src/yang_schema.cpp
@@ -112,8 +112,15 @@
bool YangSchema::leafEnumHasValue(const schemaPath_& location, const ModuleNodePair& node, const std::string& value) const
{
+ auto enums = enumValues(location, node);
+
+ return std::any_of(enums.begin(), enums.end(), [=](const auto& x) { return x == value; });
+}
+
+const std::set<std::string> YangSchema::enumValues(const schemaPath_& location, const ModuleNodePair& node) const
+{
if (!isLeaf(location, node) || leafType(location, node) != yang::LeafDataTypes::Enum)
- return false;
+ return {};
libyang::Schema_Node_Leaf leaf(getSchemaNode(location, node));
auto type = leaf.type();
@@ -126,7 +133,9 @@
enm = type->info()->enums()->enm();
}
- return std::any_of(enm.begin(), enm.end(), [=](const auto& x) { return x->name() == value; });
+ std::set<std::string> enumSet;
+ std::transform(enm.begin(), enm.end(), std::inserter(enumSet, enumSet.end()), [](auto it) { return it->name(); });
+ return enumSet;
}
bool YangSchema::listHasKey(const schemaPath_& location, const ModuleNodePair& node, const std::string& key) const
diff --git a/src/yang_schema.hpp b/src/yang_schema.hpp
index e4d6d5d..e56c853 100644
--- a/src/yang_schema.hpp
+++ b/src/yang_schema.hpp
@@ -39,6 +39,7 @@
bool nodeExists(const std::string& location, const std::string& node) const override;
const std::set<std::string> listKeys(const schemaPath_& location, const ModuleNodePair& node) const override;
yang::LeafDataTypes leafType(const schemaPath_& location, const ModuleNodePair& node) const override;
+ const std::set<std::string> enumValues(const schemaPath_& location, const ModuleNodePair& node) const override;
std::set<std::string> childNodes(const schemaPath_& path, const Recursion recursion) const override;
void registerModuleCallback(const std::function<std::string(const char*, const char*, const char*)>& clb);