haskell / haskell-language-server

Official haskell ide support via language server (LSP). Successor of ghcide & haskell-ide-engine.
Apache License 2.0
2.61k stars 351 forks source link

Support structured diagnostics #4311

Open dylan-thinnes opened 2 weeks ago

dylan-thinnes commented 2 weeks ago

Addresses https://github.com/haskell/haskell-language-server/issues/2014

Should hopefully enable https://github.com/haskell/haskell-language-server/issues/3246

TODOs:

Additional work (future PRs):

dylan-thinnes commented 1 week ago

Re: deriving JSON instances, the messages often contain fragments of AST and other things which aren't terribly friendly to ToJSON/FromJSON. I tried deriving an instance and immediately came up against

No instance for ‘ToJSON
                         (Language.Haskell.Syntax.Binds.HsBindLR
                            GHC.Hs.Extension.GhcRn GHC.Hs.Extension.GhcRn)’

which makes me think this approach is not going to be easy.

dylan-thinnes commented 1 week ago

Gonna take a break for today, but two big TODOs remain, and a few open questions.

michaelpj commented 1 week ago

Re: deriving JSON instances, the messages often contain fragments of AST and other things which aren't terribly friendly to ToJSON/FromJSON.

This tickled my brain and I remembered that GHC has its own JSON conversion functions! https://gitlab.haskell.org/ghc/ghc/-/blob/master/compiler/GHC/Utils/Json.hs?ref_type=heads

And they definitely have instances for diagnostics, since they're used in the JSON output for GHC, see e.g. here: https://gitlab.haskell.org/ghc/ghc/-/merge_requests/11093

Having written this I realise that that only handles one direction, so it doesn't help us much, oh well.

michaelpj commented 1 week ago

They might have another serialization format, though. There's nothing stopping us from serializing them to bytes and the smuggling a bytestring as a JSON string in data :joy:

wz1000 commented 6 days ago

I don't think we should serialise the raw data over the wire, instead we should stash it in some sort of Map and send over an identifier/key which we can later use to look up the value from the Map. It requires care to ensure that the values are properly garbage collected when no longer valid though.

michaelpj commented 6 days ago

I don't think we should serialise the raw data over the wire, instead we should stash it in some sort of Map and send over an identifier/key which we can later use to look up the value from the Map. It requires care to ensure that the values are properly garbage collected when no longer valid though.

There's no viable serialization format anyway. I do think it would be nice if there was one, though.

That said, I don't think we should need this info in diagnostics that we e.g. get back from the client. So the main issue is when we e.g. ask for the diagnostics covering a range so we can then match on them to work out code actions. At that point we need the GHC diagnostics. So I don't think we need a separate store, at worst we might have to augment our server-side diagnostic store.

dylan-thinnes commented 1 day ago

One remaining point to address from review: https://github.com/haskell/haskell-language-server/pull/4311#discussion_r1651757991, have made a commit for it https://github.com/haskell/haskell-language-server/commit/414c845a74ef64ded31c7486607aa90004bab56e

I'm looking into the CI failures now - I assume some CPP shenanigans are at least part of the issue.