Merge changes I823773f4,If63415b5,Ic5a92c8b,I1f713427,I2a6c9f46, ...
* changes:
StaticSchema: Remove unused method
Change struct to a function
Simplify listInstancePath_class
Prefer std::variant in dataNode_/schemaNode_
Get rid of useless variant in get
Complete slash after lists when inputting "any" path
diff --git a/src/ast_commands.hpp b/src/ast_commands.hpp
index 5ce1cbd..5759eda 100644
--- a/src/ast_commands.hpp
+++ b/src/ast_commands.hpp
@@ -141,7 +141,7 @@
/> get
/> get /module:path)";
bool operator==(const get_& b) const;
- boost::optional<boost::variant<boost::variant<dataPath_, schemaPath_>, module_>> m_path;
+ boost::optional<boost::variant<dataPath_, schemaPath_, module_>> m_path;
};
struct describe_ : x3::position_tagged {
diff --git a/src/ast_handlers.hpp b/src/ast_handlers.hpp
index b9cf883..5b5a152 100644
--- a/src/ast_handlers.hpp
+++ b/src/ast_handlers.hpp
@@ -178,14 +178,14 @@
boost::optional<std::string> module;
if (ast.m_nodes.back().m_prefix)
module = ast.m_nodes.back().m_prefix.value().m_name;
- container_ cont = boost::get<container_>(ast.m_nodes.back().m_suffix);
+ container_ cont = std::get<container_>(ast.m_nodes.back().m_suffix);
auto location = pathWithoutLastNode(parserContext.currentSchemaPath());
if (!schema.isPresenceContainer(location, {module, cont.m_name})) {
parserContext.m_errorMsg = "This container is not a presence container.";
_pass(context) = false;
}
- } catch (boost::bad_get&) {
+ } catch (std::bad_variant_access&) {
parserContext.m_errorMsg = "This is not a container.";
_pass(context) = false;
}
@@ -197,13 +197,7 @@
void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
{
auto& parserContext = x3::get<parser_context_tag>(context);
- if (ast.m_nodes.empty()) {
- parserContext.m_errorMsg = "This is not a list instance.";
- _pass(context) = false;
- return;
- }
-
- if (ast.m_nodes.back().m_suffix.type() != typeid(listElement_)) {
+ if (ast.m_nodes.empty() || !std::holds_alternative<listElement_>(ast.m_nodes.back().m_suffix)) {
parserContext.m_errorMsg = "This is not a list instance.";
_pass(context) = false;
}
@@ -215,7 +209,7 @@
void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
{
auto& parserContext = x3::get<parser_context_tag>(context);
- if (ast.m_nodes.empty() || ast.m_nodes.back().m_suffix.type() != typeid(leafListElement_)) {
+ if (ast.m_nodes.empty() || !std::holds_alternative<leafListElement_>(ast.m_nodes.back().m_suffix)) {
parserContext.m_errorMsg = "This is not a leaf list element.";
_pass(context) = false;
}
@@ -267,14 +261,14 @@
try {
auto lastNode = parserContext.currentSchemaPath().m_nodes.back();
- auto leaf = boost::get<leaf_>(lastNode.m_suffix);
+ auto leaf = std::get<leaf_>(lastNode.m_suffix);
auto location = pathWithoutLastNode(parserContext.currentSchemaPath());
ModuleNodePair node{lastNode.m_prefix.flat_map([](const auto& it) { return boost::optional<std::string>{it.m_name}; }), leaf.m_name};
parserContext.m_tmpListKeyLeafPath.m_location = location;
parserContext.m_tmpListKeyLeafPath.m_node = node;
- } catch (boost::bad_get&) {
+ } catch (std::bad_variant_access&) {
parserContext.m_errorMsg = "This is not a path to leaf.";
_pass(context) = false;
}
@@ -415,13 +409,11 @@
}
};
-struct commandNamesVisitor {
- template <typename T>
- std::string operator()(boost::type<T>)
- {
- return T::name;
- }
-};
+template <typename T>
+std::string commandNamesVisitor (boost::type<T>)
+{
+ return T::name;
+}
struct createCommandSuggestions_class {
template <typename T, typename Iterator, typename Context>
@@ -432,7 +424,7 @@
parserContext.m_suggestions.clear();
boost::mpl::for_each<CommandTypes, boost::type<boost::mpl::_>>([&parserContext](auto cmd) {
- parserContext.m_suggestions.insert({commandNamesVisitor()(cmd), " "});
+ parserContext.m_suggestions.insert({commandNamesVisitor(cmd), " "});
});
}
};
diff --git a/src/ast_path.cpp b/src/ast_path.cpp
index b9b9b5a..1a26a1c 100644
--- a/src/ast_path.cpp
+++ b/src/ast_path.cpp
@@ -124,8 +124,7 @@
return this->m_nodes == b.m_nodes;
}
-
-struct nodeToSchemaStringVisitor : public boost::static_visitor<std::string> {
+struct nodeToSchemaStringVisitor {
std::string operator()(const nodeup_&) const
{
return "..";
@@ -148,7 +147,7 @@
}
}
-struct nodeToDataStringVisitor : public boost::static_visitor<std::string> {
+struct nodeToDataStringVisitor {
std::string operator()(const listElement_& node) const
{
std::ostringstream res;
@@ -176,7 +175,7 @@
std::string nodeToSchemaString(decltype(dataPath_::m_nodes)::value_type node)
{
- return boost::apply_visitor(nodeToSchemaStringVisitor(), node.m_suffix);
+ return std::visit(nodeToSchemaStringVisitor(), node.m_suffix);
}
std::string pathToDataString(const dataPath_& path, Prefixes prefixes)
@@ -188,9 +187,9 @@
for (const auto& it : path.m_nodes) {
if (it.m_prefix)
- res = joinPaths(res, it.m_prefix.value().m_name + ":" + boost::apply_visitor(nodeToDataStringVisitor(), it.m_suffix));
+ res = joinPaths(res, it.m_prefix.value().m_name + ":" + std::visit(nodeToDataStringVisitor(), it.m_suffix));
else
- res = joinPaths(res, (prefixes == Prefixes::Always ? path.m_nodes.at(0).m_prefix.value().m_name + ":" : "") + boost::apply_visitor(nodeToDataStringVisitor(), it.m_suffix));
+ res = joinPaths(res, (prefixes == Prefixes::Always ? path.m_nodes.at(0).m_prefix.value().m_name + ":" : "") + std::visit(nodeToDataStringVisitor(), it.m_suffix));
}
return res;
@@ -205,9 +204,9 @@
for (const auto& it : path.m_nodes) {
if (it.m_prefix)
- res = joinPaths(res, it.m_prefix.value().m_name + ":" + boost::apply_visitor(nodeToSchemaStringVisitor(), it.m_suffix));
+ res = joinPaths(res, it.m_prefix.value().m_name + ":" + std::visit(nodeToSchemaStringVisitor(), it.m_suffix));
else
- res = joinPaths(res, (prefixes == Prefixes::Always ? path.m_nodes.at(0).m_prefix.value().m_name + ":" : "") + boost::apply_visitor(nodeToSchemaStringVisitor(), it.m_suffix));
+ res = joinPaths(res, (prefixes == Prefixes::Always ? path.m_nodes.at(0).m_prefix.value().m_name + ":" : "") + std::visit(nodeToSchemaStringVisitor(), it.m_suffix));
}
return res;
}
@@ -217,19 +216,20 @@
return pathToSchemaString(dataPathToSchemaPath(path), prefixes);
}
-struct dataSuffixToSchemaSuffix : boost::static_visitor<decltype(schemaNode_::m_suffix)> {
- auto operator()(const listElement_& listElement) const
+struct dataSuffixToSchemaSuffix {
+ using ReturnType = decltype(schemaNode_::m_suffix);
+ ReturnType operator()(const listElement_& listElement) const
{
return list_{listElement.m_name};
}
- auto operator()(const leafListElement_& leafListElement) const
+ ReturnType operator()(const leafListElement_& leafListElement) const
{
return leafList_{leafListElement.m_name};
}
template <typename T>
- auto operator()(const T& suffix) const
+ ReturnType operator()(const T& suffix) const
{
return suffix;
}
@@ -239,7 +239,7 @@
{
schemaNode_ res;
res.m_prefix = node.m_prefix;
- res.m_suffix = boost::apply_visitor(dataSuffixToSchemaSuffix(), node.m_suffix);
+ res.m_suffix = std::visit(dataSuffixToSchemaSuffix(), node.m_suffix);
return res;
}
diff --git a/src/ast_path.hpp b/src/ast_path.hpp
index f768461..b1b949c 100644
--- a/src/ast_path.hpp
+++ b/src/ast_path.hpp
@@ -10,8 +10,8 @@
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/std_pair.hpp>
-#include <boost/variant/variant.hpp>
#include <map>
+#include <variant>
#include <vector>
#include "ast_values.hpp"
@@ -83,7 +83,7 @@
struct schemaNode_ {
boost::optional<module_> m_prefix;
- boost::variant<container_, list_, nodeup_, leaf_, leafList_> m_suffix;
+ std::variant<container_, list_, nodeup_, leaf_, leafList_> m_suffix;
schemaNode_();
schemaNode_(decltype(m_suffix) node);
@@ -93,7 +93,7 @@
struct dataNode_ {
boost::optional<module_> m_prefix;
- boost::variant<container_, listElement_, nodeup_, leaf_, leafListElement_, leafList_, list_> m_suffix;
+ std::variant<container_, listElement_, nodeup_, leaf_, leafListElement_, leafList_, list_> m_suffix;
dataNode_();
dataNode_(decltype(m_suffix) node);
diff --git a/src/grammars.hpp b/src/grammars.hpp
index 02d6666..253a16a 100644
--- a/src/grammars.hpp
+++ b/src/grammars.hpp
@@ -74,7 +74,7 @@
command_names_table()
{
boost::mpl::for_each<CommandTypes, boost::type<boost::mpl::_>>([this](auto cmd) {
- add(commandNamesVisitor()(cmd), decltype(help_::m_cmd)(cmd));
+ add(commandNamesVisitor(cmd), decltype(help_::m_cmd)(cmd));
});
}
} const command_names;
diff --git a/src/interpreter.cpp b/src/interpreter.cpp
index 909d863..2d69e63 100644
--- a/src/interpreter.cpp
+++ b/src/interpreter.cpp
@@ -65,9 +65,9 @@
void Interpreter::operator()(const create_& create) const
{
- if (create.m_path.m_nodes.back().m_suffix.type() == typeid(listElement_))
+ if (std::holds_alternative<listElement_>(create.m_path.m_nodes.back().m_suffix))
m_datastore.createListInstance(absolutePathFromCommand(create));
- else if (create.m_path.m_nodes.back().m_suffix.type() == typeid(leafListElement_))
+ else if (std::holds_alternative<leafListElement_>(create.m_path.m_nodes.back().m_suffix))
m_datastore.createLeafListInstance(absolutePathFromCommand(create));
else
m_datastore.createPresenceContainer(absolutePathFromCommand(create));
@@ -75,9 +75,9 @@
void Interpreter::operator()(const delete_& delet) const
{
- if (delet.m_path.m_nodes.back().m_suffix.type() == typeid(container_))
+ if (std::holds_alternative<container_>(delet.m_path.m_nodes.back().m_suffix))
m_datastore.deletePresenceContainer(absolutePathFromCommand(delet));
- else if (delet.m_path.m_nodes.back().m_suffix.type() == typeid(leafListElement_))
+ else if (std::holds_alternative<leafListElement_>(delet.m_path.m_nodes.back().m_suffix))
m_datastore.deleteLeafListInstance(absolutePathFromCommand(delet));
else
m_datastore.deleteListInstance(absolutePathFromCommand(delet));
@@ -231,6 +231,11 @@
}
struct pathToStringVisitor : boost::static_visitor<std::string> {
+ std::string operator()(const module_& path) const
+ {
+ using namespace std::string_literals;
+ return "/"s + boost::get<module_>(path).m_name + ":*";
+ }
std::string operator()(const schemaPath_& path) const
{
return pathToSchemaString(path, Prefixes::WhenNeeded);
@@ -242,6 +247,11 @@
};
struct getPathScopeVisitor : boost::static_visitor<Scope> {
+ Scope operator()(const module_&) const
+ {
+ throw std::logic_error("Interpreter: a top-level module has no scope.");
+ }
+
template <typename T>
Scope operator()(const T& path) const
{
@@ -258,11 +268,10 @@
const auto path = *get.m_path;
if (path.type() == typeid(module_)) {
- return "/"s + boost::get<module_>(path).m_name + ":*";
+ return boost::apply_visitor(pathToStringVisitor(), path);
} else {
- auto actualPath = boost::get<boost::variant<dataPath_, schemaPath_>>(path);
- std::string pathString = boost::apply_visitor(pathToStringVisitor(), actualPath);
- auto pathScope{boost::apply_visitor(getPathScopeVisitor(), actualPath)};
+ std::string pathString = boost::apply_visitor(pathToStringVisitor(), path);
+ auto pathScope{boost::apply_visitor(getPathScopeVisitor(), path)};
if (pathScope == Scope::Absolute) {
return pathString;
diff --git a/src/parser.cpp b/src/parser.cpp
index 2942d56..195789b 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -88,7 +88,7 @@
m_curDir = name;
} else {
for (const auto& it : name.m_nodes) {
- if (it.m_suffix.type() == typeid(nodeup_))
+ if (std::holds_alternative<nodeup_>(it.m_suffix))
m_curDir.m_nodes.pop_back();
else
m_curDir.m_nodes.push_back(it);
diff --git a/src/parser_context.cpp b/src/parser_context.cpp
index 26e6fa3..6b15cb9 100644
--- a/src/parser_context.cpp
+++ b/src/parser_context.cpp
@@ -43,7 +43,7 @@
void ParserContext::pushPathFragment(const dataNode_& node)
{
auto pushNode = [this] (auto& where, const auto& what) {
- if (what.m_suffix.type() == typeid(nodeup_)) {
+ if (std::holds_alternative<nodeup_>(what.m_suffix)) {
where.m_nodes.pop_back();
if (where.m_nodes.empty()) {
m_topLevelModulePresent = false;
diff --git a/src/path_parser.hpp b/src/path_parser.hpp
index ecd3bd7..bb622ef 100644
--- a/src/path_parser.hpp
+++ b/src/path_parser.hpp
@@ -58,9 +58,13 @@
using type = dataNode_;
};
+enum class CompletionMode {
+ Schema,
+ Data
+};
-template <NodeParserMode PARSER_MODE>
-struct NodeParser : x3::parser<NodeParser<PARSER_MODE>> {
+template <NodeParserMode PARSER_MODE, CompletionMode COMPLETION_MODE>
+struct NodeParser : x3::parser<NodeParser<PARSER_MODE, COMPLETION_MODE>> {
using attribute_type = typename ModeToAttribute<PARSER_MODE>::type;
std::function<bool(const Schema&, const std::string& path)> m_filterFunction;
@@ -114,7 +118,12 @@
} else {
out.m_suffix = listElement_{child.second, {}};
}
- parserContext.m_suggestions.emplace(Completion{parseString, "[", Completion::WhenToAdd::IfFullMatch});
+
+ if constexpr (COMPLETION_MODE == CompletionMode::Schema) {
+ parserContext.m_suggestions.emplace(Completion{parseString + "/"});
+ } else {
+ parserContext.m_suggestions.emplace(Completion{parseString, "[", Completion::WhenToAdd::IfFullMatch});
+ }
break;
case yang::NodeTypes::LeafList:
if constexpr (std::is_same<attribute_type, schemaNode_>()) {
@@ -122,7 +131,12 @@
} else {
out.m_suffix = leafListElement_{child.second, {}};
}
- parserContext.m_suggestions.emplace(Completion{parseString, "[", Completion::WhenToAdd::IfFullMatch});
+
+ if constexpr (COMPLETION_MODE == CompletionMode::Schema) {
+ parserContext.m_suggestions.emplace(Completion{parseString + "/"});
+ } else {
+ parserContext.m_suggestions.emplace(Completion{parseString, "[", Completion::WhenToAdd::IfFullMatch});
+ }
break;
case yang::NodeTypes::Action:
case yang::NodeTypes::AnyXml:
@@ -156,19 +170,19 @@
parserContext.m_curModule = attr.m_prefix->m_name;
}
- if (attr.m_suffix.type() == typeid(leaf_)) {
+ if (std::holds_alternative<leaf_>(attr.m_suffix)) {
parserContext.m_tmpListKeyLeafPath.m_location = parserContext.currentSchemaPath();
ModuleNodePair node{attr.m_prefix.flat_map([](const auto& it) {
return boost::optional<std::string>{it.m_name};
}),
- boost::get<leaf_>(attr.m_suffix).m_name};
+ std::get<leaf_>(attr.m_suffix).m_name};
parserContext.m_tmpListKeyLeafPath.m_node = node;
}
if constexpr (std::is_same<attribute_type, dataNode_>()) {
- if (attr.m_suffix.type() == typeid(listElement_)) {
- parserContext.m_tmpListName = boost::get<listElement_>(attr.m_suffix).m_name;
- res = listSuffix.parse(begin, end, ctx, rctx, boost::get<listElement_>(attr.m_suffix).m_keys);
+ if (std::holds_alternative<listElement_>(attr.m_suffix)) {
+ parserContext.m_tmpListName = std::get<listElement_>(attr.m_suffix).m_name;
+ res = listSuffix.parse(begin, end, ctx, rctx, std::get<listElement_>(attr.m_suffix).m_keys);
// FIXME: think of a better way to do this, that is, get rid of manual iterator reverting
if (!res) {
@@ -176,26 +190,26 @@
// If we don't, we fail the whole symbol table.
if constexpr (PARSER_MODE == NodeParserMode::IncompleteDataNode) {
res = true;
- attr.m_suffix = list_{boost::get<listElement_>(attr.m_suffix).m_name};
+ attr.m_suffix = list_{std::get<listElement_>(attr.m_suffix).m_name};
} else {
begin = saveIter;
}
}
}
- if (attr.m_suffix.type() == typeid(leafListElement_)) {
+ if (std::holds_alternative<leafListElement_>(attr.m_suffix)) {
parserContext.m_tmpListKeyLeafPath.m_location = parserContext.currentSchemaPath();
ModuleNodePair node{attr.m_prefix.flat_map([](const auto& it) {
return boost::optional<std::string>{it.m_name};
}),
- boost::get<leafListElement_>(attr.m_suffix).m_name};
+ std::get<leafListElement_>(attr.m_suffix).m_name};
parserContext.m_tmpListKeyLeafPath.m_node = node;
- res = leafListValue.parse(begin, end, ctx, rctx, boost::get<leafListElement_>(attr.m_suffix).m_value);
+ res = leafListValue.parse(begin, end, ctx, rctx, std::get<leafListElement_>(attr.m_suffix).m_value);
if (!res) {
if constexpr (PARSER_MODE == NodeParserMode::IncompleteDataNode) {
res = true;
- attr.m_suffix = leafList_{boost::get<leafListElement_>(attr.m_suffix).m_name};
+ attr.m_suffix = leafList_{std::get<leafListElement_>(attr.m_suffix).m_name};
} else {
begin = saveIter;
}
@@ -216,10 +230,10 @@
}
};
-using schemaNode = NodeParser<NodeParserMode::SchemaNode>;
-using dataNode = NodeParser<NodeParserMode::CompleteDataNode>;
-using incompleteDataNode = NodeParser<NodeParserMode::IncompleteDataNode>;
-using pathCompletions = NodeParser<NodeParserMode::CompletionsOnly>;
+template <CompletionMode COMPLETION_MODE> using schemaNode = NodeParser<NodeParserMode::SchemaNode, COMPLETION_MODE>;
+template <CompletionMode COMPLETION_MODE> using dataNode = NodeParser<NodeParserMode::CompleteDataNode, COMPLETION_MODE>;
+template <CompletionMode COMPLETION_MODE> using incompleteDataNode = NodeParser<NodeParserMode::IncompleteDataNode, COMPLETION_MODE>;
+template <CompletionMode COMPLETION_MODE> using pathCompletions = NodeParser<NodeParserMode::CompletionsOnly, COMPLETION_MODE>;
using AnyPath = boost::variant<schemaPath_, dataPath_>;
@@ -244,8 +258,8 @@
using type = dataPath_;
};
-template <PathParserMode PARSER_MODE>
-struct PathParser : x3::parser<PathParser<PARSER_MODE>> {
+template <PathParserMode PARSER_MODE, CompletionMode COMPLETION_MODE>
+struct PathParser : x3::parser<PathParser<PARSER_MODE, COMPLETION_MODE>> {
using attribute_type = ModeToAttribute<PARSER_MODE>;
std::function<bool(const Schema&, const std::string& path)> m_filterFunction;
@@ -266,7 +280,7 @@
// gets reverted to before the starting slash.
auto res = (-absoluteStart).parse(begin, end, ctx, rctx, attrData.m_scope);
auto dataPath = x3::attr(attrData.m_scope)
- >> (dataNode{m_filterFunction} % '/' | pathEnd >> x3::attr(std::vector<dataNode_>{}))
+ >> (dataNode<COMPLETION_MODE>{m_filterFunction} % '/' | pathEnd >> x3::attr(std::vector<dataNode_>{}))
>> -trailingSlash;
res = dataPath.parse(begin, end, ctx, rctx, attrData);
@@ -274,13 +288,13 @@
if constexpr (PARSER_MODE == PathParserMode::DataPathListEnd || PARSER_MODE == PathParserMode::AnyPath) {
if (!res || !pathEnd.parse(begin, end, ctx, rctx, x3::unused)) {
dataNode_ attrNodeList;
- res = incompleteDataNode{m_filterFunction}.parse(begin, end, ctx, rctx, attrNodeList);
+ res = incompleteDataNode<COMPLETION_MODE>{m_filterFunction}.parse(begin, end, ctx, rctx, attrNodeList);
if (res) {
attrData.m_nodes.push_back(attrNodeList);
// If the trailing slash matches, no more nodes are parsed.
// That means no more completion. So, I generate them
// manually.
- res = (-(trailingSlash >> x3::omit[pathCompletions{m_filterFunction}])).parse(begin, end, ctx, rctx, attrData.m_trailingSlash);
+ res = (-(trailingSlash >> x3::omit[pathCompletions<COMPLETION_MODE>{m_filterFunction}])).parse(begin, end, ctx, rctx, attrData.m_trailingSlash);
}
}
}
@@ -289,13 +303,13 @@
if constexpr (PARSER_MODE == PathParserMode::AnyPath) {
// If our data path already has some listElement_ fragments, we can't parse rest of the path as a schema path
auto hasLists = std::any_of(attrData.m_nodes.begin(), attrData.m_nodes.end(),
- [] (const auto& node) { return node.m_suffix.type() == typeid(listElement_); });
+ [] (const auto& node) { return std::holds_alternative<listElement_>(node.m_suffix); });
// If parsing failed, or if there's more input we try parsing schema nodes.
if (!hasLists) {
if (!res || !pathEnd.parse(begin, end, ctx, rctx, x3::unused)) {
// If dataPath parsed some nodes, they will be saved in `attrData`. We have to keep these.
schemaPath_ attrSchema = dataPathToSchemaPath(attrData);
- auto schemaPath = schemaNode{m_filterFunction} % '/';
+ auto schemaPath = schemaNode<COMPLETION_MODE>{m_filterFunction} % '/';
// The schemaPath parser continues where the dataPath parser ended.
res = schemaPath.parse(begin, end, ctx, rctx, attrSchema.m_nodes);
auto trailing = -trailingSlash >> pathEnd;
@@ -315,9 +329,9 @@
// The PathParser class would get a boost::variant as the attribute, but I
// don't want to deal with that, so I use these wrappers to ensure the
// attribute I want (and let Spirit deal with boost::variant).
-auto const anyPath = x3::rule<class anyPath_class, AnyPath>{"anyPath"} = PathParser<PathParserMode::AnyPath>{};
-auto const dataPath = x3::rule<class dataPath_class, dataPath_>{"dataPath"} = PathParser<PathParserMode::DataPath>{};
-auto const dataPathListEnd = x3::rule<class dataPath_class, dataPath_>{"dataPath"} = PathParser<PathParserMode::DataPathListEnd>{};
+auto const anyPath = x3::rule<class anyPath_class, AnyPath>{"anyPath"} = PathParser<PathParserMode::AnyPath, CompletionMode::Schema>{};
+auto const dataPath = x3::rule<class dataPath_class, dataPath_>{"dataPath"} = PathParser<PathParserMode::DataPath, CompletionMode::Data>{};
+auto const dataPathListEnd = x3::rule<class dataPath_class, dataPath_>{"dataPath"} = PathParser<PathParserMode::DataPathListEnd, CompletionMode::Data>{};
#if __clang__
#pragma GCC diagnostic push
@@ -381,7 +395,7 @@
};
auto const writableLeafPath_def =
- PathParser<PathParserMode::DataPath>{filterConfigFalse};
+ PathParser<PathParserMode::DataPath, CompletionMode::Data>{filterConfigFalse};
auto const presenceContainerPath_def =
dataPath;
diff --git a/src/static_schema.cpp b/src/static_schema.cpp
index a1a5602..5fdc42a 100644
--- a/src/static_schema.cpp
+++ b/src/static_schema.cpp
@@ -20,15 +20,6 @@
return m_nodes.at(name);
}
-bool StaticSchema::nodeExists(const std::string& location, const std::string& node) const
-{
- if (node.empty())
- return true;
- const auto& childrenRef = children(location);
-
- return childrenRef.find(node) != childrenRef.end();
-}
-
bool StaticSchema::isModule(const std::string& name) const
{
return m_modules.find(name) != m_modules.end();
diff --git a/src/static_schema.hpp b/src/static_schema.hpp
index aab4383..0426f02 100644
--- a/src/static_schema.hpp
+++ b/src/static_schema.hpp
@@ -89,7 +89,6 @@
private:
const std::unordered_map<std::string, NodeInfo>& children(const std::string& name) const;
void getIdentSet(const identityRef_& ident, std::set<identityRef_>& res) const;
- bool nodeExists(const std::string& location, const std::string& node) const;
std::unordered_map<std::string, std::unordered_map<std::string, NodeInfo>> m_nodes;
std::set<std::string> m_modules;
diff --git a/tests/path_completion.cpp b/tests/path_completion.cpp
index 71fc917..3002ed7 100644
--- a/tests/path_completion.cpp
+++ b/tests/path_completion.cpp
@@ -38,6 +38,7 @@
schema->addLeaf("/example:twoKeyList", "example:number", yang::Int32{});
schema->addLeaf("/", "example:leafInt", yang::Int32{});
schema->addLeaf("/", "example:readonly", yang::Int32{}, yang::AccessType::ReadOnly);
+ schema->addLeafList("/", "example:addresses", yang::String{});
auto mockDatastore = std::make_shared<MockDatastoreAccess>();
// The parser will use DataQuery for key value completion, but I'm not testing that here, so I don't return anything.
@@ -67,14 +68,14 @@
SECTION("ls ")
{
input = "ls ";
- expectedCompletions = {"example:ano/", "example:anoda/", "example:bota/", "example:leafInt ", "example:list", "example:ovoce", "example:readonly ", "example:ovocezelenina", "example:twoKeyList", "second:amelie/"};
+ expectedCompletions = {"example:addresses/", "example:ano/", "example:anoda/", "example:bota/", "example:leafInt ", "example:list/", "example:ovoce/", "example:readonly ", "example:ovocezelenina/", "example:twoKeyList/", "second:amelie/"};
expectedContextLength = 0;
}
SECTION("ls e")
{
input = "ls e";
- expectedCompletions = {"example:ano/", "example:anoda/", "example:bota/", "example:leafInt ", "example:list", "example:ovoce", "example:readonly ", "example:ovocezelenina", "example:twoKeyList"};
+ expectedCompletions = {"example:addresses/", "example:ano/", "example:anoda/", "example:bota/", "example:leafInt ", "example:list/", "example:ovoce/", "example:readonly ", "example:ovocezelenina/", "example:twoKeyList/"};
expectedContextLength = 1;
}
@@ -102,14 +103,14 @@
SECTION("ls /")
{
input = "ls /";
- expectedCompletions = {"example:ano/", "example:anoda/", "example:bota/", "example:leafInt ", "example:list", "example:ovoce", "example:readonly ", "example:ovocezelenina", "example:twoKeyList", "second:amelie/"};
+ expectedCompletions = {"example:addresses/", "example:ano/", "example:anoda/", "example:bota/", "example:leafInt ", "example:list/", "example:ovoce/", "example:readonly ", "example:ovocezelenina/", "example:twoKeyList/", "second:amelie/"};
expectedContextLength = 0;
}
SECTION("ls /e")
{
input = "ls /e";
- expectedCompletions = {"example:ano/", "example:anoda/", "example:bota/", "example:leafInt ", "example:list", "example:ovoce", "example:readonly ", "example:ovocezelenina", "example:twoKeyList"};
+ expectedCompletions = {"example:addresses/", "example:ano/", "example:anoda/", "example:bota/", "example:leafInt ", "example:list/", "example:ovoce/", "example:readonly ", "example:ovocezelenina/", "example:twoKeyList/"};
expectedContextLength = 1;
}
@@ -134,6 +135,13 @@
expectedContextLength = 1;
}
+ SECTION("ls /example:list")
+ {
+ input = "ls /example:list";
+ expectedCompletions = {"example:list/"};
+ expectedContextLength = 12;
+ }
+
SECTION("ls /example:list/")
{
input = "ls /example:list/";