Run parse_util_detect_errors on -c commands

This didn't do all the syntax checks, so something like

    fish -c 'echo foo; and $status'

complained of a missing command `0` (i.e. $status), and

    fish -c 'echo foo | exec grep'

hit an assert!

So we do what read_ni does, parse each command into an ast, run
parse_util_detect_errors on it if it worked and then eval the ast.

It is possible to do this neater by modifying parser::eval, but I
can't find where.
This commit is contained in:
Fabian Homborg 2021-07-27 17:44:02 +02:00
parent 08209b3d9a
commit 29e9f4838a
3 changed files with 32 additions and 3 deletions

View File

@ -51,6 +51,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#include "intern.h"
#include "io.h"
#include "parser.h"
#include "parse_util.h"
#include "path.h"
#include "proc.h"
#include "reader.h"
@ -255,7 +256,25 @@ static int run_command_list(parser_t &parser, std::vector<std::string> *cmds,
const io_chain_t &io) {
for (const auto &cmd : *cmds) {
wcstring cmd_wcs = str2wcstring(cmd);
parser.eval(cmd_wcs, io);
// Parse into an ast and detect errors.
parse_error_list_t errors;
auto ast = ast::ast_t::parse(cmd_wcs, parse_flag_none, &errors);
bool errored = ast.errored();
if (!errored) {
errored = parse_util_detect_errors(ast, cmd_wcs, &errors);
}
if (!errored) {
// Construct a parsed source ref.
// Be careful to transfer ownership, this could be a very large string.
parsed_source_ref_t ps = std::make_shared<parsed_source_t>(std::move(cmd_wcs), std::move(ast));
parser.eval(ps, io);
} else {
wcstring sb;
parser.get_backtrace(cmd_wcs, errors, sb);
std::fwprintf(stderr, L"%ls", sb.c_str());
// Note: We do not return here because that's how it historically worked.
// return 1;
}
}
return 0;

View File

@ -306,12 +306,10 @@ $fish -c 'echo {'
#CHECKERR: fish: Unexpected end of string, incomplete parameter expansion
#CHECKERR: echo {
#CHECKERR: ^
#CHECKERR:
$fish -c 'echo {}}'
#CHECKERR: fish: Unexpected '}' for unopened brace expansion
#CHECKERR: echo {}}
#CHECKERR: ^
#CHECKERR:
$fish -c 'command (asd)'
#CHECKERR: fish: Command substitutions not allowed
#CHECKERR: command (asd)

View File

@ -78,3 +78,15 @@ and echo matched
string match -rq "echo thisshouldneverbeintheconfig" < $tmp/full.prof
and echo matched
# CHECK: matched
$fish --no-config -c 'echo notprinted; echo foo | exec true; echo banana'
# CHECKERR: fish: The 'exec' command can not be used in a pipeline
# CHECKERR: echo notprinted; echo foo | exec true; echo banana
# CHECKERR: ^
# Running multiple command lists continues even if one has a syntax error.
$fish --no-config -c 'echo $$ oh no syntax error' -c 'echo this works'
# CHECK: this works
# CHECKERR: fish: $$ is not the pid. In fish, please use $fish_pid.
# CHECKERR: echo $$ oh no syntax error
# CHECKERR: ^