There are a couple of cases to handle as seen below.
Thanks @jneira for help discovering them all.
There used to be linking errors but I no longer see those after the multi-cradle patch
Non Nix
=========
The table below shows a couple of combinations of cradles and ghcide versions in a
non-Nix environment. All the version mismatches are now handled as follows:
- "Cannot satisfy package" - `-package-id` flags referencing
package versions not available (generally base)
- "bad interface" - tried to load an interface file created by a different version of ghc
cradle/ghcide | 8.6 | 8.8 | 8.10
--------------|-----|----|---
Cabal 8.6 | success | cannot satisfy package | cannot satisfy package
Cabal 8.8 | cannot satisfy package | success | cannot satisfy package
Cabal 8.10 | cannot satisfy package | cannot satisfy package | success
Stack 8.6 | success | bad-interface | bad-interfac-
Stack 8.8 | bad-interface | success | bad-interface
Stack 8.10 | bad-interface | bad-interface | success
Nix
=========
Because Nix redefines the libdir to point at the run-time ghc installation,
it's actually much easier to detect a version mismatch:
just compare the compile-time and run-time libdirs
* Initial benchmark suite, reusing ideas from Neil's post
https://neilmitchell.blogspot.com/2020/05/fixing-space-leaks-in-ghcide.html
* Add an experiment for code actions without edit
* formatting
* fix code actions bench script
* error handling + options + how to run
* extract Positions and clean up imports
(Neil's review feedback)
* replace with Extra.duration
* allow ImplicitParams
* add bench to the cradle
* applied @mpickering review feedback
* clean up after benchmark
* remove TODO
* Multi component support
In this commit we add support for loading multiple components into one
ghcide session.
The current behaviour is that each component is loaded lazily into the
session. When a file from an unrecognised component is loaded, the
cradle is consulted again to get a new set of options for the new
component. This will cause all the currently loaded files to be
reloaded into a new HscEnv which is shared by all the currently known
components. The result of this is that functions such as go-to
definition work between components if they have been loaded into the
same session but you have to open at least one file from each component
before it will work.
Only minimal changes are needed to the internals to ghcide to make the
file searching logic look in include directories for all currently
loaded components. The main changes are in exe/Main.hs which has been
heavily rewritten to avoid shake indirections. A global map is created
which maps a filepath to the HscEnv which should be used to compile it.
When a new component is created this map is completely refreshed so each
path maps to a new
Which paths belong to a componenent is determined by the targets listed
by the cradle. Therefore it is important that each cradle also lists all
the targets for the cradle. There are some other choices here as well
which are less accurate such as mapping via include directories which
is the aproach that I implemented in haskell-ide-engine.
The commit has been tested so far with cabal and hadrian.
Also deleted the .ghci file which was causing errors during testing and
seemed broken anyway.
Co-authored-by: Alan Zimmerman <alan.zimm@gmail.com>
Co-authored-by: fendor <power.walross@gmail.com>
* Final tweaks?
* Fix 8.4 build
* Add multi-component test
* Fix hlint
* Add cabal to CI images
* Modify path
* Set PATH in the right place (hopefully)
* Always generate interface files and hie files
* Use correct DynFlags in mkImportDirs
You have to use the DynFlags for the file we are currently compiling to
get the right packages in the package db so that lookupPackage doesn't
always fail.
* Revert "Always generate interface files and hie files"
This reverts commit 820aa24189.
* remove traces
* Another test
* lint
* Unset env vars set my stack
* Fix extra-source-files
As usual, stack doesn’t understand Cabal properly and doesn’t seem to
like ** wildcards so I’ve enumerated it manually.
* Unset env locally
Co-authored-by: Alan Zimmerman <alan.zimm@gmail.com>
Co-authored-by: fendor <power.walross@gmail.com>
Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>
* Update to hie-bios 0.5.0
* Fix test-cases due to changes in the direct cradle
* Update test/exe/Main.hs comment
Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>
Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>
* [#518] Build ghcide with GHC 8.10.1
Resolves#518
* Move CPP logic to the Compat module
* Revert changes to mkHieFile
* Add local fork of HieAst for 8.10.1
The fix for mkHieFile didn't make it into 8.10.1, so the override is still needed
* Ignore hlint in src-ghc810/HieAst.hs
* Whitelist CPP for Development.IDE.GHC.Orphans
* [#518] Build ghcide with GHC 8.10.1
Resolves#518
* Move CPP logic to the Compat module
* Revert changes to mkHieFile
* Add local fork of HieAst for 8.10.1
The fix for mkHieFile didn't make it into 8.10.1, so the override is still needed
* Ignore hlint in src-ghc810/HieAst.hs
* Whitelist CPP for Development.IDE.GHC.Orphans
* Plugin tests known broken in 8.10.1 (#556)
* Bump up ghc-check version
Co-authored-by: Pepe Iborra <pepeiborra@gmail.com>
Co-authored-by: pepe iborra <pepeiborra@gmail.com>
* Add a custom prefix to command IDs
A client can run more than one instance of ghcide. Some clients have a global
command registry, and all commands must be unique in that registry.
So to make the command ids unique, prefix them with the ghcide server process
id, as is done in haskell-ide-engine.
* Use same command naming scheme as in haskell-language-server
To ease interoperability
* Use makeLspCommandId for prefixing commands
This puts all the prefixing logic in one place.
* Add hlint exception for CPP in Development.IDE.Compat
* Bring in Win32 dependency for windows build
* Create rule to get ModSummary without parsing entire source file
* Load file source from disk if not available in memory
* Fix build after cherry pick
* Couple of fixes
- extract getModSummaryFromImports and fix diagnostics
- replace GetParsedModule by GetModSummary where possible
There is only one usage of GetParsedModule left, and that is in GetSpanInfos
for documentation. This the wrong approach, docs should be loaded from
interface files and not from sources. TODO
* Fix watched file tests
Progress notifications are not being sent anymore
* Compat with GHC 8.6
* Avoid parsing source files for completions and documentation
Instead, embed haddocks in interface files
* Allow CPP in module
* Force things after parsing in order to release buffers
* avoid holding on to stringbuffer unnecessarily
* Skip unnecessary file contents read
* Drop HscEnv requirement
* Add comments on forcing things
* Add comments on GHC_LIB restriction
* Parse files of interest twice to capture Haddock errors
If Opt_Haddock is not enabled we parse twice to capture Haddock parse errors
* Parallelize two-pass parsing
* Update src/Development/IDE/Core/Compile.hs
Co-authored-by: Marcelo Lazaroni <lazaronijunior@gmail.com>
Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>
* Expose codeAction and codeLens providers for haskell-language-server
Also tweak the code action reply type to generate well-formed JSON
* Expose moduleOutline for symbolProvider in hls too
* Revert to using [CAResult] rather than List CAResult
* Rules for loading interface files
* Typechecking with interface files
* Add a note in the README about the optimal project setup
* Improve support for hs-boot files
The branch was failing to load GHC because the module graph was missing
edges between a .hs file and its .hs-boot file. This means the .hs-boot
file was getting added into the HPT after the .hs file which led to
confusing errors about variables being out of scope.
The fix is to maintain a map from hs-boot to hs files and then add an
edge for this case when calling `transitiveDependencies`.
Also tidy up some code in setupEnv which I assume was attempting to fix
this but in an incorrect manner.
Add the -boot suffix when looking for hi-boot files.
For some reason, the `hi` path is not set to the right thing for
`hs-boot` files. I don't know why not perhaps it is ok to use an
existing `.hi` file in place of an `hs-boot` file. More investigation
needed. My experience is that GHC is quite bad a recompilation avoidance
for hs-boot files anyway.
For example: https://gitlab.haskell.org/ghc/ghc/issues/17434
Add the -boot suffix when writing interface files
* Generate .hi and .hie files during type checking
* Refactor GetModIface to not retain TypeChecked module in memory
This improves memory performance on a cold cache.
* Trailing whitespace
* Turn debug log messages into diagnostics
* Implement "hie" files for ghc-8.6.5
This means that the .hi files patch can also be used with 8.6.5
* Add tests for hover/definition on imported symbols
* hlints
* Generate .hie files when missing
* Fix subtle bug in setDefaultHieDir
* Simplify optimal project setup in README
* Move interface loading diagnostics behind --test flag
Reusing the --test flag for this seems harmless, I cannot justify introducing a
new flag
* Avoid expensive interface file generation for files of interest
* avoid redundant arguments (thanks Moritz K)
* qualify a DAML only comment
* Skip module source when generating hie file
thanks Moritz Kiefer for noting that we don't care for the generated .hie files
to embed module sources
* runGhcEnv <-> evalGhcEnv
* Apply suggestions from code review
Thanks Moritz Kiefer
Co-Authored-By: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>
* Add suggested Show instance
Co-Authored-By: Matthew Pickering <matthewtpickering@gmail.com>
* Use Control.Exception.Safe
This is to avoid accidentally capturing asynchronous exceptions
* Rename atomicFileUpdate
* Fix a flaky test
We have to be careful with module naming in tests to avoid interference of .hi
files across tests
* Undo formatting of D.IDE.GHC.Util
* follow changes in master
Co-authored-by: Matthew Pickering <matthewtpickering@gmail.com>
Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>
* Use custom version of h-l-t
* Use normalized path functions from h-l-t
* Restore empty path corner case
* Create a wrapper over NFP to override IsString
* Use maybe instead fromMaybe
* Use patched version of lsp-types in all yaml files
* Remove unused import
* Rename specific NormalizeFilePath to NormalizeFilePath'
* Remove specific newtype and IsString instance
* Use released haskell-lsp-0.21
* Adapt to type changes of haskell-lsp-0.21
* Add tags field to CompletionItem
* Fix test case about empty file path
* Correct stack.yaml used in azure ci cache
* Build ghcide including tests in windows azure ci
* Qualify haskell-lsp modules to avoid name clashes
* Suggest missing imports via package exports map
At the expense of some space and initialization time, suggest imports now is
able to find suggestions in all the packages available to the project.
* BadDependency - include the key in the error message
* remove the assumption that the GhcSession is always available
* fix bad spacing
Co-Authored-By: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>
* Add type annotation to clarify rule being defined
* Remove file dependency from PackageExports rule
* Guess patterns
Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>
* Refactor: extract Rules to a separate module
* Add tests for cradle loading
* Fix default extensions in exe target
* Move cradle loaded messages behind a flag
* Use satisfy
Following a suggestion by Moritz Kiefer (@cocreature)
We were calling runCradle multiple times per cradle, concurrently. For Cabal
cradles this function runs Cabal, which is neither fast nor designed to be run
concurrently
* Local hidir and hiedir folders to avoid conflicts with Cabal
hi files created by ghcide would have different optimization settings,
triggering Cabal recompilation if they were stored in Cabal folders
hie files would end up in the src folder as -hiedir is not set by Cabal
Telling GHC to write interface/hie files is pointless since we do it ourselves,
and it also leads to the recompilation checker getting confused
Using hie-bios initSession does things like setting up the cache directory for
interface files and other things which ghcide would rather manage itself.
* linker options
Co-authored-by: Matthew Pickering <matthewtpickering@gmail.com>
* Automatically pick up new dependencies
hie-bios's componentDependencies returns the dependencies of a cradle
that might change the cradle. Add those deps to the shake graph so that
the GHC session is newly created whenever they change.
For that, add a new rule type, GetHscEnvEq, to cache GHC sessions with
the key of GHC options and dependencies. And delete the optGhcSession
field from IdeOptions.
This is for https://github.com/digital-asset/ghcide/issues/50.
hie-bios's componentDependencies can return files that don't exist yet:
https://github.com/mpickering/hie-bios/blob/master/src/HIE/Bios/Types.hs#L90-L93.
This PR handles changes in the existing dependency files, but doesn't
handle newly created dependency files.
* address comments
* revert hie.yaml
* address more comments
* add test
* make direct cradles work; and use direct cradle in test
* parse lsp client configuration to track workspace roots
* Only use Watched files on workspace files
* Apply suggestions from code review
Co-Authored-By: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>
* Add tests for watched files
Left as future work: adding tests for workspace folder notifications
* Add a test for file creation outside workspace
Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>
We have been experiencing a few flaky tests in DAML caused by our CLI
compiler losing diagnostics. The reason for that is the debouncer
which meant that messages got delayed and not send before the process
exited.
This PR makes the debouncer abstract and adds a noopDebouncer which
doesn’t do any debouncing. This is also what we use in the terminal
ghcide test thingy.
* Require shake-0.18.4 which contains actionBracket
* Change progress reporting to use files rather than Shake nodes
* Remove inadvertantly writing down Shake twice
* Don't support old haddock-library versions
* Update stack.yaml values
* Remove some more haddock_library CPP
* Make sure the latest haddock-library is on GHC 8.4
* Enhancements to Haddock -> Markdown conversion
* Add tests for Haddock -> Markdown conversion
* Make HLint happy
* Let Haddock tests compile also in 8.4
* Fix build for 8.4
* Fix test for haddock-library 1.8.0
* Fix CPP problem
* Make tests a bit more readable
Co-authored-by: Moritz Kiefer <moritz.kiefer@purelyfunctional.org>
* Show kinds in hover
* Documentation on hover
* Enable kind tests
* Fix tests
* Print literals
* Show (some) overloaded literals
* Fix for 8.4
* Fix tests
* Do not consider literals for definitions
* Suggestions by @cocreature
* No warning for 8.4
* More fixes for 8.4
* Make it work with ghc-lib
* More fixes for warnings when compiled with ghc-lib
* More fixes to build in ghc-lib
* Try once again to build with ghc-lib
* More fixes for ghc-lib
* Fix warning with ghc-lib
* Improve hover performance by speeding up getFileExists
We touch the file system only the first time.
After that, we rely on the lsp client to tell us if a file is created or deleted
Fixes#101
* Remove JSON instances for completions, since we are not implementing "resolve"
* Remove completion resolve data from tests
* Better docs
* Fix tests
* Fix for 8.4
* Turn Haddock markup into Markdown
* Add types to completion items
* Make it work on 8.8 and 8.4
* Revert "Remove completion resolve data from tests"
This reverts commit 625d710f11.
* Revert "Remove JSON instances for completions, since we are not implementing "resolve""
This reverts commit 12ff27dce7.
* Fix tests
* Require higher version of regex-pcre-builtin
* Replace Pandoc with direct conversion from Haddock to Markdown
* Show kinds of type constructors too
* A few fixed to Markdown conversion
* Check optNewColonConvention
* Fix build on 8.4 and 8.8
* More fixes for 8.4 and 8.8
* Check only the common part of the completion text
* Make icons consistent with Outline
* Test docs for completions
* Make constructors return the corresponding CompletionItem + tests for that behavior
* Make test work on 8.4
* Document symbols provider
* Compatibility with GHC 8.4
* Replace large number with more descriptive maxBound
Co-Authored-By: Andreas Herrmann <42969706+aherrmann-da@users.noreply.github.com>
* Use SkFunction for all Val Declarations
* Improve outlining of PatBind and FunBind
No longer relying on gfindtype
Co-authored-by: Andreas Herrmann <42969706+aherrmann-da@users.noreply.github.com>
* Test for #45
* Remove redundant symbols from imports
Fixes#45
* Update src/Development/IDE/LSP/CodeAction.hs
Co-Authored-By: Andreas Herrmann <42969706+aherrmann-da@users.noreply.github.com>
* Apply suggestions from code review
Co-Authored-By: Andreas Herrmann <42969706+aherrmann-da@users.noreply.github.com>
* Add regex-tdfa extra deps to ghc-lib build
* Fix for GHC 8.4 (error message prints qualified binding)
GHC ticket #14881 changed this to print identifiers unqualified
* dropBindingsFromImportLine: make total
Co-authored-by: Andreas Herrmann <42969706+aherrmann-da@users.noreply.github.com>
* Initial implementation of completion support
* Add fuzzy to set of additional dependencies in 8.8
* Fix test
* Work a bit more on completion
* Attempt at getting completions from last good tckd module
* Revert "Attempt at getting completions from last good tckd module"
This reverts commit 04ca13b9d8.
* "useWithStale" everywhere
* Some suggestions by @cocreature
* Adjust positions in the document
* Start working on tests
* Fix compilation problem
* Fix tests
* Better type tests
The process of searching for definitions is similar to the process of searching
for hover information. In the original code (much of which was written out twice
with occasional stylistic differences) the signal to noise ratio seemed pretty
poor.
Here is a refactoring which aims to make it easier to see the similarities and
differences between these two related functionalities.
* Support plugins
Call initializePlugins before running typecheck.
* call initializePlugins only for GHC >= 8.6
initializePlugins doesn't exist in older GHC versions.
* A separate function for initializing plugins
* Add a test for plugins
* Move sample code out into into separate source file
* Add test/data/GotoHover.hs to cabal extra-source-files
* hlint: explicit module export list
* hlint: implement and use readFileUtf8
* hlint: remove -Wmissing-signatures
* Hack around https://github.com/mpickering/hie-bios/pull/56 - hie-bios expects files to really exist on disk
* Fix getLocatedImportsRule to pass the file to the session
* Add support for multiple simultaneous hie.yaml files.
Also rewrites the user experience on setup to be less verbose.
Also adds masking for GHC session construction.
* HLint
* Code review comments
* Switch to the Strict map
* Add code action for filling type holes
* Incorporate hole name into action title
Useful if more than one hole appears on the same line. Not so useful
if both of these holes are just `_` rather than `_name` (or more than
one hole on the same line has the same `_name`): In which case perhaps
some numbers could be attached to the action titles, to distinguish
the holes. But I suspect that this would not be worth the effort.
* Add tests for fill-type-hole actions
* Disable two tests on GHC 8.4
These test hints about local bindings, whic GHC 8.4 does not provide.
* Replace compilerVersion with new MIN_GHC_API_VERSION macro
Previously we had a mix of GHC_STABLE and checks on
__GLASGOW_HASKELL__. This PR changes this to always check on
MIN_GHC_API_VERSION. Depending on whether you use ghc-lib or not (now
controlled by a cabal flag), this macro expands to MIN_VERSION_ghc or
MIN_VERSION_ghc_lib.
* Rename hie-core to ghcide
The name `hie-core` has caused a lot of confusion as to how we relate
to haskell-ide-engine so changing it should hopefully help with that.
I also think that ghcide is still a good name once we hopefully
integrate with haskell-ide-engine more closely.
The name ghcide seems to have a reasonable amount of support on
Twitter https://twitter.com/ndm_haskell/status/1170681262987710464
which is of course the only good way to come up with names.
* Add a readme that points people to the new directory.
* Fix bogus replacements
* Use a proper link
* links are hard