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);
// 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;

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);
// 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.

View file

@ -1071,14 +1071,14 @@ const highlighter_t::color_array_t &highlighter_t::highlight() {
break;
}
case symbol_plain_statement: {
tnode_t<g::plain_statement> 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<g::tok_string> cmd_node = stmt.child<0>();
maybe_t<wcstring> 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,

View file

@ -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;
}

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);
auto plain_statement = tree().find_child<grammar::plain_statement>(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);

View file

@ -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<grammar::plain_statement> 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<parse_statement_decoration_t>(decorated_statement->tag);
if (auto decorated_statement = stmt.try_get_parent<grammar::decorated_statement>()) {
decoration = static_cast<parse_statement_decoration_t>(decorated_statement.tag());
}
return decoration;
}

View file

@ -195,11 +195,6 @@ class parse_node_tree_t : public std::vector<parse_node_t> {
// 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_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<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,
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.
bool parse_tree_from_string(const wcstring &str, parse_tree_flags_t flags,
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.
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) {

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.
using namespace grammar;
tnode_t<tok_string> 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<plain_statement> statement(&parse_tree, &node);
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();
if (!msource) continue;