reasonml-old / bettererrors Goto Github PK
View Code? Open in Web Editor NEWMake OCaml/Reason errors prettier
License: MIT License
Make OCaml/Reason errors prettier
License: MIT License
Suppose in this example, there were an error spanning the entire if
block. BetterErrors currently underlines (and makes red) the white space between the numbers and the text. I believe it looks much better if this is not the case.
193 | if (isMainAxisRow && isStyleDimDefined(child.contents, CSS_FLEX_DIRECTION_ROW)) {
194 |
195 | /* The width is definite, so use that as the flex basis.*/
196 | child.contents.layout.flexBasis = fmaxf(child.contents.style.width, getPaddingAndBorderAxis(child.contents, CSS_FLEX_DIRECTION_ROW));
197 | } else if (not <| isMainAxisRow && isStyleDimDefined(child.contents, CSS_FLEX_DIRECTION_COLUMN)) {
198 |
199 | /* The height is definite, so use that as the flex basis.*/
I was looking for something like this but instead of pretty printing the errors, it would be nice if they could be outputted into json, e.g. using some --json
flag. This will allow me to write tools on top of ocaml-better-errors.
Do you think this feature would fit with the tool?
Could you state the license this package is released under? It states "MIT" in the opam
-file, but I was wondering if this is true.
@bsansouci here's something educational for you I guess lol.
This is nonsense for beginners. RWO describes why this happens. I'd like our description to fit in max two lines.
Here's the error that the build system output. Better errors tries to parse this and fails.
SANITIZE: a total of 2 files that should probably not be in your source tree
has been found. A script shell file
"/Users/me/githubReasonMl/ExampleProject/_build/sanitize.sh" is being
created. Check this script and run it to remove unwanted files or use other
options (such as defining hygiene exceptions or using the -no-hygiene
option).
IMPORTANT: I cannot work with leftover compiled files.
ERROR: Leftover OCaml compilation files:
File Test.cmo in src has suffix .cmo
File Test.cmi in src has suffix .cmi
Exiting due to hygiene violations.
Compilation unsuccessful after building 0 targets (0 cached) in 00:00:00.
Here's the stack trace that is thrown:
Fatal error: exception Failure("hd")
Raised at file "pervasives.ml", line 30, characters 22-33
Called from file "list.ml", line 23, characters 10-23
Called from file "src/reason_error_reporter.ml", line 30, characters 2-91
Error: A type variable is unbound in this type declaration.
In type (< inner : int; .. > as 'a) Js.t the variable 'a is unbound
✔ Seems fine!
Hi!
This is a great project, it's really helping me learn Reason
I came across this error:
wat.re:14 28-43
11 │
12 │ type c 'a = option (tuple 'a);
13 │
14 │ let optSwap: c 'a => c 'a = Option.map swap
Error: The type of this expression, '_a c -> '_a c,
contains type variables that cannot be generalized
when I was doing something similar to this:
let module Option = {
let map = fun f =>
fun
| None => None
| Some x => Some (f x);
};
type pair 'a = | Pair of 'a 'a;
let swap =
fun
| Pair x y => Pair y x;
type c 'a = option (pair 'a);
let optSwap: c 'a => c 'a = Option.map swap
This page shows a very simple repro case:
https://ocaml.org/learn/tutorials/common_error_messages.html#Thetypeofthisexpressioncontainstypevariablesthatcannotbegeneralized
I understand why ref None
needs more type information, but why does Option.map swap
? I feel like the language should let me do this:
wat.re:17 28-31
14 │ let optSwap: c 'a => c 'a = Option.map swap;
15 │
16 │ let _ = optSwap (Some (Pair 1 2));
17 │ let _ = optSwap (Some (Pair 'a' 'b'));
Error: The types don't match.
This is: char
Wanted: int
In any case, this probably deserves a better error, right?
Showing the whole result only at the end is not scalable for larger apps.
https://ocaml.org/learn/tutorials/common_error_messages.html
See the relevant section down there.
:~/clone/rsn/withbuckle$ fail
zsh: command not found: fail
:~/clone/rsn/withbuckle$ echo $?
127
:~/clone/rsn/withbuckle$ fail | huh
zsh: command not found: fail
✔ Seems fine!
:~/clone/rsn/withbuckle$ echo $?
0
I expect the exit code (127
) to be preserved
I think the huh
program should be renamed to something like berror
.
When some opam dependency is updated, and a reinstallation of BetterError occurs, I get the following errors:
[ERROR] The compilation of BetterErrors failed at "make install".
[WARNING] Directory /Users/cristianoc/.opam/4.02.1/lib/BetterErrors is not empty, not removing
Repro:
opam reinstall BetterErrors
Deleting lib/BetterErrors
manually unblocks it.
193 |
before printing the source text. You can do this by subtracting min(leadingWhiteSpace, linesThatArePreviewed) from every previewed line, and then inserting two spaces after the |
. <PREVIOUS CONSOLE LINES>
/Users/jwalke/githubPRs/css-layout/src/re-layout/src/Layout.re:196 48-146
…
193 | if (isMainAxisRow && isStyleDimDefined(child.contents, 0)) {
194 |
195 | /* The width is definite, so use that as the flex basis.*/
196 | child.contents.layout.flexBasis = fmaxf(child.contents.style.width, getPaddingAndBorderAxis(child.contents, 0));
197 | } else if (not <| isMainAxisRow && isStyleDimDefined(child.contents, 0)) {
198 |
199 | /* The height is definite, so use that as the flex basis.*/
…
Error: The types don't match.
This is: float * float -> float * float
Wanted: float
/Users/jwalke/githubPRs/css-layout/src/re-layout/src/Layout.re:196 48-146
…
193 | if (isMainAxisRow && isStyleDimDefined(child.contents, 0)) {
194 |
195 | /* The width is definite, so use that as the flex basis.*/
196 | child.contents.layout.flexBasis = fmaxf(child.contents.style.width, getPaddingAndBorderAxis(child.contents, 0));
197 | } else if (not <| isMainAxisRow && isStyleDimDefined(child.contents, 0)) {
198 |
199 | /* The height is definite, so use that as the flex basis.*/
…
Error: The types don't match.
This is: float * float -> float * float
Wanted: float
<NEXT CONSOLE LINES>
Babel just tokenizes the output and colours it. We could do the same and use the existing tokenizer of ocaml + some colours.
e.g.
This is: A.b -> C.d
Wanted: A.z -> C.y
should highlight b and z, and d and y only.
https://www.dropbox.com/s/dbmk00dnod2i583/Screenshot%202016-06-11%2013.54.31.png?dl=0
talk about preprocessing that might have transformed the file name, etc (commonML)
Command failed: ~/foo/bar/bsc -bin-annot -pp ~/foo/bar/refmt -I src/ -impl src/Foo.re -impl src/Bar.re -impl src/Baz.re
Explain each parameter!
[ERROR] Bad checksum for
/Users/dsheets/.opam/packages.dev/BetterErrors.0.0.1/v0.0.1.tar.gz:
- aaac92a8c9a6078f4264454c0053e98f [expected result]
- 213fbbf17f54927d62464d0ac1188f8a [actual result]
It's slightly misleading to newcomers because it sounds like "this constructor doesn't exist". But it does (?); you're just not using it correctly.
Probably means someone forgot a ;
somewhere?
@bsansouci your thing here!
Obviously an unbound module could mean that you got your local module name wrong from e.g. a typo. We should add a small indication before telling users to go add stuff to their build.
How about we check in current directory for similar file names (yeah let's go there lol)? Ship some love.
File "asd.ml", line 1:
Error: I/O error: asd.ml: No such file or directory
Another case is File "_none_", blabla
:
Error: Cannot find file bla.cmo
Another case is File "command line"
, where the error is e.g. ocamlc -open NonExistantModule test.ml
Lastly:
echo "let a = 1; a * 5.0" | rtop -stdin 2>&1 | refmterr
Fatal error: exception Sys_error("(stdin): No such file or directory")
Don't show the file again in this case. It's just a summary for the previous warnings that we've presumably already shown.
This highlight is misleading. Because it's very possible that 'a
is indeed category list
. We should put it in another color or something, to indicate that the focus should be on the first argument.
We can leverage the extra type info (that's also parsed out below, if any) and completely skip our custom diffing algorithm in this case, and maybe in the general case too, to only color string list
(and the corresponding string -> string list
).
In general, I want to somehow show and explain type variables better.
(The actual issue here is that here I've mis-curried by forgetting to provide an extra parameter. Probably needs better message too)
Resources:
http://stackoverflow.com/questions/23595967/parameterized-types-in-ocaml
Latter contains good questions and answers.
Look at what I did for tagging a release (not in the master history) for an npm package form:
https://github.com/npm-ml/BetterErrors/releases/tag/npm-1.2.0
(here's the commit):
17fa83d
Note the convention I'm using for the tag name: npm-1.2.0
.
We need the same thing, but as a commit on top of master. I'm not sure what's up with the versions (in the opam
file they seem to conflict - there's an opam-version and a version field?) What version should we make the master branch be at? We should keep the package.json in sync with the opam version.
File "_none_", line 1:
Error: No implementations provided for the following modules:
Str referenced from src/Test.cmx
Command exited with code 2.
Compilation unsuccessful after building 4 targets (0 cached) in 00:00:00.
What happens?
Fatal error: exception Sys_error("_none_: No such file or directory")
When there is a syntax error, there will be a final error that says the preprocessor could not run, which is expected. But this is just confusing when it is redundant with the syntax error, especially since BetterErrors will highlight line 1
as having an error: BetterErrors should probably just filter it out when there's already a syntax error in that file:
Raw output:
ocamlc -pp refmt -impl ./Layout.re
File "./Layout.re", line 48, characters 48-49:
Error: 2052: <SYNTAX ERROR>
File "./Layout.re", line 1:
Error: Error while running external preprocessor
Command line: refmt './Layout.re' > /var/folders/cm/0xltsk395lb1_5lbrn9z0gqr0000gn/T/ocamlppe4a09d
Error when outputting to refmterr
:
ocamlc -pp refmt -impl ./Layout.re 2>&1 | refmterr
./Layout.re:48 48-49
45 | };
46 |
47 | let getModeName (mode, isLayoutInsteadOfMeasure) => {
48 | let kMeasureModeNames[CSS_MEASURE_MODE_COUNT] = {
49 | "UNDEFINED",
50 | "EXACTLY",
51 | "AT_MOST"
Error: 2052: <SYNTAX ERROR>
./Layout.re:1 0-0
1 | /**
2 | * Copyright (c) 2014, Facebook, Inc.
3 | * All rights reserved.
4 | *
Error: Error while running external preprocessor
Command line: refmt './Layout.re' > /var/folders/cm/0xltsk395lb1_5lbrn9z0gqr0000gn/T/ocamlpp903c85
I instinctively click on the Layout.re:1
which takes me to the first line of the file where there is no error present.
Is there any weird (e.g. buildFailure, fileNotFound) error/warning that does not output a file name? If everything outputs a file name and line info we could use that assumption to reorganize some logic.
Repro:
[%%myPpx]
let a = 5;
File "asd.ml", line 1, characters 3-8:
Uninterpreted extension 'myPpx'.
File "src/test.re", line 1:
Error: I/O error: _build: Is a directory
Pcre and Batteries tend to not be found by ocamlfind on Linux unless written in all lower case in _oasis file. ANSITerminal is correct as is. Does ocamlfind running on MacOS care for capitalization either way?
Wanted to check to make sure before creating a Pull request, just in case lower case P and B in Pcre and Batteries is not compatible everywhere. Unfortunately I currently don't have access to MacOS to give it a try.
might be compiled in a bad order. Or source not found. Or typo
Fatal error: exception Not_found
Raised at file "src/reason_toolchain.ml", line 87, characters 10-13
Called from file "src/reason_toolchain.ml", line 233, characters 14-57
Called from file "src/refmt_impl.ml", line 12, characters 48-157
Called from file "src/refmt_impl.ml", line 153, characters 18-69
File "src/Nuclide.re", line 1:
Error: Error while running external preprocessor
Command line: refmt 'src/Nuclide.re' > /var/folders/r0/dg6dl1qn2l91cq_2k1lg11v501nwsp/T/ocamlppc2cbe7
This could be formatted better. For example, formatting those files to be clickable from the command line, like we do currently for compiler errors. Plus: display better messages when there's no stack trace (e.g. "please enable -g
etc.)
https://realworldocaml.org/v1/en/html/the-compiler-frontend-parsing-and-type-checking.html Search for "principal"
Because newcomers likely don't wanna dig through compilation pipeline explanation to understand the warning.
(Continuation of #28, only this one left. Requires some bigger code refactoring)
File "asd.ml", line 1:
Error: I/O error: asd.ml: No such file or directory
Better explanation and solution.
(Now that cba093b handles the default cases better this is slightly less relevant, but nonetheless desirable to solve)
Current situation: ocamlc
outputs compiler errors to stderr, while make
+ oasis
outputs error to stdout (and leaves some simple failure message in stderr).
If we want to keep using pipes in conjunction with this repo's script (instead of using the heavy-handed solution of wrapping around ocamlc
a-la ocamlfind
), then for brevity we have no choice but to use |&
(aka pipe both stderr and stdout to stdin) to catch all the errors possibility present at either location.
This is fine, but when we run make
with oasis (which defers to ocamlbuild
), the output looks like this:
But if we intercept it through stdin, and simply pipe out the result out again, we get this:
In our specific case, when we detect no error we output a green check mark along with what we got piped in from stdin. So it's basically this:
(Remember that |&
receives stderr and stdout, so it's similar to the situation in the 2nd screenshot)
I'm positive make
is overriding terminal output in order not to be noisy. In fact, we see a little progress bar going on while it's making. But for the life of me I don't understand why I can't capture that and pipe it out normally*, instead of seeing a bunch of log output.
More info on how to override terminal output (on OSX it's \r\c
)
Potentially relevant source code
* I've tested a script where it waits for stdin and outputs every char as soon as possible. With this I've captured my self-made progress bar without it being able to erase old characters. But it doesn't work with make
. It just doesn't see the progress bar and the message in the first screenshot at all...?
https://ocaml.org/learn/tutorials/common_error_messages.html
We could provide even better error for optional argument erasure by providing a solution, as shown in the doc.
Here's the sample output. I don't know if it's broken for just this case or for all cases. I haven't seen one that actually prints correctly. I'm on the latest Reason
(so it pulls in master BetterErrors
IIRC).
File "src/Layout.re", line 511, characters 12-287:
Warning 10: this expression should have type unit.
File "src/Layout.re", line 553, characters 16-50:
Error: This expression has type float but an expression was expected of type
int ref
Command exited with code 2.
Compilation unsuccessful after building 10 targets (9 cached) in 00:00:00.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.