-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Quote source as part of error messages #3020
Conversation
I'm so excited for this change, I think it will be a huge devX improvement 🎉. Some small bugs with +deterministic:
The root cause seems to be that
|
quote_source_1(File, Loc1, Line) when is_integer(Line) -> | ||
quote_source_1(File, Loc1, {Line, -1}); | ||
quote_source_1(File, {StartLine, StartCol}, {EndLine, EndCol}) -> | ||
case file:read_file(File) of |
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 looks like we are re-reading the source file for each error line. Is there a way to do fewer reads?
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.
Absolutely, this was a simplistic implementation. Considering OS file caches, it's probably not too bad as it is even for a hundred or more errors, but you could implement a caching system (which would have to handle include files as well, not just the main source file).
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.
Seems to be fast enough when compiling the compiler test suite (which has many warnings). In real code, there is probably very few warnings, as many projects use -Werror
nowadays.
484beb9
to
5170eff
Compare
To make things easier for upstream adoption, I am splitting this into two separate parts. This part now only adds the messages and points out the start position, so it does not affect the parser annotations. |
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.
compile_SUITE:app_test/1
fails because you have not included compile_messages
in the app file.
Found two minor style issues.
Otherwise, looks good to me.
Any suggestion for a different module name than "compile_messages", or is it ok for you? |
Should there be tests for this? or are the existing tests sufficient? |
If you can make it sound like a "object", that will be good. Modules probably are well-suited with a notion of a "subject". "compile_messages" sound more like a verb. Just my thoughts. Honestly haven't gone through the details of the PR, so excuse me for being shallow. |
That's basically why I'm asking (and also because someone out there might be using this name for something else already). The main point with the current name is that it indicates its relation to the "compile" module. |
Traditionally, Robert and Joe use So, perhaps, |
5170eff
to
deadadc
Compare
Fixed style issues and renamed to sys_messages. |
deadadc
to
f0df03b
Compare
Tried rebasing on master as well to trigger another rebuild, but it's still failing. Docker trouble? |
Yes, seems to be. It builds fine on our Jenkins server, though. |
There are failed test cases in erlc_SUITE (system) and escript_SUITE (stdlib). |
Consider this module: -module(w). -export([ll/0, sum/0, tt/0, ignored/2]). ll() -> L = {a,b,c}, length(L). sum() -> A = a, B = b, A + B. tt() -> (try nan after whatever end) + 42. ignored(X, Y) -> X + Y, ok. When compiling this module using erlang#3020, the following warnings are emitted: w.erl:6:5: Warning: this expression will fail with a 'badarg' exception % 6| length(L). % | ^ w.erl:11:7: Warning: this expression will fail with a 'badarith' exception % 11| A + B. % | ^ w.erl:14:34: Warning: this expression will fail with a 'badarith' exception % 14| (try nan after whatever end) + 42. % | ^ w.erl:17:7: Warning: the result of the expression is ignored (suppress the warning by assigning the expression to the _ variable) % 17| X + Y, % | ^ The last three warnings are slightly confusing, because the warnings say "this expression" or "the expression", but the column position points out the `+` operator in the middle of the expresson instead of the beginning of the expression. For the second warning, it would be better to point out the variable `A`: w.erl:11:5: Warning: this expression will fail with a 'badarith' exception % 11| A + B. % | ^ However, to produce that warning would need a major rethinking of the compiler pass, `sys_core_fold`, that produces that kind of warning. `sys_core_fold` is an optimization pass that opportunistically emits warnings while optimizing the code. When the warning for line 11 is emitted, the original code has been lost and the line and column number for the variable `A` is no longer available. The third warning does not seem possible to fix by moving the position of the caret: w.erl:14:34: Warning: this expression will fail with a 'badarith' exception % 14| (try nan after whatever end) + 42. % | ^ Pointing to the atom `nan` would be confusing. Considering that the second warning would need a lot of work and that there is no good solution for the third warning, I instead chose to rephrase the warnings like this: w.erl:6:5: Warning: the call to length/1 will fail with a 'badarg' exception % 6| length(L). % | ^ w.erl:11:7: Warning: evaluation of operator '+'/2 will fail with a 'badarith' exception % 11| A + B. % | ^ w.erl:14:34: Warning: evaluation of operator '+'/2 will fail with a 'badarith' exception % 14| (try nan after whatever end) + 42. % | ^ w.erl:17:7: Warning: the result of an expression is ignored (suppress the warning by assigning the expression to the _ variable) % 17| X + Y, % | ^ I did not come up with a great solution for the fourth warning, so I only changed "the expression" to "an expression".
Consider this module: -module(w). -export([ll/0, sum/0, tt/0, ignored/2]). ll() -> L = {a,b,c}, length(L). sum() -> A = a, B = b, A + B. tt() -> (try nan after whatever end) + 42. ignored(X, Y) -> X + Y, ok. When compiling this module using erlang#3020, the following warnings are emitted: w.erl:6:5: Warning: this expression will fail with a 'badarg' exception % 6| length(L). % | ^ w.erl:11:7: Warning: this expression will fail with a 'badarith' exception % 11| A + B. % | ^ w.erl:14:34: Warning: this expression will fail with a 'badarith' exception % 14| (try nan after whatever end) + 42. % | ^ w.erl:17:7: Warning: the result of the expression is ignored (suppress the warning by assigning the expression to the _ variable) % 17| X + Y, % | ^ The last three warnings are slightly confusing, because the warnings say "this expression" or "the expression", but the column position points out the `+` operator in the middle of the expresson instead of the beginning of the expression. For the second warning, it would be better to point out the variable `A`: w.erl:11:5: Warning: this expression will fail with a 'badarith' exception % 11| A + B. % | ^ However, to produce that warning would need a major rethinking of the compiler pass, `sys_core_fold`, that produces that kind of warning. `sys_core_fold` is an optimization pass that opportunistically emits warnings while optimizing the code. When the warning for line 11 is emitted, the original code has been lost and the line and column number for the variable `A` is no longer available. The third warning does not seem possible to fix by moving the position of the caret: w.erl:14:34: Warning: this expression will fail with a 'badarith' exception % 14| (try nan after whatever end) + 42. % | ^ Pointing to the atom `nan` would be confusing. Considering that the second warning would need a lot of work and that there is no good solution for the third warning, I instead chose to rephrase the warnings like this: w.erl:6:5: Warning: the call to length/1 will fail with a 'badarg' exception % 6| length(L). % | ^ w.erl:11:7: Warning: evaluation of operator '+'/2 will fail with a 'badarith' exception % 11| A + B. % | ^ w.erl:14:34: Warning: evaluation of operator '+'/2 will fail with a 'badarith' exception % 14| (try nan after whatever end) + 42. % | ^ w.erl:17:7: Warning: the result of evaluating operator '+'/2 is ignored (suppress the warning by assigning the expression to the _ variable) % 17| X + Y, % | ^
Consider this module: -module(w). -export([ll/0, sum/0, tt/0, ignored/2]). ll() -> L = {a,b,c}, length(L). sum() -> A = a, B = b, A + B. tt() -> (try nan after whatever end) + 42. ignored(X, Y) -> X + Y, ok. When compiling this module using erlang#3020, the following warnings are emitted: w.erl:6:5: Warning: this expression will fail with a 'badarg' exception % 6| length(L). % | ^ w.erl:11:7: Warning: this expression will fail with a 'badarith' exception % 11| A + B. % | ^ w.erl:14:34: Warning: this expression will fail with a 'badarith' exception % 14| (try nan after whatever end) + 42. % | ^ w.erl:17:7: Warning: the result of the expression is ignored (suppress the warning by assigning the expression to the _ variable) % 17| X + Y, % | ^ The last three warnings are slightly confusing, because the warnings say "this expression" or "the expression", but the column position points out the `+` operator in the middle of the expresson instead of the beginning of the expression. For the second warning, it would be better to point out the variable `A`: w.erl:11:5: Warning: this expression will fail with a 'badarith' exception % 11| A + B. % | ^ However, to produce that warning would need a major rethinking of the compiler pass, `sys_core_fold`, that produces that kind of warning. `sys_core_fold` is an optimization pass that opportunistically emits warnings while optimizing the code. When the warning for line 11 is emitted, the original code has been lost and the line and column number for the variable `A` is no longer available. The third warning does not seem possible to fix by moving the position of the caret: w.erl:14:34: Warning: this expression will fail with a 'badarith' exception % 14| (try nan after whatever end) + 42. % | ^ Pointing to the atom `nan` would be confusing. Considering that the second warning would need a lot of work and that there is no good solution for the third warning, I instead chose to rephrase the warnings like this: w.erl:6:5: Warning: the call to length/1 will fail with a 'badarg' exception % 6| length(L). % | ^ w.erl:11:7: Warning: evaluation of operator '+'/2 will fail with a 'badarith' exception % 11| A + B. % | ^ w.erl:14:34: Warning: evaluation of operator '+'/2 will fail with a 'badarith' exception % 14| (try nan after whatever end) + 42. % | ^ w.erl:17:7: Warning: the result of evaluating operator '+'/2 is ignored (suppress the warning by assigning the expression to the _ variable) % 17| X + Y, % | ^
On my machine this prints:
|
@garazdawi The problem you found is a problem with If you compile your function with the
There should be no need take any
The carets are placed in the correct place:
|
Great! |
@richcarl We found that Could you fix this in one of two ways?
|
Bumped to 10 min. Caching can wait until later. |
ce1ea49
to
7c79850
Compare
Found that the underlining was too naive, and could get out of sync with tabs in combination with utf-8 multibytes. Now treats lines as sequences of codepoints, respecting the file encoding. This should always correspond to the column number computed by the scanner. (Forced edit: handle broken encodings in a sensible way instead of crashing.) |
Do you think you could add a test case to test those things you just fixed? To avoid have to constantly update that test case, it would probably be best to call |
Added test case. Running the full compiler to ensure that encodings are checked properly. |
There are still two failing test cases in |
See if you like this solution better before I squash. Also added a fix for the hardcoded paths preventing you from running erlc_SUITE directly from make under erts. |
I think all traces of ranges (#3026) should be removed in this PR. StartLoc = erl_anno:location(Loc). should not try to be forward compatible with ranges. It breaks the |
I agree, so I'll try to remove stuff that shouldn't have been in this part to begin with. Something is weird with the types, though. in compile.erl, a comp_ret(), which is the return type for compile:file() and compile:forms(), is defined as reporting errors and warnings that contain err_info() :: {erl_anno:line() | 'none', module(), term()}. Note that it says line(), which is defined in erl_anno as non_neg_integer(), and this should be changed to location() to reflect the new support for column numbers, which might fix the DEBUG compilation problem. Meanwhile, internally in compile.erl the errors and warnings fields of the I don't really want to start on a type annotation whack-a-mole to try to clean up that stuff myself, since it might cause some cascading type issues, at least not until I know what you think how it should look. |
Looks good to me, and the test cases now run clean. |
I think you can squash it now. (I would prefer down to a single commit.) If everything goes well in our nightly tests, I intend to merge this PR tomorrow. |
I see that you've reverted erl_lint. Looks OK.
You've haven't fixed this, as far as I can see.
No, the erl_anno-abstraction is broken in a more fundamental way. The quoted line,
breaks the erl_anno abstraction.
should suffice. lists_errors also breaks the erl_anno-abstraction:
I suppose you can keep the EndLoc in quote_source as long it's |
bd1675b
to
9a7d62a
Compare
Squashed. Working on a cleanup of type usages, but I can put that in a separate PR after this is merged. |
9a7d62a
to
4451621
Compare
Can be suppressed with the 'brief' compiler option. Moves message formatting code to a separate module.
4451621
to
3253259
Compare
Accidentally deleted a clause that was actually used. Also finally saw what @uabboli meant, so I removed the calls to erl_anno on a location type. |
Thanks, I can confirm that it works with |
Thanks for your pull request. |
Provides one or more additional lines of context for compiler messages, showing the relevant source code with the error position indicated by ^, like this:
These long messages can be suppressed with the 'brief' compiler option.
The message formatting code is moved out to a separate module.
The followup PR #3026 also adds end position to the parser, allowing the error ranges to be underlined.