1
1
mirror of https://github.com/wader/fq.git synced 2024-12-23 13:22:58 +03:00

cli: Better filenames in errors

This commit is contained in:
Mattias Wadman 2021-08-18 18:47:13 +02:00
parent 394e2b3837
commit 0dd848de6c
8 changed files with 44 additions and 31 deletions

View File

@ -38,7 +38,7 @@ func (i *Interp) makeFunctions(registry *registry.Registry) []Function {
{[]string{"tty"}, 0, 0, i.tty, nil},
{[]string{"readline"}, 0, 2, i.readline, nil},
{[]string{"eval"}, 1, 1, nil, i.eval},
{[]string{"eval"}, 1, 2, nil, i.eval},
{[]string{"stdout"}, 0, 0, nil, i.stdout},
{[]string{"stderr"}, 0, 0, nil, i.stderr},
@ -246,12 +246,20 @@ func (i *Interp) readline(c interface{}, a []interface{}) interface{} {
}
func (i *Interp) eval(c interface{}, a []interface{}) gojq.Iter {
var err error
src, err := toString(a[0])
if err != nil {
return gojq.NewIter(fmt.Errorf("src: %w", err))
}
var filenameHint string
if len(a) >= 2 {
filenameHint, err = toString(a[1])
if err != nil {
return gojq.NewIter(fmt.Errorf("filename hint: %w", err))
}
}
iter, err := i.Eval(i.evalContext.ctx, ScriptMode, c, src, i.evalContext.stdout)
iter, err := i.Eval(i.evalContext.ctx, ScriptMode, c, src, filenameHint, i.evalContext.stdout)
if err != nil {
return gojq.NewIter(err)
}

View File

@ -54,10 +54,11 @@ type compileError struct {
func (ce compileError) Value() interface{} {
return map[string]interface{}{
"error": ce.err.Error(),
"what": ce.what,
"line": ce.pos.Line,
"column": ce.pos.Column,
"error": ce.err.Error(),
"what": ce.what,
"filename": ce.filename,
"line": ce.pos.Line,
"column": ce.pos.Column,
}
}
func (ee compileError) Error() string {
@ -540,7 +541,7 @@ func (i *Interp) Main(ctx context.Context, stdout io.Writer, version string) err
return nil
}
func (i *Interp) Eval(ctx context.Context, mode RunMode, c interface{}, src string, stdout Output) (gojq.Iter, error) {
func (i *Interp) Eval(ctx context.Context, mode RunMode, c interface{}, src string, filename string, stdout Output) (gojq.Iter, error) {
var err error
// TODO: did not work
// nq := &(*q)
@ -549,9 +550,10 @@ func (i *Interp) Eval(ctx context.Context, mode RunMode, c interface{}, src stri
if err != nil {
p := queryErrorPosition(err)
return nil, compileError{
err: err,
what: "parse",
pos: p,
err: err,
what: "parse",
filename: filename,
pos: p,
}
}
@ -692,7 +694,7 @@ func (i *Interp) Eval(ctx context.Context, mode RunMode, c interface{}, src stri
return nil, compileError{
err: err,
what: "parse",
filename: filename,
filename: filenamePart,
pos: p,
}
}
@ -712,9 +714,10 @@ func (i *Interp) Eval(ctx context.Context, mode RunMode, c interface{}, src stri
if err != nil {
p := queryErrorPosition(err)
return nil, compileError{
err: err,
what: "compile",
pos: p,
err: err,
what: "compile",
filename: filename,
pos: p,
}
}
@ -752,7 +755,7 @@ func (i *Interp) EvalFunc(ctx context.Context, mode RunMode, c interface{}, name
/// _args to mark variable as internal and hide it from completion
// {input: ..., args: [...]} | .args as {args: $_args} | .input | name[($_args[0]; ...)]
trampolineExpr := fmt.Sprintf(". as {args: $_args} | .input | %s%s", name, argExpr)
iter, err := i.Eval(ctx, mode, trampolineInput, trampolineExpr, stdout)
iter, err := i.Eval(ctx, mode, trampolineInput, trampolineExpr, "", stdout)
if err != nil {
return nil, err
}

View File

@ -169,9 +169,9 @@ def _eval_is_compile_error: type == "object" and .error != null and .what != nul
def _eval_compile_error_tostring:
"\(.filename // "src"):\(.line):\(.column): \(.error)";
def _eval($e; f; on_error; on_compile_error):
def _eval($e; $filename; f; on_error; on_compile_error):
( _default_options(_build_default_options) as $_
| try eval($e) | f
| try eval($e; $filename) | f
catch
if _eval_is_compile_error then on_compile_error
else on_error
@ -184,7 +184,7 @@ def _repl_on_error:
| (_error_str | println)
);
def _repl_on_compile_error: _repl_on_error;
def _repl_eval($e): _eval($e; _repl_display; _repl_on_error; _repl_on_compile_error);
def _repl_eval($e): _eval($e; "repl"; _repl_display; _repl_on_error; _repl_on_compile_error);
# run read-eval-print-loop
def repl($opts; iter): #:: a|(Opts) => @
@ -231,8 +231,8 @@ def _cli_expr_on_compile_error:
| halt_error(_exit_code_compile_error)
);
# _cli_expr_eval halts on compile errors
def _cli_expr_eval($e; f): _eval($e; f; _cli_expr_on_error; _cli_expr_on_compile_error);
def _cli_expr_eval($e): _eval($e; .; _cli_expr_on_error; _cli_expr_on_compile_error);
def _cli_expr_eval($e; $filename; f): _eval($e; $filename; f; _cli_expr_on_error; _cli_expr_on_compile_error);
def _cli_expr_eval($e; $filename): _eval($e; $filename; .; _cli_expr_on_error; _cli_expr_on_compile_error);
# next valid input
def input:
@ -450,10 +450,12 @@ def _main:
( { null_input: ($parsed_args.null_input == true) }
| if $parsed_args.file then
( .expr = ($parsed_args.file | open | string)
| .expr_filename = $parsed_args.file
| .filenames = $rest
)
else
( .expr = ($rest[0] // ".")
| .expr_filename = "arg"
| .filenames = $rest[1:]
)
end
@ -462,7 +464,7 @@ def _main:
elif .filenames == [] then
.filenames = ["-"]
end
| . as {$expr, $filenames, $null_input}
| . as {$expr, $expr_filename, $filenames, $null_input}
| _include_paths([
$parsed_args.include_path // empty
]) as $_
@ -472,10 +474,10 @@ def _main:
else inputs
end
# will iterate zero or more inputs
| if $parsed_args.repl then [_cli_expr_eval($expr)] | repl({}; .[])
| if $parsed_args.repl then [_cli_expr_eval($expr; $expr_filename)] | repl({}; .[])
else
( _cli_last_expr_error(null) as $_
| _cli_expr_eval($expr; _repl_display)
| _cli_expr_eval($expr; $expr_filename; _repl_display)
)
end
)

View File

@ -15,11 +15,11 @@ exitcode: 123
$ fq -n invalid
exitcode: 3
stderr:
error: src:1:0: function not defined: invalid/0
error: arg:1:0: function not defined: invalid/0
$ fq -n "("
exitcode: 3
stderr:
error: src:1:2: unexpected token <EOF>
error: arg:1:2: unexpected token <EOF>
$ fq . non-existing
exitcode: 2
stderr:

View File

@ -5,4 +5,4 @@ $ fq -L /library -n 'include "a"; a'
$ fq -L /wrong -n 'include "a"; a'
exitcode: 3
stderr:
error: src:1:0: open a.jq: file does not exist
error: arg:1:0: open a.jq: file does not exist

View File

@ -54,11 +54,11 @@ error: /non-existing: file not found
$ fq -d raw '(' /a /b /c
exitcode: 3
stderr:
error: src:1:2: unexpected token <EOF>
error: arg:1:2: unexpected token <EOF>
$ fq -d raw bla /a /b /c
exitcode: 3
stderr:
error: src:1:0: function not defined: bla/0
error: arg:1:0: function not defined: bla/0
$ fq -d raw '1+"a"' /a /b /c
exitcode: 5
stderr:

View File

@ -2,9 +2,9 @@ $ fq -i
null> 1+1
2
null> (
error: src:1:2: unexpected token <EOF>
error: repl:1:2: unexpected token <EOF>
null> abc
error: src:1:0: function not defined: abc/0
error: repl:1:0: function not defined: abc/0
null> 1+"a"
error: cannot add: number (1) and string ("a")
null> 1 | repl

View File

@ -19,7 +19,7 @@ null> $a
"aa"
null> var("a"; empty)
null> $a
error: src:1:0: variable not defined: $a
error: repl:1:0: variable not defined: $a
null> var
{
"bb": "bb"