Teach decoration_for_plain_statement about tnode, rename it get_decoration

This commit is contained in:
ridiculousfish 2018-01-13 16:43:12 -08:00
parent 84dcb24682
commit f0f56a6910
9 changed files with 29 additions and 41 deletions

View file

@ -1336,7 +1336,7 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> *out_c
current_command = cmd_node.get_source(cmd); current_command = cmd_node.get_source(cmd);
// Check the decoration. // Check the decoration.
switch (tree.decoration_for_plain_statement(*plain_statement)) { switch (get_decoration(plain_statement)) {
case parse_statement_decoration_none: { case parse_statement_decoration_none: {
use_command = true; use_command = true;
use_function = true; use_function = true;

View file

@ -3402,7 +3402,7 @@ static bool test_1_parse_ll2(const wcstring &src, wcstring *out_cmd, wcstring *o
tnode_t<grammar::plain_statement> stmt = stmts.at(0); tnode_t<grammar::plain_statement> stmt = stmts.at(0);
// Return its decoration and command. // 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); *out_cmd = *command_for_plain_statement(stmt, src);
// Return arguments separated by spaces. // Return arguments separated by spaces.

View file

@ -1071,14 +1071,14 @@ const highlighter_t::color_array_t &highlighter_t::highlight() {
break; break;
} }
case symbol_plain_statement: { case symbol_plain_statement: {
tnode_t<g::plain_statement> stmt(&parse_tree, &node);
// Get the decoration from the parent. // Get the decoration from the parent.
enum parse_statement_decoration_t decoration = enum parse_statement_decoration_t decoration = get_decoration(stmt);
parse_tree.decoration_for_plain_statement(node);
// Color the command. // Color the command.
const parse_node_t *cmd_node = tnode_t<g::tok_string> cmd_node = stmt.child<0>();
parse_tree.get_child(node, 0, parse_token_type_string); maybe_t<wcstring> cmd = cmd_node.get_source(buff);
if (cmd_node == NULL || !cmd_node->has_source()) { if (!cmd) {
break; // not much as we can do without a node that has source text 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; is_valid_cmd = true;
} else { } else {
// Check to see if the command is valid. // 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. // Try expanding it. If we cannot, it's an error.
bool expanded = expand_one( bool expanded = expand_one(
cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES | EXPAND_SKIP_JOBS); *cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES | EXPAND_SKIP_JOBS);
if (expanded && !has_expand_reserved(cmd)) { if (expanded && !has_expand_reserved(*cmd)) {
is_valid_cmd = command_is_valid(cmd, decoration, working_directory, vars); is_valid_cmd = command_is_valid(*cmd, decoration, working_directory, vars);
} }
} }
this->color_node(*cmd_node, this->color_node(*cmd_node,

View file

@ -1892,11 +1892,9 @@ void history_t::add_pending_with_file_detection(const wcstring &str) {
bool impending_exit = false; bool impending_exit = false;
parse_node_tree_t tree; parse_node_tree_t tree;
parse_tree_from_string(str, parse_flag_none, &tree, NULL); parse_tree_from_string(str, parse_flag_none, &tree, NULL);
size_t count = tree.size();
path_list_t potential_paths; path_list_t potential_paths;
for (size_t i = 0; i < count; i++) { for (const parse_node_t &node : tree) {
const parse_node_t &node = tree.at(i);
if (!node.has_source()) { if (!node.has_source()) {
continue; 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 // 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 // background file detection, because we won't be able to write it to our history file
// before we exit. // 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; impending_exit = true;
} }

View file

@ -148,8 +148,7 @@ parse_execution_context_t::infinite_recursive_statement_in_job_list(const parse_
tnode_t<grammar::decorated_statement> dec_statement(&tree(), &statement); tnode_t<grammar::decorated_statement> dec_statement(&tree(), &statement);
auto plain_statement = tree().find_child<grammar::plain_statement>(dec_statement); auto plain_statement = tree().find_child<grammar::plain_statement>(dec_statement);
if (tree().decoration_for_plain_statement(plain_statement) != if (get_decoration(plain_statement) != parse_statement_decoration_none) {
parse_statement_decoration_none) {
// This statement has a decoration like 'builtin' or 'command', and therefore is not // This statement has a decoration like 'builtin' or 'command', and therefore is not
// infinite recursion. In particular this is what enables 'wrapper functions'. // infinite recursion. In particular this is what enables 'wrapper functions'.
continue; 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, // Determine the process type, which depends on the statement decoration (command, builtin,
// etc). // etc).
enum parse_statement_decoration_t decoration = enum parse_statement_decoration_t decoration = get_decoration({&tree(), &plain_statement});
tree().decoration_for_plain_statement(plain_statement);
if (decoration == parse_statement_decoration_exec) { if (decoration == parse_statement_decoration_exec) {
// Always 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 the specified command does not exist, and is undecorated, try using an implicit cd.
if (!has_command && 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. // Implicit cd requires an empty argument and redirection list.
const parse_node_t *args = const parse_node_t *args =
get_child(statement, 1, symbol_arguments_or_redirections_list); get_child(statement, 1, symbol_arguments_or_redirections_list);

View file

@ -1319,13 +1319,10 @@ bool parse_node_tree_t::argument_list_is_root(const parse_node_t &node) const {
return result; return result;
} }
enum parse_statement_decoration_t parse_node_tree_t::decoration_for_plain_statement( enum parse_statement_decoration_t get_decoration(tnode_t<grammar::plain_statement> stmt) {
const parse_node_t &node) const {
assert(node.type == symbol_plain_statement);
parse_statement_decoration_t decoration = parse_statement_decoration_none; parse_statement_decoration_t decoration = parse_statement_decoration_none;
const parse_node_t *decorated_statement = this->get_parent(node, symbol_decorated_statement); if (auto decorated_statement = stmt.try_get_parent<grammar::decorated_statement>()) {
if (decorated_statement) { decoration = static_cast<parse_statement_decoration_t>(decorated_statement.tag());
decoration = static_cast<parse_statement_decoration_t>(decorated_statement->tag);
} }
return decoration; return decoration;
} }

View file

@ -195,11 +195,6 @@ class parse_node_tree_t : public std::vector<parse_node_t> {
// Utilities // 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 /// 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 /// include_first is set, the first command in a pipeline is considered part of it; otherwise
/// only the second or additional commands are. /// only the second or additional commands are.
@ -287,6 +282,9 @@ class tnode_t {
bool has_source() const { return nodeptr && nodeptr->has_source(); } 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_t> source_range() const { maybe_t<source_range_t> source_range() const {
if (!has_source()) return none(); if (!has_source()) return none();
return source_range_t{nodeptr->source_start, nodeptr->source_length}; return source_range_t{nodeptr->source_start, nodeptr->source_length};
@ -385,6 +383,9 @@ std::vector<tnode_t<Type>> parse_node_tree_t::find_nodes(const parse_node_t &par
maybe_t<wcstring> command_for_plain_statement(tnode_t<grammar::plain_statement> stmt, maybe_t<wcstring> command_for_plain_statement(tnode_t<grammar::plain_statement> stmt,
const wcstring &src); const wcstring &src);
/// Return the decoration for a plain statement.
parse_statement_decoration_t get_decoration(tnode_t<grammar::plain_statement> stmt);
/// The big entry point. Parse a string, attempting to produce a tree for the given goal type. /// 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, bool parse_tree_from_string(const wcstring &str, parse_tree_flags_t flags,
parse_node_tree_t *output, parse_error_list_t *errors, parse_node_tree_t *output, parse_error_list_t *errors,

View file

@ -1174,7 +1174,7 @@ parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src,
// We need to know the decoration. // We need to know the decoration.
const enum parse_statement_decoration_t 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. // Check that we don't try to pipe through exec.
if (is_in_pipeline && decoration == parse_statement_decoration_exec) { if (is_in_pipeline && decoration == parse_statement_decoration_exec) {

View file

@ -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. // Look for plain statements where the cursor is at the end of the command.
using namespace grammar; using namespace grammar;
tnode_t<tok_string> matching_cmd_node; tnode_t<tok_string> matching_cmd_node;
const size_t len = parse_tree.size(); for (const parse_node_t &node : parse_tree) {
for (size_t i = 0; i < len; i++) {
const parse_node_t &node = parse_tree.at(i);
// Only interested in plain statements with source. // Only interested in plain statements with source.
if (node.type != symbol_plain_statement || !node.has_source()) continue; 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. // Get the command node. Skip it if we can't or it has no source.
tnode_t<plain_statement> statement(&parse_tree, &node); tnode_t<plain_statement> statement(&parse_tree, &node);
tnode_t<tok_string> cmd_node = statement.child<0>(); tnode_t<tok_string> cmd_node = statement.child<0>();
// Skip decorated statements.
if (get_decoration(statement) != parse_statement_decoration_none) continue;
auto msource = cmd_node.source_range(); auto msource = cmd_node.source_range();
if (!msource) continue; if (!msource) continue;