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

Better errors #51

Merged
merged 9 commits into from
Dec 27, 2020
Merged

Better errors #51

merged 9 commits into from
Dec 27, 2020

Conversation

gasche
Copy link
Collaborator

@gasche gasche commented Dec 26, 2020

This PR is on top of #50, it adds more informative arguments to render-time exceptions and transforms them into better error messages.

Before:

Fatal error: exception Mustache_types.Missing_variable("d")

After:

Template render error:
File "test.mustache", line 2, characters 7-12: the variable d is missing.

This is a breaking change as the exception types have changed, but the change only affects users who are not catching and inspecting Mustache exceptions.

However, good error locations are only available if people used the With_locations modules. If you want a 4.0 release for a breaking change, now may also be a good time to make With_locations the default.
(I have some other features planned for the next few days, so I am not suggesting to make a new release right now. But I'm interested in having an idea of the amount of breakage that @rgrinberg would consider acceptable for a future release.)

@rgrinberg I would have liked to add cram-style tests for this PR (I'm thinking of having bin/test where each error message is tested by cramming the binary), but this requires upgrading dune-lang to 2.7; I tried this and it complains that action was deleted some time ago and I should rewrite some other tests in a way that I don't really understand. When you have time, do you think that you could take care of upgrading dune-lang to 2.x for the project?

@rgrinberg
Copy link
Owner

However, good error locations are only available if people used the With_locations modules. If you want a 4.0 release for a breaking change, now may also be a good time to make With_locations the default.

Sounds good to me. Judging by opam, there aren't many users of this ilbrary, and the improvement in usability is significant.

When you have time, do you think that you could take care of upgrading dune-lang to 2.x for the project?

Sure.

let lexbuf = Lexing.from_string template_data in
let () =
let open Lexing in
lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_fname = template_filename };
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Note: this can now be done with just Lexing.set_filename lexbuf template_filename, but this function only appeared in 4.11 so I just went with the old way.

@@ -1,12 +1,27 @@
let apply_mustache json_data template_data =
module Mustache = struct
Copy link
Owner

Choose a reason for hiding this comment

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

Why do we need this module?

Copy link
Collaborator Author

@gasche gasche Dec 27, 2020

Choose a reason for hiding this comment

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

This is a Mustache module where With_locations is the default. If I remove this declaration, Mustache.parse_lx and Mustache.render below will resolve to Mustache.Without_locations, so the errors will only receive dummy locations. Instead of defining this module, I could instead use Mustache.With_locations.parse_lx and Mustache.With_locations.render explicitly -- but I find the global declaration more convenient, as we never want to use the Without_locations definition in the binary.

(Which reminds me that I need to change the error-printing logic to avoid printing dummy locations. Will do right now.)

Copy link
Owner

@rgrinberg rgrinberg Dec 27, 2020

Choose a reason for hiding this comment

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

I thought our plan was to make good locations the default, in which case this would only be temporary. In any case, it's fine.

@gasche
Copy link
Collaborator Author

gasche commented Dec 27, 2020

I rebased this PR on top of #55 (cram tests with examples of most error modes). I expected it to be useful for review, but it turns out to be very useful for myself as well, as I immediately spotted several easy improvements I wanted to make to the error messages I had chosen -- applied in the current PR.

The error message used the first example now says:

Template render error:
File "test.mustache", line 2, characters 7-12: the variable 'd' is missing.

(The change is to use single quotes around variable names; this is not so important with clearly-variable-names like d, but it makes a real difference when the missing variable looks more like a normal English word.)

- Invalid_template is now properly handled as a parsing error.
- The various rendering exceptions are consolidated into a single
  error type, in preparation for better error payloads.
@gasche gasche force-pushed the better-errors branch 2 times, most recently from ae4a590 to 9151d9a Compare December 27, 2020 19:45
@gasche gasche merged commit 0600d37 into rgrinberg:master Dec 27, 2020
psafont added a commit to psafont/opam-repository that referenced this pull request Nov 24, 2023
CHANGES:

* Remove the AST without locations: now all functions build an AST with locations;
  in particular, parsing always provide located error messages.
  To ease backward-compatibility, the smart constructors still use the
  same interface, using dummy locations by default, with
  a With_locations module for users who wish to explicitly provide
  locations.
  (@gasche, rgrinberg/ocaml-mustache#65)
* Support for "template inheritance" (partials with parameters)
  `{{<foo}} {{$param1}}...{{/param1}} {{$param2}}...{{/param2}} {{/foo}`
  following the widely-implemented semi-official specification
    mustache/spec#75
  (@gasche, 58)
* Partials are now supported in the `mustache` command-line tool (@gasche, rgrinberg/ocaml-mustache#57)
  They are interpreted as template inclusion: "{{>foo/bar}}" will include
  "foo/bar.mustache", relative to the current working directory.
* Improve error messages (@gasche, rgrinberg/ocaml-mustache#47, rgrinberg/ocaml-mustache#51, rgrinberg/ocaml-mustache#56)
  Note: the exceptions raised by Mustache have changed, this breaks
  compatibility for users that would catch and deconstruct existing
  exceptions.
* Add `render_buf` to render templates directly to buffers (@gasche, rgrinberg/ocaml-mustache#48)
* When a lookup fails in the current context, lookup in parents contexts.
  This should fix errors when using "{{#foo}}" for a scalar variable
  'foo' to check that the variable exists.
  (@gasche, rgrinberg/ocaml-mustache#49)
psafont added a commit to psafont/opam-repository that referenced this pull request Nov 24, 2023
CHANGES:

* Remove the AST without locations: now all functions build an AST with locations;
  in particular, parsing always provide located error messages.
  To ease backward-compatibility, the smart constructors still use the
  same interface, using dummy locations by default, with
  a With_locations module for users who wish to explicitly provide
  locations.
  (@gasche, rgrinberg/ocaml-mustache#65)
* Support for "template inheritance" (partials with parameters)
  `{{<foo}} {{$param1}}...{{/param1}} {{$param2}}...{{/param2}} {{/foo}`
  following the widely-implemented semi-official specification
    mustache/spec#75
  (@gasche, 58)
* Partials are now supported in the `mustache` command-line tool (@gasche, rgrinberg/ocaml-mustache#57)
  They are interpreted as template inclusion: "{{>foo/bar}}" will include
  "foo/bar.mustache", relative to the current working directory.
* Improve error messages (@gasche, rgrinberg/ocaml-mustache#47, rgrinberg/ocaml-mustache#51, rgrinberg/ocaml-mustache#56)
  Note: the exceptions raised by Mustache have changed, this breaks
  compatibility for users that would catch and deconstruct existing
  exceptions.
* Add `render_buf` to render templates directly to buffers (@gasche, rgrinberg/ocaml-mustache#48)
* When a lookup fails in the current context, lookup in parents contexts.
  This should fix errors when using "{{#foo}}" for a scalar variable
  'foo' to check that the variable exists.
  (@gasche, rgrinberg/ocaml-mustache#49)
psafont added a commit to psafont/opam-repository that referenced this pull request Nov 27, 2023
CHANGES:

* Remove the AST without locations: now all functions build an AST with locations;
  in particular, parsing always provide located error messages.
  To ease backward-compatibility, the smart constructors still use the
  same interface, using dummy locations by default, with
  a With_locations module for users who wish to explicitly provide
  locations.
  (@gasche, rgrinberg/ocaml-mustache#65)
* Support for "template inheritance" (partials with parameters)
  `{{<foo}} {{$param1}}...{{/param1}} {{$param2}}...{{/param2}} {{/foo}`
  following the widely-implemented semi-official specification
    mustache/spec#75
  (@gasche, 58)
* Partials are now supported in the `mustache` command-line tool (@gasche, rgrinberg/ocaml-mustache#57)
  They are interpreted as template inclusion: "{{>foo/bar}}" will include
  "foo/bar.mustache", relative to the current working directory.
* Improve error messages (@gasche, rgrinberg/ocaml-mustache#47, rgrinberg/ocaml-mustache#51, rgrinberg/ocaml-mustache#56)
  Note: the exceptions raised by Mustache have changed, this breaks
  compatibility for users that would catch and deconstruct existing
  exceptions.
* Add `render_buf` to render templates directly to buffers (@gasche, rgrinberg/ocaml-mustache#48)
* When a lookup fails in the current context, lookup in parents contexts.
  This should fix errors when using "{{#foo}}" for a scalar variable
  'foo' to check that the variable exists.
  (@gasche, rgrinberg/ocaml-mustache#49)
psafont added a commit to psafont/opam-repository that referenced this pull request Nov 28, 2023
CHANGES:

* Remove the AST without locations: now all functions build an AST with locations;
  in particular, parsing always provide located error messages.
  To ease backward-compatibility, the smart constructors still use the
  same interface, using dummy locations by default, with
  a With_locations module for users who wish to explicitly provide
  locations.
  (@gasche, rgrinberg/ocaml-mustache#65)
* Support for "template inheritance" (partials with parameters)
  `{{<foo}} {{$param1}}...{{/param1}} {{$param2}}...{{/param2}} {{/foo}`
  following the widely-implemented semi-official specification
    mustache/spec#75
  (@gasche, 58)
* Partials are now supported in the `mustache` command-line tool (@gasche, rgrinberg/ocaml-mustache#57)
  They are interpreted as template inclusion: "{{>foo/bar}}" will include
  "foo/bar.mustache", relative to the current working directory.
* Improve error messages (@gasche, rgrinberg/ocaml-mustache#47, rgrinberg/ocaml-mustache#51, rgrinberg/ocaml-mustache#56)
  Note: the exceptions raised by Mustache have changed, this breaks
  compatibility for users that would catch and deconstruct existing
  exceptions.
* Add `render_buf` to render templates directly to buffers (@gasche, rgrinberg/ocaml-mustache#48)
* When a lookup fails in the current context, lookup in parents contexts.
  This should fix errors when using "{{#foo}}" for a scalar variable
  'foo' to check that the variable exists.
  (@gasche, rgrinberg/ocaml-mustache#49)
nberth pushed a commit to nberth/opam-repository that referenced this pull request Jun 18, 2024
CHANGES:

* Remove the AST without locations: now all functions build an AST with locations;
  in particular, parsing always provide located error messages.
  To ease backward-compatibility, the smart constructors still use the
  same interface, using dummy locations by default, with
  a With_locations module for users who wish to explicitly provide
  locations.
  (@gasche, rgrinberg/ocaml-mustache#65)
* Support for "template inheritance" (partials with parameters)
  `{{<foo}} {{$param1}}...{{/param1}} {{$param2}}...{{/param2}} {{/foo}`
  following the widely-implemented semi-official specification
    mustache/spec#75
  (@gasche, 58)
* Partials are now supported in the `mustache` command-line tool (@gasche, rgrinberg/ocaml-mustache#57)
  They are interpreted as template inclusion: "{{>foo/bar}}" will include
  "foo/bar.mustache", relative to the current working directory.
* Improve error messages (@gasche, rgrinberg/ocaml-mustache#47, rgrinberg/ocaml-mustache#51, rgrinberg/ocaml-mustache#56)
  Note: the exceptions raised by Mustache have changed, this breaks
  compatibility for users that would catch and deconstruct existing
  exceptions.
* Add `render_buf` to render templates directly to buffers (@gasche, rgrinberg/ocaml-mustache#48)
* When a lookup fails in the current context, lookup in parents contexts.
  This should fix errors when using "{{#foo}}" for a scalar variable
  'foo' to check that the variable exists.
  (@gasche, rgrinberg/ocaml-mustache#49)
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.

2 participants