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

Improve user error messages #1147

Merged
merged 7 commits into from
Dec 12, 2019
Merged

Improve user error messages #1147

merged 7 commits into from
Dec 12, 2019

Conversation

Julow
Copy link
Collaborator

@Julow Julow commented Nov 14, 2019

  • 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

@Julow Julow requested review from emillon and gpetiot November 14, 2019 11:40
@facebook-github-bot
Copy link

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!

@facebook-github-bot
Copy link

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks!

Copy link
Collaborator

@emillon emillon left a 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

lib/Conf.ml Outdated Show resolved Hide resolved
lib/Conf.ml Outdated Show resolved Hide resolved
@@ -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)
Copy link
Collaborator

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.

Copy link
Collaborator Author

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.

Copy link
Collaborator

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.

Copy link
Collaborator

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

Copy link
Collaborator Author

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.

Copy link
Collaborator

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

================
args: --impl -
ocamlformat: Error while parsing .ocamlformat:
For option "bad": expecting "0.12-18-gea9fdbb-dirty" but got "bad"
Copy link
Collaborator

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.

Copy link
Collaborator Author

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".

| 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
Copy link
Collaborator

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.

Copy link
Collaborator Author

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.

Copy link
Collaborator

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)

Copy link
Collaborator

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)

Copy link
Collaborator Author

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.

Copy link
Collaborator

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.

Copy link
Collaborator

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:

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.

Copy link
Collaborator Author

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) ?

Copy link
Collaborator

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?

Copy link
Collaborator Author

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
    ?

test/cli/test_cli.ml Outdated Show resolved Hide resolved
Copy link
Collaborator

@gpetiot gpetiot left a 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.

@Julow
Copy link
Collaborator Author

Julow commented Nov 15, 2019

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.

@jberdine
Copy link
Collaborator

This cannot be merged yet, the version test is not stable.

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?

@Julow
Copy link
Collaborator Author

Julow commented Nov 25, 2019

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 !

@Julow Julow requested a review from gpetiot November 25, 2019 12:54
@Julow
Copy link
Collaborator Author

Julow commented Nov 25, 2019

I rebased on master (cli tests changed) and worked around the version problem.
This is ready for review and merge.

test/cli/dune Outdated Show resolved Hide resolved
@jberdine
Copy link
Collaborator

I haven't managed to find the root cause, but note that with this PR I still see the emacs integration silently swallowing errors.

lib/Conf.ml Outdated Show resolved Hide resolved
@jberdine
Copy link
Collaborator

Hmm, I don't understand why, but the disagreement between the changes from 1127 and ocamlformat.el still remain after this.

@Julow
Copy link
Collaborator Author

Julow commented Nov 26, 2019

@jberdine What is the error that you expect and don't show up? Do you see the Could not apply ocamlformat message?

@jberdine
Copy link
Collaborator

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.

@Julow
Copy link
Collaborator Author

Julow commented Nov 26, 2019

Could it be that the file passed to ocamlformat is not located where the bad .ocamlformat file can be found? (eg. in /tmp)

@jberdine
Copy link
Collaborator

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 *compilation* buffer depending on the emacs config (I've tried both).

@Julow
Copy link
Collaborator Author

Julow commented Dec 9, 2019

This PR wasn't fixing #1139. I opened #1180 for that.

I think this PR is still an improvement, it improves error outputs a lot and adds tests for them.

@gpetiot
Copy link
Collaborator

gpetiot commented Dec 12, 2019

If all blocking points have been resolved it's time to merge this one as well.

Print error messages to stderr
Remove sexp output and backtraces
Add tests for some error messages
@Julow
Copy link
Collaborator Author

Julow commented Dec 12, 2019

Just rebased. I think we can merge now :)

@Julow Julow merged commit 39897bd into ocaml-ppx:master Dec 12, 2019
Julow added a commit to Julow/opam-repository that referenced this pull request Jan 28, 2020
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)
bogdan2412 pushed a commit to bogdan2412/ocamlformat that referenced this pull request Mar 28, 2020
Print error messages to stderr
Remove sexp output and backtraces
Add tests for some error messages
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants