-
Notifications
You must be signed in to change notification settings - Fork 179
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
Improve user error messages #1147
Conversation
Julow
commented
Nov 14, 2019
•
edited
Loading
edited
- Add tests for invalid ocamlformat files and env variable.
- Nicer error messages instead of uncaught exceptions with sexp payload and backtrace
- Error messages are printed to stderr
Hi Julow! Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file.In order for us to review and merge your code, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA. If you have received this in error or have any questions, please contact us at [email protected]. Thanks! |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changes look good, thanks for working on this
@@ -52,10 +52,10 @@ module Binary_reason = struct | |||
let rec loop = function | |||
| [] -> | |||
if is_intf_or_impl magic then | |||
user_error "Unknown version" [("magic", Sexp.Atom magic)] | |||
failwith (Format.sprintf "Unknown version (magic: %s)" magic) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what do you think about defining failwithf
in Import
? (using Format.kasprintf failwith
). I thought it was in Base
, but it's only in Core
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would only be used twice. In the future, this code could be either gone or improved, in both cases this would no longer be useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with a dead failwithf
in import if you think it's worth it in the meantime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it would not be in vain, in the future we would need an easy way to emit errors, warnings and hints
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's why I'm against adding this.
We need more than the Failure
exception (eg. locations, colors, formatting) and I don't want that to be used elsewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see no problem to have only what is necessary for this PR for now and rework it when we need it
test/cli/test_cli.expected
Outdated
================ | ||
args: --impl - | ||
ocamlformat: Error while parsing .ocamlformat: | ||
For option "bad": expecting "0.12-18-gea9fdbb-dirty" but got "bad" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will always fail as it depends on the commit number, unfortunately. You can postprocess the output but we can leave this test for now I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was hoping #1133 would solve this.
I just forgot to mark this PR as "Draft".
test/cli/test_cli.ml
Outdated
| Some d -> Format.fprintf pp "cd '%s'; " d | ||
| None -> () | ||
in | ||
let cmd = Format.asprintf "%a%s %s 2>&1" pp_cd pwd ocamlformat args in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This adds a lot of complexity to the test harness just to parse .ocamlformat
files. We could use spawn
to simplify that, but actually, does this need to be tested at the end to end level?
What do you think about pulling out the function that parses a .ocamlformat
file and put that in a test harness instead? It looks like it's the main branch of Conf.read_config_file
. That way, we can just test a string -> config file and remove all of this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. That's something I want to do next and it's required to have ocamlformat as a library.
Here I wanted to test end-to-end because I'm checking the error message given to the user.
I think we should both keep this and have the config parsing unit-tested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not too useful to test the same thing at both level. In my experience it's enough to just test the happy path as e2e (and maybe one error to see how it's rendered), but that has not its place in this test harness. We can think how to make an e2e test for file parsing (ocamlformat / ignore / ocp-indent) in a separate PR. (we can probably do it by hand)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(you'll need #1148 to link a test suite, I can give you a hand with that)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes but here I'm not testing that errors are reported or anything. I'm testing the rendering of messages.
I'm testing a single level, the e2e one.
Unit-tests are for an other PR, this one is about error messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If dune can do more work for us that would be great, I'm not opposed to having duplicates of tests in many places for now. That's a job we need to do later anyway, determine where and how is tested every usecase, and fill the blanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, we can live with extra tests. however I don't think we should try to use this test harness for things it'll do worse than dune. to expand a bit:
- in Add command line tests #1117 we added a way to run ocamlformat with some options and stdin and compare the results.
- in Use an expect test for cli tests #1126 this was simplified since running a binary with arguments is simple enough that it can be done in-process. expect test are a good enough balance for this.
However, if we need to add features like changing directory, setting environment variables, etc, this is more complicated in-process than using (setenv)
and (chdir)
in a dune file.
So I suggest that we:
- leave
test_cli
unchanged in this PR and use it only for things that just pass arguments and don't need to set env/read.ocamlformat
files - use manually written dune rules for these new tests, in a style similar to the rules generated in Add command line tests #1117. we don't need a generator for this.
As for test_cli
, maybe it was a bit overreaching, and the right balance is a set of manually written dune rules (without a generator). There are not that many cases, so we can avoid having this test_cli
and leverage dune's ability to run processes with arguments and diff files. I'm happy to undo this part after this PR if that works for you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree test_cli
is becoming too complicated (it was from the beginning) and we will have to maintain it.
Instead of going back to vanilla dune (it still lacks features like allowing failing commands) and is a bit harder to setup when we have new needs (especially with no generators), wouldn't it be better to just use better tools ?
We could use bos
to cleanup process-handling code or use a cram-like tool (eg. ppx_expect
if it can do that) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, great. We can live with a couple manual rules. I suggest the following plan to move things forward:
- you convert the new tests to plain dune rules (in this PR)
- I undo
test_cli
as plain dune rules (in another PR) - we try to use craml or mdx later to run the commands (later)
sounds good?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure converting tests to plain dune rules is good idea because it's pretty hard and time consuming.
This PR won't be merged now because of something else. What about:
- Keep this PR open
- We try to use craml or mdx (in another PR) for the tests currently in master
- Rebase this PR on that
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me if the test duplication is not blocking, can be merged as soon as it is ready.
As I was arguing, I believe there is no problem with the tests. This new tests are about how error are printed to CLI users and are absolutely not testing the handling of errors. This cannot be merged yet, the version test is not stable. I'm hoping #1133 will help with that, I think the version check should be relaxed with dev builds. |
Is the (only) problem that there is a test which includes the current version in the output error message, and that keeps changing? If so, is it possible to change that test to just check the exit code? |
Yes, #1133 needs more work so I'll workaround that ! |
6bdc881
to
732fb6a
Compare
I rebased on master (cli tests changed) and worked around the version problem. |
I haven't managed to find the root cause, but note that with this PR I still see the emacs integration silently swallowing errors. |
Hmm, I don't understand why, but the disagreement between the changes from 1127 and ocamlformat.el still remain after this. |
@jberdine What is the error that you expect and don't show up? Do you see the |
When I test with a file whose config specifies a mismatched version, for example, and invoke ocamlformat, I see "Applied ocamlformat" when in fact it errored out. I tried debugging the elisp for a while, and saw that printing the status code returned from call-process is 0. So I don't understand at all. |
Could it be that the file passed to ocamlformat is not located where the bad |
I don't think that is it. I have tested by building the parent commit of pr1127 and see the expected error, and then build pr1127 and the error is silently ignored, and with this pr and see the same as with 1127. I just pick any random infer file, add some extra line, try to reformat and look for the error in the echo area or |
a041e37
to
08a5c59
Compare
If all blocking points have been resolved it's time to merge this one as well. |
08a5c59
to
2917c91
Compare
Print error messages to stderr Remove sexp output and backtraces Add tests for some error messages
Just rebased. I think we can merge now :) |
CHANGES: #### New features + Add an option `--margin-check` to emit a warning if the formatted output exceeds the margin (ocaml-ppx/ocamlformat#1110) (Guillaume Petiot) + Preserve comment indentation when `wrap-comments` is unset (ocaml-ppx/ocamlformat#1138, ocaml-ppx/ocamlformat#1159) (Jules Aguillon) + Improve error messages (ocaml-ppx/ocamlformat#1147) (Jules Aguillon) + Display standard output in the emacs plugin even when ocamlformat does not fail (ocaml-ppx/ocamlformat#1189) (Guillaume Petiot) #### Removed + Remove `ocamlformat_reason` (ocaml-ppx/ocamlformat#254, ocaml-ppx/ocamlformat#1185) (Etienne Millon). This tool has never been released to opam, has no known users, and overlaps with what `refmt` can do. + Remove `ocamlformat-diff` (ocaml-ppx/ocamlformat#1205) (Guillaume Petiot) This tool has never been released to opam, has no known users, and overlaps with what `merge-fmt` can do. #### Packaging + Work with base v0.13.0 (ocaml-ppx/ocamlformat#1163) (Jules Aguillon) #### Bug fixes + Fix placement of comments just before a '|' (ocaml-ppx/ocamlformat#1203) (Jules Aguillon) + Fix build version detection when building in the absence of a git root (ocaml-ppx/ocamlformat#1198) (Anil Madhavapeddy) + Fix wrapping of or-patterns in presence of comments with `break-cases=fit` (ocaml-ppx/ocamlformat#1167) (Jules Aguillon) This also fixes an unstable comment bug in or-patterns + Fix an unstable comment bug in variant declarations (ocaml-ppx/ocamlformat#1108) (Jules Aguillon) + Fix: break multiline comments (ocaml-ppx/ocamlformat#1122) (Guillaume Petiot) + Fix: types on named arguments were wrapped incorrectly when preceding comments (ocaml-ppx/ocamlformat#1124) (Guillaume Petiot) + Fix the indentation produced by max-indent (ocaml-ppx/ocamlformat#1118) (Guillaume Petiot) + Fix break after Psig_include depending on presence of docstring (ocaml-ppx/ocamlformat#1125) (Guillaume Petiot) + Remove some calls to if_newline and break_unless_newline and fix break before closing brackets (ocaml-ppx/ocamlformat#1168) (Guillaume Petiot) + Fix unstable cmt in or-pattern (ocaml-ppx/ocamlformat#1173) (Guillaume Petiot) + Fix location of comment attached to the underscore of an open record (ocaml-ppx/ocamlformat#1208) (Guillaume Petiot) + Fix parentheses around optional module parameter (ocaml-ppx/ocamlformat#1212) (Christian Barcenas) + Fix grouping of horizontally aligned comments (ocaml-ppx/ocamlformat#1209) (Guillaume Petiot) + Fix dropped comments around module pack expressions (ocaml-ppx/ocamlformat#1214) (Jules Aguillon) + Fix regression of comment position in list patterns (ocaml-ppx/ocamlformat#1141) (Josh Berdine) + Fix: adjust definition of Location.is_single_line to reflect margin (ocaml-ppx/ocamlformat#1102) (Josh Berdine) #### Documentation + Fix documentation of option `version-check` (ocaml-ppx/ocamlformat#1135) (Wilfred Hughes) + Fix hint when using `break-separators=after-and-docked` (ocaml-ppx/ocamlformat#1130) (Greta Yorsh)
Print error messages to stderr Remove sexp output and backtraces Add tests for some error messages