Factor block description part of stack traces into a new function

This commit is contained in:
ridiculousfish 2019-12-22 16:22:20 -08:00
parent a59f35a378
commit 0c49dce75d
2 changed files with 82 additions and 75 deletions

View file

@ -76,8 +76,8 @@ class io_chain_t;
#define UNKNOWN_BLOCK N_(L"unknown/invalid block") #define UNKNOWN_BLOCK N_(L"unknown/invalid block")
// Given a file path, return something nicer. Currently we just "unexpand" tildes. // Given a file path, return something nicer. Currently we just "unexpand" tildes.
wcstring parser_t::user_presentable_path(const wcstring &path) const { static wcstring user_presentable_path(const wcstring &path, const environment_t &vars) {
return replace_home_directory_with_tilde(path, vars()); return replace_home_directory_with_tilde(path, vars);
} }
parser_t::parser_t(std::shared_ptr<env_stack_t> vars) : variables(std::move(vars)) { parser_t::parser_t(std::shared_ptr<env_stack_t> vars) : variables(std::move(vars)) {
@ -334,34 +334,11 @@ std::vector<completion_t> parser_t::expand_argument_list(const wcstring &arg_lis
std::shared_ptr<parser_t> parser_t::shared() { return shared_from_this(); } std::shared_ptr<parser_t> parser_t::shared() { return shared_from_this(); }
wcstring parser_t::stack_trace() const { /// Append stack trace info for the block \p b to \p trace.
wcstring trace; static void append_block_description_to_stack_trace(const block_t &b, wcstring &trace,
for (const auto &b : blocks()) { const environment_t &vars) {
if (b.type() == block_type_t::event) { bool print_call_site = false;
// This is an event handler.
assert(b.event && "Should have an event");
wcstring description = event_get_desc(*b.event);
append_format(trace, _(L"in event handler: %ls\n"), description.c_str());
// Stop at event handler. No reason to believe that any other code is relevant.
//
// It might make sense in the future to continue printing the stack trace of the code
// that invoked the event, if this is a programmatic event, but we can't currently
// detect that.
break;
}
if (b.type() == block_type_t::function_call ||
b.type() == block_type_t::function_call_no_shadow || b.type() == block_type_t::source ||
b.type() == block_type_t::subst) {
// These types of blocks should be printed.
switch (b.type()) { switch (b.type()) {
case block_type_t::source: {
const wchar_t *source_dest = b.sourced_file;
append_format(trace, _(L"from sourcing file %ls\n"),
user_presentable_path(source_dest).c_str());
break;
}
case block_type_t::function_call: case block_type_t::function_call:
case block_type_t::function_call_no_shadow: { case block_type_t::function_call_no_shadow: {
append_format(trace, _(L"in function '%ls'"), b.function_name.c_str()); append_format(trace, _(L"in function '%ls'"), b.function_name.c_str());
@ -382,32 +359,64 @@ wcstring parser_t::stack_trace() const {
append_format(trace, _(L" with arguments '%ls'"), args_str.c_str()); append_format(trace, _(L" with arguments '%ls'"), args_str.c_str());
} }
trace.push_back('\n'); trace.push_back('\n');
print_call_site = true;
break; break;
} }
case block_type_t::subst: { case block_type_t::subst: {
append_format(trace, _(L"in command substitution\n")); append_format(trace, _(L"in command substitution\n"));
print_call_site = true;
break; break;
} }
default: { case block_type_t::source: {
break; // can't get here const wchar_t *source_dest = b.sourced_file;
append_format(trace, _(L"from sourcing file %ls\n"),
user_presentable_path(source_dest, vars).c_str());
print_call_site = true;
break;
} }
case block_type_t::event: {
assert(b.event && "Should have an event");
wcstring description = event_get_desc(*b.event);
append_format(trace, _(L"in event handler: %ls\n"), description.c_str());
print_call_site = true;
break;
} }
case block_type_t::top:
case block_type_t::begin:
case block_type_t::switch_block:
case block_type_t::while_block:
case block_type_t::for_block:
case block_type_t::if_block:
case block_type_t::breakpoint:
case block_type_t::variable_assignment:
break;
}
if (print_call_site) {
// Print where the function is called. // Print where the function is called.
const wchar_t *file = b.src_filename; const wchar_t *file = b.src_filename;
if (file) { if (file) {
append_format(trace, _(L"\tcalled on line %d of file %ls\n"), b.src_lineno, append_format(trace, _(L"\tcalled on line %d of file %ls\n"), b.src_lineno,
user_presentable_path(file).c_str()); user_presentable_path(file, vars).c_str());
} else if (is_within_fish_initialization()) { } else if (is_within_fish_initialization()) {
append_format(trace, _(L"\tcalled during startup\n")); append_format(trace, _(L"\tcalled during startup\n"));
} else {
// This one is way too noisy
// append_format(*buff, _(L"\tcalled on standard input\n"));
}
} }
} }
}
wcstring parser_t::stack_trace() const {
wcstring trace;
for (const auto &b : blocks()) {
append_block_description_to_stack_trace(b, trace, vars());
// Stop at event handler. No reason to believe that any other code is relevant.
//
// It might make sense in the future to continue printing the stack trace of the code
// that invoked the event, if this is a programmatic event, but we can't currently
// detect that.
if (b.type() == block_type_t::event) break;
}
return trace; return trace;
} }
@ -520,8 +529,8 @@ wcstring parser_t::current_line() {
// If we are not going to print a stack trace, at least print the line number and filename. // If we are not going to print a stack trace, at least print the line number and filename.
if (!is_interactive() || is_function()) { if (!is_interactive() || is_function()) {
if (file) { if (file) {
append_format(prefix, _(L"%ls (line %d): "), user_presentable_path(file).c_str(), append_format(prefix, _(L"%ls (line %d): "),
lineno); user_presentable_path(file, vars()).c_str(), lineno);
} else if (is_within_fish_initialization()) { } else if (is_within_fish_initialization()) {
append_format(prefix, L"%ls (line %d): ", _(L"Startup"), lineno); append_format(prefix, L"%ls (line %d): ", _(L"Startup"), lineno);
} else { } else {
@ -703,9 +712,10 @@ void parser_t::get_backtrace(const wcstring &src, const parse_error_list_t &erro
if (filename) { if (filename) {
if (which_line > 0) { if (which_line > 0) {
prefix = format_string(_(L"%ls (line %lu): "), prefix = format_string(_(L"%ls (line %lu): "),
user_presentable_path(filename).c_str(), which_line); user_presentable_path(filename, vars()).c_str(), which_line);
} else { } else {
prefix = format_string(_(L"%ls: "), user_presentable_path(filename).c_str()); prefix =
format_string(_(L"%ls: "), user_presentable_path(filename, vars()).c_str());
} }
} else { } else {
prefix = L"fish: "; prefix = L"fish: ";

View file

@ -237,9 +237,6 @@ class parser_t : public std::enable_shared_from_this<parser_t> {
/// every block if it is of type FUNCTION_CALL. /// every block if it is of type FUNCTION_CALL.
const wchar_t *is_function(size_t idx = 0) const; const wchar_t *is_function(size_t idx = 0) const;
// Given a file path, return something nicer. Currently we just "unexpand" tildes.
wcstring user_presentable_path(const wcstring &path) const;
/// Create a parser. /// Create a parser.
parser_t(); parser_t();
parser_t(std::shared_ptr<env_stack_t> vars); parser_t(std::shared_ptr<env_stack_t> vars);