haskell / haskell-language-server

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

LSP project root vs hie-bios cradle #3043

Open andreabedini opened 2 years ago

andreabedini commented 2 years ago

HLS uses hie-bios to set up a GHC API session appropriate for the project. From hie-bios, hls inherits the hie.yaml which is a way to explicitly describe what kind of project we have (e.g. cabal or stack).

In particular hie-bios will use hie.yaml to determine the project root directory as described in https://github.com/haskell/hie-bios#explicit-configuration. hie-bios will refer to this directory as the "cradle".

I claim hie-bios cradle detection can get hls confused.

Hopefully reproducible example:

mkdir tmp tmp/a tmp/b
cd tmp
(cd a; cabal init -n -m)
(cd b; cabal init -n -m)
echo 'packages: a b' > cabal.project
echo 'cradle: { cabal: null }' >> hie.yaml
cd a
haskell-language-server-wrapper app/Main.hs 

this fails with

Found "/home/andrea/tmp/hie.yaml" for "/home/andrea/tmp/a/a"
Run entered for haskell-language-server-wrapper(haskell-language-server-wrapper) Version 1.7.0.0 x86_64 ghc-9.2.2
Current directory: /home/andrea/tmp/a
Operating system: linux
Arguments: ["app/Main.hs"]
Cradle directory: /home/andrea/tmp
Cradle type: Cabal

Tool versions found on the $PATH
cabal:      3.8.0.20220526
stack:      2.7.5
ghc:        8.10.7

Consulting the cradle to get project GHC version...
Project GHC version: 8.10.7
haskell-language-server exe candidates: ["haskell-language-server-8.10.7","haskell-language-server"]
Launching haskell-language-server exe at:/home/andrea/.ghcup/bin/haskell-language-server-8.10.7
2022-07-15T14:02:42.893354Z | Info | No log file specified; using stderr.
2022-07-15T14:02:42.893709Z | Info | haskell-language-server version: 1.7.0.0 (GHC: 8.10.7) (PATH: /home/andrea/.ghcup/hls/1.7.0.0/lib/haskell-language-server-1.7.0.0/bin/haskell-language-server-8.10.7)
2022-07-15T14:02:42.893992Z | Info | Directory: /home/andrea/tmp
2022-07-15T14:02:42.894096Z | Info | Logging heap statistics every 60.00s
 ghcide setup tester in /home/andrea/tmp.
Report bugs at https://github.com/haskell/haskell-language-server/issues

Step 1/4: Finding files to test in /home/andrea/tmp
haskell-language-server-8.10.7: app/Main.hs: getDirectoryContents:openDirStream: does not exist (No such file or directory)

My reading is that the hie.yaml is what determines the crade directory but hls assumes that is the current directory, which is false.

Another symptom of the confusion appears using neovim and lsp-config: after opening nvim app/Main.hs from the tmp/a directory; LspInfo informs me the root is tmp/a (as determined by the client, neovim) but the cache gets created in ~/.cache/hie-bios/dist-tmp-....

ring @michaelpj

michaelpj commented 2 years ago

Yeah, there's clearly some confusion between the workspace root that the client sends us and us auto-detecting something based on hie.yaml. I'm not 100% sure what the correct behaviour is.

michaelpj commented 2 years ago

We think the problem may actually be that the HLS changes directory to the root directory immediately. And then the relative path app/Main.hs no longer points to the right place. The fix should be easy: when we parse the filepath arguments on the command line, we should absolutize/canonicalize them immediately.