From f0f56a6910dbaa2fbb8f48b29e8d4be01511a8d5 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 13 Jan 2018 16:43:12 -0800 Subject: [PATCH] Teach decoration_for_plain_statement about tnode, rename it get_decoration --- src/complete.cpp | 2 +- src/fish_tests.cpp | 2 +- src/highlight.cpp | 18 ++++++++---------- src/history.cpp | 6 ++---- src/parse_execution.cpp | 8 +++----- src/parse_tree.cpp | 9 +++------ src/parse_tree.h | 11 ++++++----- src/parse_util.cpp | 2 +- src/reader.cpp | 12 ++++-------- 9 files changed, 29 insertions(+), 41 deletions(-) diff --git a/src/complete.cpp b/src/complete.cpp index 08b3f0e4e..5060e1ed1 100644 --- a/src/complete.cpp +++ b/src/complete.cpp @@ -1336,7 +1336,7 @@ void complete(const wcstring &cmd_with_subcmds, std::vector *out_c current_command = cmd_node.get_source(cmd); // Check the decoration. - switch (tree.decoration_for_plain_statement(*plain_statement)) { + switch (get_decoration(plain_statement)) { case parse_statement_decoration_none: { use_command = true; use_function = true; diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index a80883bb3..6ce192837 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -3402,7 +3402,7 @@ static bool test_1_parse_ll2(const wcstring &src, wcstring *out_cmd, wcstring *o tnode_t stmt = stmts.at(0); // Return its decoration and command. - *out_deco = tree.decoration_for_plain_statement(stmt); + *out_deco = get_decoration(stmt); *out_cmd = *command_for_plain_statement(stmt, src); // Return arguments separated by spaces. diff --git a/src/highlight.cpp b/src/highlight.cpp index 944098b0a..9c016f7b1 100644 --- a/src/highlight.cpp +++ b/src/highlight.cpp @@ -1071,14 +1071,14 @@ const highlighter_t::color_array_t &highlighter_t::highlight() { break; } case symbol_plain_statement: { + tnode_t stmt(&parse_tree, &node); // Get the decoration from the parent. - enum parse_statement_decoration_t decoration = - parse_tree.decoration_for_plain_statement(node); + enum parse_statement_decoration_t decoration = get_decoration(stmt); // Color the command. - const parse_node_t *cmd_node = - parse_tree.get_child(node, 0, parse_token_type_string); - if (cmd_node == NULL || !cmd_node->has_source()) { + tnode_t cmd_node = stmt.child<0>(); + maybe_t cmd = cmd_node.get_source(buff); + if (!cmd) { break; // not much as we can do without a node that has source text } @@ -1088,13 +1088,11 @@ const highlighter_t::color_array_t &highlighter_t::highlight() { is_valid_cmd = true; } else { // Check to see if the command is valid. - wcstring cmd(buff, cmd_node->source_start, cmd_node->source_length); - // Try expanding it. If we cannot, it's an error. bool expanded = expand_one( - cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES | EXPAND_SKIP_JOBS); - if (expanded && !has_expand_reserved(cmd)) { - is_valid_cmd = command_is_valid(cmd, decoration, working_directory, vars); + *cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES | EXPAND_SKIP_JOBS); + if (expanded && !has_expand_reserved(*cmd)) { + is_valid_cmd = command_is_valid(*cmd, decoration, working_directory, vars); } } this->color_node(*cmd_node, diff --git a/src/history.cpp b/src/history.cpp index 38649343e..37af02161 100644 --- a/src/history.cpp +++ b/src/history.cpp @@ -1892,11 +1892,9 @@ void history_t::add_pending_with_file_detection(const wcstring &str) { bool impending_exit = false; parse_node_tree_t tree; parse_tree_from_string(str, parse_flag_none, &tree, NULL); - size_t count = tree.size(); path_list_t potential_paths; - for (size_t i = 0; i < count; i++) { - const parse_node_t &node = tree.at(i); + for (const parse_node_t &node : tree) { if (!node.has_source()) { continue; } @@ -1911,7 +1909,7 @@ void history_t::add_pending_with_file_detection(const wcstring &str) { // Hack hack hack - if the command is likely to trigger an exit, then don't do // background file detection, because we won't be able to write it to our history file // before we exit. - if (tree.decoration_for_plain_statement(node) == parse_statement_decoration_exec) { + if (get_decoration({&tree, &node}) == parse_statement_decoration_exec) { impending_exit = true; } diff --git a/src/parse_execution.cpp b/src/parse_execution.cpp index e2a86851b..407269a4d 100644 --- a/src/parse_execution.cpp +++ b/src/parse_execution.cpp @@ -148,8 +148,7 @@ parse_execution_context_t::infinite_recursive_statement_in_job_list(const parse_ tnode_t dec_statement(&tree(), &statement); auto plain_statement = tree().find_child(dec_statement); - if (tree().decoration_for_plain_statement(plain_statement) != - parse_statement_decoration_none) { + if (get_decoration(plain_statement) != parse_statement_decoration_none) { // This statement has a decoration like 'builtin' or 'command', and therefore is not // infinite recursion. In particular this is what enables 'wrapper functions'. continue; @@ -177,8 +176,7 @@ enum process_type_t parse_execution_context_t::process_type_for_command( // Determine the process type, which depends on the statement decoration (command, builtin, // etc). - enum parse_statement_decoration_t decoration = - tree().decoration_for_plain_statement(plain_statement); + enum parse_statement_decoration_t decoration = get_decoration({&tree(), &plain_statement}); if (decoration == parse_statement_decoration_exec) { // Always exec. @@ -857,7 +855,7 @@ parse_execution_result_t parse_execution_context_t::populate_plain_process( // If the specified command does not exist, and is undecorated, try using an implicit cd. if (!has_command && - tree().decoration_for_plain_statement(statement) == parse_statement_decoration_none) { + get_decoration({&tree(), &statement}) == parse_statement_decoration_none) { // Implicit cd requires an empty argument and redirection list. const parse_node_t *args = get_child(statement, 1, symbol_arguments_or_redirections_list); diff --git a/src/parse_tree.cpp b/src/parse_tree.cpp index a44d2e9a2..f103b9060 100644 --- a/src/parse_tree.cpp +++ b/src/parse_tree.cpp @@ -1319,13 +1319,10 @@ bool parse_node_tree_t::argument_list_is_root(const parse_node_t &node) const { return result; } -enum parse_statement_decoration_t parse_node_tree_t::decoration_for_plain_statement( - const parse_node_t &node) const { - assert(node.type == symbol_plain_statement); +enum parse_statement_decoration_t get_decoration(tnode_t stmt) { parse_statement_decoration_t decoration = parse_statement_decoration_none; - const parse_node_t *decorated_statement = this->get_parent(node, symbol_decorated_statement); - if (decorated_statement) { - decoration = static_cast(decorated_statement->tag); + if (auto decorated_statement = stmt.try_get_parent()) { + decoration = static_cast(decorated_statement.tag()); } return decoration; } diff --git a/src/parse_tree.h b/src/parse_tree.h index b23125d06..5a8fb1edc 100644 --- a/src/parse_tree.h +++ b/src/parse_tree.h @@ -195,11 +195,6 @@ class parse_node_tree_t : public std::vector { // Utilities - /// Given a plain statement, get the decoration (from the parent node), or none if there is no - /// decoration. - enum parse_statement_decoration_t decoration_for_plain_statement( - const parse_node_t &node) const; - /// Given a plain statement, return true if the statement is part of a pipeline. If /// include_first is set, the first command in a pipeline is considered part of it; otherwise /// only the second or additional commands are. @@ -287,6 +282,9 @@ class tnode_t { bool has_source() const { return nodeptr && nodeptr->has_source(); } + // return the tag, or 0 if missing. + parse_node_tag_t tag() const { return nodeptr ? nodeptr->tag : 0; } + maybe_t source_range() const { if (!has_source()) return none(); return source_range_t{nodeptr->source_start, nodeptr->source_length}; @@ -385,6 +383,9 @@ std::vector> parse_node_tree_t::find_nodes(const parse_node_t &par maybe_t command_for_plain_statement(tnode_t stmt, const wcstring &src); +/// Return the decoration for a plain statement. +parse_statement_decoration_t get_decoration(tnode_t stmt); + /// The big entry point. Parse a string, attempting to produce a tree for the given goal type. bool parse_tree_from_string(const wcstring &str, parse_tree_flags_t flags, parse_node_tree_t *output, parse_error_list_t *errors, diff --git a/src/parse_util.cpp b/src/parse_util.cpp index d4334e027..9f46902ab 100644 --- a/src/parse_util.cpp +++ b/src/parse_util.cpp @@ -1174,7 +1174,7 @@ parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src, // We need to know the decoration. const enum parse_statement_decoration_t decoration = - node_tree.decoration_for_plain_statement(node); + get_decoration({&node_tree, &node}); // Check that we don't try to pipe through exec. if (is_in_pipeline && decoration == parse_statement_decoration_exec) { diff --git a/src/reader.cpp b/src/reader.cpp index efbcf7455..cc77f5ada 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -582,21 +582,17 @@ bool reader_expand_abbreviation_in_command(const wcstring &cmdline, size_t curso // Look for plain statements where the cursor is at the end of the command. using namespace grammar; tnode_t matching_cmd_node; - const size_t len = parse_tree.size(); - for (size_t i = 0; i < len; i++) { - const parse_node_t &node = parse_tree.at(i); - + for (const parse_node_t &node : parse_tree) { // Only interested in plain statements with source. if (node.type != symbol_plain_statement || !node.has_source()) continue; - // Skip decorated statements. - if (parse_tree.decoration_for_plain_statement(node) != parse_statement_decoration_none) - continue; - // Get the command node. Skip it if we can't or it has no source. tnode_t statement(&parse_tree, &node); tnode_t cmd_node = statement.child<0>(); + // Skip decorated statements. + if (get_decoration(statement) != parse_statement_decoration_none) continue; + auto msource = cmd_node.source_range(); if (!msource) continue;