Skip to content
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

HLS not working for file without .hs extension #3567

Open
voidus opened this issue Apr 20, 2023 · 8 comments
Open

HLS not working for file without .hs extension #3567

voidus opened this issue Apr 20, 2023 · 8 comments
Labels
can-workaround type: bug Something isn't right: doesn't work as intended, documentation is missing/outdated, etc..

Comments

@voidus
Copy link

voidus commented Apr 20, 2023

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.

@voidus voidus added status: needs triage type: bug Something isn't right: doesn't work as intended, documentation is missing/outdated, etc.. labels Apr 20, 2023
@fendor
Copy link
Collaborator

fendor commented 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 to do. 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
Copy link
Author

voidus commented 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
Copy link
Collaborator

fendor commented Apr 20, 2023

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?

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
Copy link
Author

voidus commented 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
Copy link
Collaborator

fendor commented 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 the languageId and adding a field to PluginDescriptor to add the languageId it accepts. Then, the type errors should be enough to guide you.
Every time you invoke pluginResponsible, you need to pass in the languageId field, which you can obtain from TextDocument.

@voidus
Copy link
Author

voidus commented Apr 23, 2023

Just did a small experiment with Debug.trace nvim lspconfig does indeed send either haskell, cabal or lhaskell.

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
Copy link
Collaborator

fendor commented 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
Copy link
Author

voidus commented 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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
can-workaround type: bug Something isn't right: doesn't work as intended, documentation is missing/outdated, etc..
Projects
None yet
Development

No branches or pull requests

2 participants