tnode_t adoption of find_nodes

This commit is contained in:
ridiculousfish 2018-01-11 17:19:48 -08:00
parent 618996a166
commit 4d68877f51
3 changed files with 40 additions and 20 deletions

View File

@ -1294,9 +1294,9 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> *out_c
while (position_in_statement > 0 && cmd.at(position_in_statement - 1) == L' ') {
position_in_statement--;
}
auto plain_statement = tnode_t<grammar::plain_statement>{
&tree, tree.find_node_matching_source_location(symbol_plain_statement,
position_in_statement, NULL)};
auto plain_statement =
tnode_t<grammar::plain_statement>::find_node_matching_source_location(
&tree, position_in_statement, nullptr);
if (!plain_statement) {
// Not part of a plain statement. This could be e.g. a for loop header, case expression,
// etc. Do generic file completions (issue #1309). If we had to backtrack, it means
@ -1368,15 +1368,14 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> *out_c
use_implicit_cd);
} else {
// Get all the arguments.
const parse_node_tree_t::parse_node_list_t all_arguments =
tree.find_nodes(*plain_statement, symbol_argument);
auto all_arguments = tnode_t<grammar::argument>::find_nodes(&tree, plain_statement);
// See whether we are in an argument. We may also be in a redirection, or nothing at
// all.
size_t matching_arg_index = -1;
for (size_t i = 0; i < all_arguments.size(); i++) {
const parse_node_t *node = all_arguments.at(i);
if (node->location_in_or_at_end_of_source_range(position_in_statement)) {
tnode_t<grammar::argument> arg = all_arguments.at(i);
if (arg.location_in_or_at_end_of_source_range(position_in_statement)) {
matching_arg_index = i;
break;
}
@ -1386,7 +1385,7 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> *out_c
wcstring current_argument, previous_argument;
if (matching_arg_index != (size_t)(-1)) {
const wcstring matching_arg =
all_arguments.at(matching_arg_index)->get_source(cmd);
all_arguments.at(matching_arg_index).get_source(cmd);
// If the cursor is in whitespace, then the "current" argument is empty and the
// previous argument is the matching one. But if the cursor was in or at the end
@ -1401,13 +1400,13 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> *out_c
current_argument = matching_arg;
if (matching_arg_index > 0) {
previous_argument =
all_arguments.at(matching_arg_index - 1)->get_source(cmd);
all_arguments.at(matching_arg_index - 1).get_source(cmd);
}
}
// Check to see if we have a preceding double-dash.
for (size_t i = 0; i < matching_arg_index; i++) {
if (all_arguments.at(i)->get_source(cmd) == L"--") {
if (all_arguments.at(i).get_source(cmd) == L"--") {
had_ddash = true;
break;
}
@ -1417,9 +1416,10 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> *out_c
// If we are not in an argument, we may be in a redirection.
bool in_redirection = false;
if (matching_arg_index == (size_t)(-1)) {
const parse_node_t *redirection = tree.find_node_matching_source_location(
symbol_redirection, position_in_statement, plain_statement);
in_redirection = (redirection != NULL);
if (tnode_t<grammar::redirection>::find_node_matching_source_location(
&tree, position_in_statement, plain_statement)) {
in_redirection = true;
}
}
bool do_file = false, handle_as_special_cd = false;

View File

@ -3394,14 +3394,12 @@ static bool test_1_parse_ll2(const wcstring &src, wcstring *out_cmd, wcstring *o
}
// Get the statement. Should only have one.
const parse_node_tree_t::parse_node_list_t stmt_nodes =
tree.find_nodes(tree.at(0), symbol_plain_statement);
if (stmt_nodes.size() != 1) {
say(L"Unexpected number of statements (%lu) found in '%ls'", stmt_nodes.size(),
src.c_str());
auto stmts = tnode_t<grammar::plain_statement>::find_nodes(&tree, &tree.at(0));
if (stmts.size() != 1) {
say(L"Unexpected number of statements (%lu) found in '%ls'", stmts.size(), src.c_str());
return false;
}
const parse_node_t &stmt = *stmt_nodes.at(0);
tnode_t<grammar::plain_statement> stmt = stmts.at(0);
// Return its decoration.
*out_deco = tree.decoration_for_plain_statement(stmt);

View File

@ -166,7 +166,7 @@ class parse_node_tree_t : public std::vector<parse_node_t> {
// Find all the nodes of a given type underneath a given node, up to max_count of them.
typedef std::vector<const parse_node_t *> parse_node_list_t;
parse_node_list_t find_nodes(const parse_node_t &parent, parse_token_type_t type,
size_t max_count = (size_t)(-1)) const;
size_t max_count = size_t(-1)) const;
// Finds the last node of a given type underneath a given node, or NULL if it could not be
// found. If parent is NULL, this finds the last node in the tree of that type.
@ -286,6 +286,14 @@ class tnode_t {
return nodeptr && nodeptr->location_in_or_at_end_of_source_range(loc);
}
static tnode_t find_node_matching_source_location(const parse_node_tree_t *tree,
size_t source_loc,
const parse_node_t *parent) {
assert(tree && "null tree");
return tnode_t{tree,
tree->find_node_matching_source_location(Type::token, source_loc, parent)};
}
/// Type-safe access to a child at the given index.
template <node_offset_t Index>
tnode_t<child_at<Type, Index>> child() const {
@ -303,6 +311,20 @@ class tnode_t {
if (!nodeptr) return {};
return {tree, tree->get_parent(*nodeptr, ParentType::token)};
}
static std::vector<tnode_t> find_nodes(const parse_node_tree_t *tree,
const parse_node_t *parent,
size_t max_count = size_t(-1)) {
assert(tree && "null tree");
assert(parent && "null parent");
auto ptrs = tree->find_nodes(*parent, Type::token, max_count);
std::vector<tnode_t> result;
result.reserve(ptrs.size());
for (const parse_node_t *np : ptrs) {
result.emplace_back(tree, np);
}
return result;
}
};
/// The big entry point. Parse a string, attempting to produce a tree for the given goal type.