Description
I've created this as a follow-up to the discussion started in the contributor forum. Since there was no push back, I've gone ahead and started the process. I'll use this issue as a way to track where the progress is at and to also communicate ahead of time the changes that I intend to give full chance for someone to spot something I may not be thinking of.
Short recap
If you don't want to read through the full contributors thread, the TLDR is this:
- Current diagnostics only report a message, a source position, and a severity level
- This makes it tricky for tooling (like Metals for example) to reliably offer code actions or quick fixes on diagnostics unless we do stuff like regex the message to determine the error type
- To fix this we can expose the
ErrorMessageID
during reporting - As a bonus, we can also take situations where we have multiple positions relating to a diagnostic (like inlined positions) and expose them in a structured way.
While the code changes to do this won't be super large, it will impact quite a few places, so I'll outline the plan down below.
The plan
- Get everyone on board
- https://contributors.scala-lang.org/t/revisiting-dotty-diagnostics-for-tooling/5649 holds the initial conversation about this
- [Proposal] Updates to Problem to enable richer reporting sbt/sbt#6868 holds the proposal to the changes to
Problem
- Make the changes to
Problem
to includeDiagnosticCode
andDiagnosticRelatedInformation
- Bump util-interface in the compiler-interface of Zinc (this is what will bring in the field in
Problem
for Dotty) - Add in a way to make an
ErrorMessageID
as inactive. - Bump the compiler-interface in Dotty
- Change the
Problem.java
in the sbt-bridge to include the newDiagnosticCode
andDiagnosticRelatedInformation
- Changes needed to
Diagnostic.scala
to account for theDiagnosticRelatedInformation
. It already holds aMessage
which contains theErrorMessageId
we need for theDiagnosticCode
- Changes needed to the reporting in various places where there are multiple positions associated to a
Diagnostic
to instead of throwing everything in the message, to utilize the related information fields. - Change the
DelegatingReporter
in sbt-bridge to include this information from theDiagnostic
- Ensure these fields are available in BSP
- There was a slight difference here that I noticed. PR to address it is here: fix: align DiagnosticRelatedInformation with the LSP spec build-server-protocol/build-server-protocol#320
- Ensure build tools that serve as build servers start capturing this to forward on
- sbt (feat: start forwarding diagnosticCode via BSP sbt/sbt#6998)
- Bloop (testing this in feat: capture diagnostic code from Problem scalacenter/bloop#1750)
- Mill (testing this in Bump zinc and account for diagnostic code com-lihaoyi/mill#1912)
- Ensure the
ErrorMessageID
s are published somewhere- I've started documenting these in https://github.com/ckipp01/dotty-error-index with the goal to upstream this to the docs
- There is a specific issue created for this in Generate documentation for error IDs #15265
- Tools like Metals can start using these -- aka profit.
Some other notes
With the above, there is also some other assumptions. There are a ton of places we don't create a Message
for an error. I know there was a big effort for this in #1589 but it was paused with the following message
The architecture for errors described in this issue proved to be heavy and impractical. The migration process frequently interferes with in-flight PRs and the benefits are marginal. We should find a more light-weight way to represent errors.
I'd challenge the idea of benefits are marginal, but as far as I'm aware, there is no alternative solution yet correct? Are we ok to start path on this path? I'm assuming yes, seeing that there has been no opposition yet on the forum? If this isn't ok, please speak up now as the ball has started rolling on the changes already. I've tried to over-communicate on this in multiple places to give ample opportunity for feedback, and I'm interpreting silence as support. So it'd be nice to have some explicit 🆗's from the core team before pushing this even further.
I also see that there were some changes to rename ErrorMessageID
s to UNUSED
in 2e5df79. I recommend not to do this and to instead represent some sort of active indication in the actual structure instead. If we change them to UNUSED
we sort of screw up the documentation, even if those IDs will no longer be used. I think we can follow a similar pattern as Rust in just marking them as "The compiler no longer emits this error" in the docs. That's what I've been doing here as an example.
There are also some things that are a bit foggy at the moment, like the case of the diagnostic that multiple inline positions attached to it. Currently this is all contained in the message, and we can expose that more structured in DiagnosticRelatedInformation
, which works great for tooling, but not for console reporting. So we also need to figure out a good way to determine how that is displayed based on where it's being displayed. But maybe this isn't an issue as Dotty can just expose the diagnostic, and then the report is in charge of pulling what it needs out of DiagnosticRelatedInformation
if there is anything and displaying it nicely.
If there are issues with anything outline above, please do speak up.