Description
Heya,
I've searched a bit but couldn't find this mentioned before, but I found it pretty hard to search for terms like "extension", ".hs", etc., so please forgive me if this has already been brought up.
I'm using haskell to write a ./go script. In a nutshell, it fills the same role as makefiles in projects that don't use it's only-rebuild-what's-neccessary functionality, or npm's package.json scripts
stuff.
I wanted to call it literally do
, but then I realized that HSL doesn't work.
I don't have a cabal file or anything since this is not even a haskell project, I'm using a nix devshell to get ghc with the packages I need.
When I rename the file to do.hs
, everything works as it should.
While my use case might be better solved by a simpler approach anyways, this should work, right? Looking into :LspLog, it seems like HLS is running but doesn't care about the file. It didn't even print anything about hie-bios or sth.
Your environment
nvim + lspconfig
haskell-language-server version: 1.10.0.0 (GHC: 9.2.7) (PATH: /nix/store/cqcm8dqw7zjj363q8z0mphg17bnxrrn1-haskell-language-server-1.10.0.0/bin/haskell-language-server-wrapper)
Which OS do you use?
Arch linux, but everything is done via nix
I tried adding a hie.yaml with different content but nothing changed
If this is actually debugging-worthy, I'd be happy to trim down my stuff and upload it somewhere, reproducing should be straightforward with nix.
Activity
fendor commentedon Apr 20, 2023
Hi, thank you for your bug report!
This issue is twofold, I think. First, the client needs to realise this is a haskell script, launch HLS and feed it with the file contents. I don't know whether your LSP client does that, e.g. on VSCode does not send a file without an .hs or .lhs extension to HLS. Even if it worked, HLS tries to be a multi-language Language Server, for .cabal and .hs files. It tells the difference by looking at the file extensions. If HLS accepted source files with no extension, I don't think it would be able to tell them apart easily.
I don't know how HLS can support .cabal and .hs files but still satisfy your requirements.
A quick workaround might that you create a symbolic link, e.g.
do.hs
that points todo
. Maybe that's enough to trick HLS to work correctly? Since you are nix for developing, the nix develop could create that symbolic link automatically?voidus commentedon Apr 20, 2023
The multi-filetype thing sounds about right.
Editing through a symlink works indeed. It even works if the file is called
.do.hs
😂I think I have wired up nvim to send stuff to HLS if the filetype is marked haskell. I don't know the lsp protocol, but shouldn't HLS get that info from vim?
If not, I'd propose a way to force that filetype, like
# hls: haskell
after the shebang. But I'd also understand if this is not a priority.fendor commentedon Apr 20, 2023
That looks possible https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentItem seems to have
languageId
. We might use that as the secondary information to distinguish the filetype.voidus commentedon Apr 20, 2023
That would be pretty cool. I'd be curious to contribute on that, but between the learning and time I'll need, I can't tell if or when I'd get around to that.
fendor commentedon Apr 20, 2023
As a warning, I am not confident that works, e.g. do clients actually send
"haskell"
or something like that?But if you want to give it a try, I think it should be a matter of modifying
pluginResponsible
to take an additional parameter for thelanguageId
and adding a field toPluginDescriptor
to add thelanguageId
it accepts. Then, the type errors should be enough to guide you.Every time you invoke
pluginResponsible
, you need to pass in thelanguageId
field, which you can obtain fromTextDocument
.voidus commentedon Apr 23, 2023
Just did a small experiment with
Debug.trace
nvim lspconfig does indeed send eitherhaskell
,cabal
orlhaskell
.This should be verified with other clients, but I'm optimistic.
The bad news is that the code needs nontrivial changes. As far as I can tell from a quick look, we're actually matching the plugins on every request. But the language ID is only sent when the document is openened, so we'd need to store it somewhere.
fendor commentedon Apr 24, 2023
Storing should be possible, but I can't tell you right away what changes that requires 😅. I'll try to take a look.
voidus commentedon May 11, 2023
I've added a new Var to the ide state and I think I can get it threaded through.
voidus#1
(I opened the PR for easier feedback, but I didn't want to increase the noise here since it's still a very early draft)
I haven't really understood the test strategy yet, maybe I'll look into that when I find some more time.
From what I see, I get the impression that we can get away with carrying around very little state outside of the shake rules, which is great of course, but maybe this change would be time to refactor that a little?
Currently, we store whether files are modified and whether it's a file of interest. Fixing this would add the language ID.
Should we add a record to group this buffer information?
The bigger issue though is that with this change, we now need part of the global state (the language for the given file) to determine which plugin to run. Currently, we take the uri from the request. This seems like a significant complication for that part of the system.
I'd be happy to hear your thoughts on this, and I'll keep looking into this whenever I find some time.
I will need support though, and I am conscious of taking your time.
All in all, I don't think this feature is the biggest, most important thing. For me personally, it's at least partly an excuse to dig into a haskell codebase. If you don't have time for this (or just need a while to respond) that is completely okay with me.
Edit: It's interesting though that the params aren't needed anymore for deciding if a plugin should handle a request. Maybe this could be moved to startup? Can plugins be dynamically configured?
fendor commentedon May 21, 2025
Sorry, for some reason this got completely lost.
If you are still interested (after more than 2 years 😆 ), please open the PR against HLS itself, since I think part of why I missed it is because it is not a PR against upstream.
Otherwise, maybe we can get someone during ZuriHac to push this over the finish line.
Maybe @VeryMilkyJoe ?
Also, I think the PR looks pretty good.