Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simpler error messages #10054

Closed
wants to merge 4 commits into from
Closed

Conversation

faho
Copy link
Member

@faho faho commented Oct 13, 2023

Description

These are three fairly independent commits with a common goal:

To make our error messages better.

The first adds some extra cases where we used to print "Unknown error while evaluating command substitution". The messages it adds are pretty redundant, but not adding an error there would require some extra scaffolding. Or we could pull these errors apart, which requires separate status codes. I would like to add this one to 3.7.0 as-is, and think it's fairly uncontroversial.

The second puts the "called on" on the same line as the block description in stack traces. So instead of

in command substitution
        called on line 14 of file foo.fish

you get

in command substitution called on line 14 of file foo.fish

This makes some possibly very large messages a bunch smaller.

One potential issue is that this also changes the output of status print-stack-trace, which people could potentially rely on. Last time we did that I can't remember anyone complaining.

It also changes all these messages, which means the translations would need to be fixed (which should be fine to just do because it's removing a \n).

The third one removes a potential redundant "fish:" line we get in some cases, because we add an error without a message to add context. It's a bit hacky, but not too odious I think. Mostly it would be easier if describe_with_prefix didn't have to add error messages for bare variable assignments or andor_in_pipeline, because then the outside could just drive it, and decide to set the prefix to empty if there is no message.

There's some slight concern that there are errors where it's unclear they are from fish - if so, I'd argue that they should just be improved.

Here's a demonstration of how messages change:

fish -c 'nonexistent' changes from

fish: Unknown command: nonexistent
fish: 
nonexistent
^~~~~~~~~~^

to

fish: Unknown command: nonexistent
nonexistent
^~~~~~~~~~^

And a nonsense script I wrote changes from:

fish: Unknown command: nonexistent
foo.fish (line 4): 
    if nonexistent
       ^~~~~~~~~~^
in function 'this-errors' with arguments '2'
	called on line 11 of file foo.fish
in function 'call-this'
	called on line 1 of file foo.fish
in command substitution
	called on line 14 of file foo.fish
foo.fish (line 1): for: status: cannot overwrite read-only variable
for status in 1 2 3; echo $status; end
    ^~~~~^
in command substitution
	called on line 7 of file foo.fish
in function 'this-errors' with arguments '2'
	called on line 11 of file foo.fish
in function 'call-this'
	called on line 1 of file foo.fish
in command substitution
	called on line 14 of file foo.fish
foo.fish (line 7): Unknown error while evaluating command substitution
    echo (for status in 1 2 3; echo $status; end)
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
in function 'this-errors' with arguments '2'
	called on line 11 of file foo.fish
in function 'call-this'
	called on line 1 of file foo.fish
in command substitution
	called on line 14 of file foo.fish

to

fish: Unknown command: nonexistent
foo.fish (line 4): 
    if nonexistent
       ^~~~~~~~~~^
in function 'this-errors' with arguments '2' called on line 11 of file foo.fish
in function 'call-this' called on line 1 of file foo.fish
in command substitution called on line 14 of file foo.fish
foo.fish (line 1): for: status: cannot overwrite read-only variable
for status in 1 2 3; echo $status; end
    ^~~~~^
in command substitution called on line 7 of file foo.fish
in function 'this-errors' with arguments '2' called on line 11 of file foo.fish
in function 'call-this' called on line 1 of file foo.fish
in command substitution called on line 14 of file foo.fish
foo.fish (line 7): Invalid arguments
    echo (for status in 1 2 3; echo $status; end)
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
in function 'this-errors' with arguments '2' called on line 11 of file foo.fish
in function 'call-this' called on line 1 of file foo.fish
in command substitution called on line 14 of file foo.fish

A 50% reduction in number of lines - from 30 lines to 20, for a single wrong variable name and nonexistent command. The script itself is 15 lines long. Or see the stack-overflow test, where this removes 130 lines.

It would also be possible to reword this, while we're at it (I've seen things phrase line positions as "file:line", so "called on foo.fish:14").

TODOs:

  • Changes to fish usage are reflected in user documentation/manpages.
  • Tests have been added for regressions fixed
  • User-visible changes noted in CHANGELOG.rst

I would be entirely fine if we decided to go with just the first one, or if we decided to put the rest off for 4.0, or if the rest gets in the way of someone's porting and I need to write it again later, or if we decide to go for a cleaner solution.

These printed "Unknown error while evaluating command substitution".

Now they print something like

```
fish: for: status: cannot overwrite read-only variable
for status in foo; end
    ^~~~~^
in command substitution
fish: Invalid arguments
echo (for status in foo; end)
     ^~~~~~~~~~~~~~~~~~~~~~~^
```

for `echo (for status in foo; end)`

This is, of course, still not *great*. Mostly the `fish: Invalid
arguments` is basically entirely redundant.

An alternative is to simply skip the error message, but that requires some
more scaffolding (describe_with_prefix adds some error messages on its
own, so we can't simply say "don't add the prefix if we don't have a
message")
When fish prints an error, it will often add a stack trace.

This stack trace could look like

```
test: Missing argument at index 3
-eq 5
      ^
./foo.fish (line 3):
    test $args -eq 5
    ^
in function 'this-errors' with arguments '2'
	called on line 7 of file ./foo.fish
in function 'call-this'
	called on line 1 of file ./foo.fish
in command substitution
	called on line 10 of file ./foo.fish
```

which is a bit long, and the "called on" lines start with tab
characters, which is weird.

So, this shortens it to:

```
test: Missing argument at index 3
-eq 5
      ^
./foo.fish (line 3):
    test $args -eq 5
    ^
in function 'this-errors' with arguments '2' called on line 7 of file ./foo.fish
in function 'call-this' called on line 1 of file ./foo.fish
in command substitution called on line 10 of file ./foo.fish
```

Note: We expose stack traces via `status print-stack-trace`, so this
can break people's scripts if they rely on that.

However, we did a similar change in
7095de6,
where we put the function arguments on the same line, and haven't
heard a peep from anyone.
For example `fish -c "nonexistent-command-1234 banana rama"` prints:

```
fish: Unknown command: nonexistent-command-1234
fish:
nonexistent-command-1234 banana rama
^~~~~~~~~~~~~~~~~~~~~~~^
```

That "fish: " line is entirely useless, and this removes it.
@faho faho added this to the fish 3.7.0 milestone Oct 13, 2023
break;
}
case block_type_t::event: {
assert(b.event && "Should have an event");
wcstring description = *event_get_desc(parser, **b.event);
append_format(trace, _(L"in event handler: %ls\n"), description.c_str());
print_call_site = true;
append_format(trace, _(L"in event handler: %ls"), description.c_str());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only potential downside is it could look worse if the argument strings are overlong.
I think that's an edge case so probably this is fine and overall a great change.


As a programmer, the stack traces are a bit confusing to me, if I see something like

function foo file bar.fish:3
function bar ...

I expect that line 3 in bar.fish is inside function foo. But that's a separate concern

Also I expect the ordering file,line,function,arguments instead of function,arguments,file,line (which would alleviate the concern about long arguments)


I would be entirely fine if we decided to go with just the first one, or if we decided to put the rest off for 4.0, or if the rest gets in the way of someone's porting and I need to write it again later, or if we decide to go for a cleaner solution.

I don't mind merging things like this first (it's small and I don't expect too many of them).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only potential downside is it could look worse if the argument strings are overlong.

There are a bunch of ways to solve this:

  1. Truncate/ellipsize the arguments (not great)
  2. Move the arguments onto another line if they are very long

Something like

fish: Unknown command: nonexistent
foo.fish (line 4): 
    if nonexistent
       ^~~~~~~~~~^
in function 'this-errors' with arguments:
'foo\ bar aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa baz'
 called on line 11 of file foo.fish
in function 'call-this' called on line 1 of file foo.fish

for the latter. I have something whipped up, I'll add it here.

Also I expect the ordering file,line,function,arguments instead of function,arguments,file,line

I think that would be awkward because we don't tend to use tons of files. So you would have a lot of

foo.fish:50:foo bar baz
foo.fish:42:function2 arguments
foo.fish:38:function1 arguments

which is a bunch of noise.

I've been experimenting with only showing the file when it changed

This should alleviate concerns over the argument list being too long
and pushing the file off-screen (well, onto the new line)
@faho
Copy link
Member Author

faho commented Nov 9, 2023

Alright, I'm going to be merging the first commit of this, also to 3.7.0 and then rework the rest later.

@faho
Copy link
Member Author

faho commented Nov 9, 2023

8d5d0c2 / 67faa10

@faho faho closed this Nov 9, 2023
@faho faho deleted the simpler-error-messages branch November 24, 2023 17:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants