forked from erlang/eep
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ef18834
commit b5ec4e1
Showing
2 changed files
with
195 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
Author: Roberto Aloi <prof3ta(at)gmail(dot)com> | ||
Status: Draft | ||
Type: Standards Track | ||
Created: 23-Aug-2024 | ||
Erlang-Version: OTP-28 | ||
Post-History: | ||
**** | ||
EEP 72: Erlang Error Index | ||
---- | ||
|
||
Abstract | ||
======== | ||
|
||
The **Erlang Error Index** is a _catalogue_ of errors emitted by | ||
various tools within the Erlang ecosystem, including - but not limited | ||
to - the `erlc` Erlang compiler and the `dialyzer` type checker. | ||
|
||
The catalogue is not limited to tools shipped with Erlang/OTP, but it | ||
can include third-party applications such as the [EqWAlizer][] | ||
type-checker or the [Elvis][] code style reviewer. | ||
|
||
Each error in the catalogue is identified by a **unique code** and it | ||
is accompanied by a description, examples and possible courses of | ||
action. Error codes are _namespaced_ based on the tool that generates | ||
them. | ||
|
||
Unique error codes can be leveraged by IDEs and language servers to | ||
provide better contextual information about errors and make errors | ||
easier to search and reference. A standardized error index creates a | ||
common space for the Community to provide extra examples and | ||
documentation, creating the perfect companion for the Erlang User | ||
Manual and standard documentation. | ||
|
||
Rationale | ||
========= | ||
|
||
The concept of an "Error Index" for a programming language is not a | ||
novel idea. Error catalogues already exist, for example, in the | ||
[Rust][] and [Haskell][] Communities. | ||
|
||
Producing meaningful error messages can sometimes be challenging for | ||
developer tools such as compilers and type checkers due to various | ||
constraints, including limited context and character count. | ||
|
||
By associating a **unique code** to each _diagnostic_ (warning or | ||
error) we relief tools from having to condense a lot of textual | ||
information into a - sometime cryptic - generic, single | ||
sentence. Furthermore, as specific wording of errors and warnings is | ||
improved over time, error codes remain constant, providing a | ||
search-engine friendly way to index and reference diagnostics. | ||
|
||
An good example of this is the _expression updates a literal_ error | ||
message, introduced in OTP 27. Given the following code: | ||
|
||
-define(DEFAULT, #{a => 1}). | ||
|
||
updated(Value) -> | ||
?DEFAULT#{a => Value}. | ||
|
||
The compiler emits the following error: | ||
|
||
test.erl:8:11: Warning: expression updates a literal | ||
% 8| ?DEFAULT#{timeout => 1000}. | ||
% | ^ | ||
|
||
The meaning of the error may not be obvious to everyone. Most | ||
importantly, the compiler provide no information on why the warning is | ||
raised and what a user could do about it. The user will then have to | ||
recur to a search engine, a forum or equivalent to proceed. | ||
|
||
Conversely, we can associate a unique identifier to the code (say, | ||
`ERL-1234`): | ||
|
||
test.erl:8:11: Warning: expression updates a literal (ERL-1234) | ||
% 8| ?DEFAULT#{timeout => 1000}. | ||
% | ^ | ||
|
||
The code make it possible to link the error message to an external | ||
resource (a wiki), which contains all the required, additional, | ||
information about the error that would not be practical to present | ||
directly to the user. Here is an example of what the entry could look | ||
like for the above code: | ||
|
||
![Erlang Error Index Sample Entry][] | ||
|
||
Unique error codes also have the advantage to be better searchable in | ||
forums and chats, where the exact error message could vary, but the | ||
error code would be the same. | ||
|
||
Finally, error codes can be used by IDEs (e.g. via language servers) | ||
to match on error codes and provide contextual help. Both the [Erlang | ||
LS][] and the [ELP][] language server already use "unofficial" error | ||
codes. | ||
|
||
Format | ||
------ | ||
|
||
An error code should be composed by two parts: an alphanumeric | ||
_namespace_ (three letters) and a numeric identifier (four digits), | ||
divided by a dash (`-`). | ||
|
||
A potential set of namespaces could look like the following: | ||
|
||
| Namespace | Description | | ||
|-----------|----------------------------------------------------------------| | ||
| ERL | The Erlang compiler and related tools (linter, parser, scanner | | ||
| DIA | The Dialyzer type-checker | | ||
| ELV | The Elvis code-style reviewer | | ||
| ELP | The Erlang Language Platform | | ||
| ... | ... | | ||
|
||
A set of potential error codes could look like: | ||
|
||
ERL-0123 | ||
DIA-0009 | ||
ELV-0015 | ||
ELP-0001 | ||
|
||
The exact number of characters/digits for each namespace and code is | ||
open for discussion, as well as the fact whether components such as | ||
the parser, the scanner or the `erlint` Erlang linter should have | ||
their own namespace. | ||
|
||
Responsibilities | ||
---------------- | ||
|
||
The Erlang/OTP team would be ultimately responsible for maintaining a | ||
list of _official_ namespaces. Each tool maintainer would then be | ||
responsible to allocate specific codes to specific diagnostics. | ||
|
||
Processes | ||
--------- | ||
|
||
Error cannot be re-used. If a tool stops emitting an error code, the | ||
_deprecated_ error code is still documented in the index, together | ||
with a deprecation notice. This is to avoid re-using a single code for | ||
multiple purposes. | ||
|
||
Reference Implementation | ||
------------------------ | ||
|
||
The [ELP website][] contains a proof of concept of what an Erlang | ||
Error Index could look like. Ideally, such a website would live under | ||
the `erlang.org` domain. | ||
|
||
The website should use _Markdown_ as the primary mechanism to write | ||
content and it should be easily extensible by the Community. | ||
|
||
Required Changes | ||
================ | ||
|
||
* The `erlc` compiler and the `dialyzer` type-checker would start | ||
emitting error codes together with errors and warnings messags. | ||
* The tools could also expose a `--explain` option from the command | ||
line - similarly to `rustc` - which would take an error code as the | ||
input and return the Markdown documentation as output. | ||
|
||
Copyright | ||
========= | ||
|
||
This document is placed in the public domain or under the CC0-1.0-Universal | ||
license, whichever is more permissive. | ||
|
||
[EqWAlizer]: https://github.com/whatsapp/eqwalizer | ||
"The EqWAlizer Type Checker" | ||
|
||
[Elvis]: https://github.com/inaka/elvis | ||
"The Elvis Style Reviewer" | ||
|
||
[Rust]: https://doc.rust-lang.org/error_codes/error-index.html | ||
"The Rust Error Index" | ||
|
||
[Haskell]: https://errors.haskell.org | ||
"The Haskell Error Index" | ||
|
||
[Erlang Error Index Sample Entry]: eep-0072-1.png | ||
"Erlang Error Index Sample Entry" | ||
|
||
[Erlang LS]: https://github.com/erlang-ls/erlang_ls/blob/a4a12001e36b26343d1e9d57a0de0526d90480f2/apps/els_lsp/src/els_compiler_diagnostics.erl#L237 | ||
"Erlang LS using error codes" | ||
|
||
[ELP]: https://github.com/WhatsApp/erlang-language-platform/blob/99a426772be274f3739116736bb22d4c98c123c4/erlang_service/src/erlang_service.erl#L608 | ||
"ELP using error codes" | ||
|
||
[ELP Website]: https://whatsapp.github.io/erlang-language-platform/docs/erlang-error-index/ | ||
"ELP website" | ||
|
||
[EmacsVar]: <> "Local Variables:" | ||
[EmacsVar]: <> "mode: indented-text" | ||
[EmacsVar]: <> "indent-tabs-mode: nil" | ||
[EmacsVar]: <> "sentence-end-double-space: t" | ||
[EmacsVar]: <> "fill-column: 70" | ||
[EmacsVar]: <> "coding: utf-8" | ||
[EmacsVar]: <> "End:" | ||
[VimVar]: <> " vim: set fileencoding=utf-8 expandtab shiftwidth=4 softtabstop=4: " |