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 368 forks source link

Find all references does not find all references #3147

Open eltix opened 2 years ago

eltix commented 2 years ago

Your environment

Which OS do you use?

Ubuntu 20.04

Which version of GHC do you use and how did you install it?

GHC 9.2.3

How is your project built (alternative: link to the project)?

Nix+bazel

Which LSP client (editor/plugin) do you use?

We're using VSCode with the Haskell plugin

Steps to reproduce

In any project, "Find all references" does not reference files that have not been indexed by HLS. From what we've empirically inferred, it seems that HLS only lists the references appearing in already indexed files and indexing is lazy. Files that have never been indexed (because they're leaves of the dependency tree and have never been opened in the editor) are off the radar. After opening said files, "Find all references" does list all the references. This kind of defeats the purpose of the feature since one has first to Ctrl-Shift-F the function of interest, open the search hits in the editor and then use the "Find all references". The fact that one cannot "trust" the result of "Find all references" because it depends on the history of opened files in the editor is a problem. It would be more accurate to call the feature "Find some references (warning: lazy search)" or something similar.

Expected behaviour

One would expect "Find all references" to find all references

Actual behaviour

"Find all references" does not find all references.

wz1000 commented 2 years ago

HLS tries to typecheck/index all files on startup by default (though this is configurable). However, this depends on us knowing all the targets which exist, which need to be enumerated by the hie-bios cradle. I think cabal and stack cradles do this by default. You should check that your cradle lists out all the targets (module names or file names) in the options that it passes to HLS, using something like hie-bios flags src/File.hs

kokobd commented 2 years ago

Maybe we should have an option to load all components on start by default?

eltix commented 2 years ago

@wz1000 Thank you for your answer. We will investigate this further on our side and will either come back with more info or close the issue.

guibou commented 1 year ago

I can confirm that all the files and flags are correctly passed to HLS using a hie.yaml file as simple as:

cradle:
  bios:
    shell: "generate_flags_for_project > $HIE_BIOS_OUTPUT"

The generate_flags_for_project generate a static list of flags: it does not depend on the file being observed and always return the flags / files for the complete project.

Even when waiting for the end of the indexing phase from HLS (It can take a few minutes), the different references from other files are not available.

However, as @eltix already described it, opening a file which contains a reference fix the reference informations. I also observed that removing the symbol we care about from export list of the module then adding it again does "update" the DB.

guibou commented 1 year ago

The problem is perfectly reproducible when the use of the symbol is in a Main module and when you have multiples Main module in the environment. I'm still trying to reproduce this in a different context.

In https://github.com/haskell/haskell-language-server/commit/89a3e627e6f6b9d5646811cad04c7e68334f80b9 I designed a reproduction.

There are two non-Main modules: dirA/A.hs and dirB/B.hs which are named A and B.

Then C.hs and D.hs are Main modules which reference a and b from A and B. Note that a is also referenced in B.

I observed the hiedb file and it is interesting:

After opening A.hs the first time, it shows a reference in Main at line 13.

hiedb -D ~/.cache/ghcide/1634d290c00070ae2b558ef43dc6d2a8855d6436-hls_repro_reverse_search-9.0.2-1.hiedb name-refs a
B:5:5-5:6
Main:13:10-13:11
A:3:1-3:2

But after opening C.hs, the reference change:

hiedb -D ~/.cache/ghcide/1634d290c00070ae2b558ef43dc6d2a8855d6436-hls_repro_reverse_search-9.0.2-1.hiedb name-refs a
B:5:5-5:6
A:3:1-3:2
Main:5:10-5:11

My conclusion here is that references are stored in the db using module name, and if we have multiples modules with the same name, this leads to conflict.

Should this be considered a bug in HLS or a bug in the way we are using HLS?