-
Notifications
You must be signed in to change notification settings - Fork 804
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
Add ExtendedData to FSharpDiagnostic #15840
Conversation
Probably needs some docs + examples of usage. |
Binary compatibility bothers me a bit here. Will need to think about implications, if we'll need to be making @baronfel @TheAngryByrd thoughts? |
From a FSAC point of view, I think we've grown accustomed to dealing with breaking changes, so not too worried there. The bigger concern would be from some analyzer to be point of view, where if analyzers were relying on some form of structured data, I think FCS would need to publish it for ever, or at least until some understandable breaking change point (and not in a hotfix release). Would have to probably create new types if we need new ways to portray the information. Feels akin to an event sourcing versioning problem. |
True enough, but I don't see a way around it unless you want to do |
@TheAngryByrd yes, event sourcing was exactly the problem I had in mind. That's why my initial suggestion was something fairly untyped as the message envelope ( That's just a looser form of API compatibility problem, though. |
That is the reason why I suggested using a composable list of lower-level extended data items , instead of an option. And it would not fail if the list is extended in the future, neither compile-time nor run-time. It is similar to an approach with a dictionairy of primitives, but instead of .NET primitives, it would use compiler-domain-primitives, and instead of string-based keys, the naming would come from the name of a type. From the point of view of this PR, it's not much more to change - turn option into a list, and remodel some of the examples. |
The documentation is not yet written, while the api discussions are going on. But of course it will be added. Small prototype JetBrains/resharper-fsharp@fd9dd3c. Also, we have a bunch of PRs with new quick fixes: https://github.com/JetBrains/resharper-fsharp/blob/f04f7326b3888b778238d0a1e0e6283a39f6d532/ReSharper.FSharp/src/FSharp.Psi.Daemon/src/Stages/FcsErrorsStageProcessBase.fs#L319-L325 (from JetBrains/resharper-fsharp#545) https://github.com/JetBrains/resharper-fsharp/blob/884e2a68eda184534cd349cc893175978df8bcb8/ReSharper.FSharp/src/FSharp.Psi.Daemon/src/Stages/FcsErrorsStageProcessBase.fs#L319-L325 (from JetBrains/resharper-fsharp#549) https://github.com/JetBrains/resharper-fsharp/blob/432d2009fdda494222184ab2865f77195c7c5678/ReSharper.FSharp/src/FSharp.Psi.Daemon/src/Stages/FcsErrorsStageProcessBase.fs#L319-L329 (from JetBrains/resharper-fsharp#546) Where instead of fsharp/src/Compiler/Symbols/FSharpDiagnostic.fs Lines 103 to 107 in 917fa2d
As you can see from these examples, a single extended data type (such as At the same time, different extended data types can be used to restore the diagnostic context in the case of heterogeneous diagnostics under the same number (as, for example, in
Currently, FCS provides a strongly typed API for all public subsystems. Quite unexpectedly and confusing to receive in this case a set of raw strings/objects with which additional manipulations must be carried out. At the same time, lazy-computed properties with the necessary data can be located inside a separate type, which can play a role in large sets of additional data. For example, extended data might provide a set of missing elements to implement an interface that might not be needed at all, because no one would call a quick fix for it, but it would still have to be computed and put into a dictionary. With properties, we also can change data calculation to lazy without losing backward compatibility.
Together with diagnostic numbers and strongly typed extended data, we can not only get additional data, but also the ability to restore the context of the diagnostic itself. For example, in this code for heterogeneous diagnostics with a single number, from the If we want to make a list of In the current PR, we have the following options, which seem to be no worse than lists and dictionaries
|
Thanks for the detailed responses @DedSec256. Your point about lazy calculation of properties allowing for minimizing the cost of generating good diagnostic data is a great one - it's conceptually similar the reason why detecting a codefix is relevant and applying the codefix is logically separate in models like the LSP. I think I'm beginning to be convinced. We already have some amount of API compat issues, but this kind of API compat is entirely in-process and manageable by the editors - it will only appear as each editor updates its FCS dependency. It's not going to start happening by e.g. a .NET SDK update alone. And the mitigations would hopefully be reasonable - only areas that dealt directly with each diagnostic would be impacted. And putting the relevant codefix data directly on the extended data would reduce the amount of duplicated code in each editor (to do things like determine the name of a type to suggest, or similar). |
Strongly typed data tailored for each diagnostic specifically is of course a superior data-transfer model from the consumer point of view, but it only holds in a closed-world assumption. Which I don't believe can hold in an external analyzer scenario, which is on the roadmap. That being said, could you please mark all the added types as |
I want to throw in my plus one for the current proposal.
I'm pretty convinced that the amount of consumers of this exact API will be minimal. Getting a sense of what FCS consumers would actually use this and how they feel about nice typed data should definitely weigh in on the decision here. As for the compatibility issue, this could be detected early on if public preview FCS releases are consumable for all parties and dropped frequently. I only want to state that this potential problem might not be as painful as you currently think it is. |
Existing F# diagnostics almost never change, this means that the A loosely typed solution will just silently break external users. |
I think it's ready for review and further discussion |
I'm genuinely enthusiastic about the potential trajectory here. I've been actively experimenting with incorporating additional data into #15256, and you can check out my work at https://github.com/DedSec256/fsharp/pull/2/files. The notion of having both the error code and supplementary information seamlessly integrated into the IDE holds significant promise for uncovering optimal refactoring opportunities. In the example I've provided, I can readily guide users towards considering the inclusion of a type annotation precisely where the ambiguity arises within the record definition. |
We'll need to go over it next Monday on our review session and discuss implications for the public surface and both future Analyzers SDK and LSP, and how will we go about deprecating stuff if needed. |
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.
I like the idea, but a bit on the fence because of how ad-hoc this solution is (not necessary a bad thing), and how much of the new public surface we're exposing.
I don't mind merging it and see how does it look with real compiler diagnostics exposed to the user, but would like to hear others' opinions about it.
Hey, I will go thorough this tomorrow to get the idea of the possible implications on the editor side - stay tuned. |
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.
Sorry didn't want to block this. Left some notes - might be misunderstanding something.
As we can see, this test is green after the changes, since the quickfix itself is tied to the diagnostic number, which I did not change. And even more, in the future this code can be replaced by simply getting the names of the arguments from fsharp/vsintegration/src/FSharp.Editor/CodeFixes/RenameParamToMatchSignature.fs Lines 23 to 29 in d95e8f3
For this error, instead of the general diagnostic exception type with a number and message, I created the separate strict type fsharp/src/Compiler/Symbols/FSharpDiagnostic.fs Lines 188 to 189 in 9cf7dcb
Base class? :) |
.../FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl
Outdated
Show resolved
Hide resolved
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.
@DedSec256 thanks for the explanations, it took me some time to understand what's going on here.
I don't have any general objections, things "feel" a bit heavy but I don't have a better design idea and the potential benefits for the tooling outweigh the big API surface for me.
We have this as an experimental so for me it would be important to try building something on top of it to see this in action. Maybe we can then adjust the API on-the-go a bit.
Thanks for this!
tests/FSharp.Compiler.ComponentTests/ErrorMessages/ExtendedDiagnosticDataTests.fs
Show resolved
Hide resolved
Can you, please, mark conversations that are no longer relevant as resolved? :) |
Thanks to everyone who took part in this PR (: |
This PR implements fsharp/fslang-suggestions#1094 and proposes the following:
ExendedData: IFSharpDiagnosticExtendedData option
toFSharpDiagnostic
,where
IFSharpDiagnosticExtendedData
implementations are created fromPhasedDiagnostic
exceptions and can lazily provide the data needed for quick fixes and other IDE-related thingsIFSharpDiagnosticExtendedData
implementations as a proof-of-concept (and which are already needed to stop parsing error messages for some quick fixes :) )To do: