Haskell Language Server 2.15.0.0 is now available

The HLS team is excited to announce the release 2.15.0.0 of the Haskell Language Server.

Binaries for this release are available at
Index of /~hls/haskell-language-server-2.15.0.0/.

These binaries can be installed using GHCup, using the vanilla metadata channel.

WARNING: Only use this if you also installed GHC via the vanilla channel.

ghcup --url-source=https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-vanilla-0.1.0.yaml install hls 2.15.0.0

All of these tarballs have associated GPG signatures. The signature should be from Hannes Siebenhandl <hannes.siebenhandl@posteo.net> (key ID 9849506453CA97E75F505D054EF829564CA34FC8).

The prebuilt binaries in this release support the following GHC versions:

  • GHC 9.14.1
  • GHC 9.12.4
  • GHC 9.12.2
  • GHC 9.10.3
  • GHC 9.8.4
  • GHC 9.6.7

2.15.0.0

This release brings some much-needed performance improvements to the startup time in large projects and fixes issues with multiple home unit support.

In this release, we are excited to introduce two brand new plugins:

Last but not least, this release adds support for whole project loading which you can opt into by setting the option haskell.componentLoading: "multi: whole-project".
This allows you to load the whole Haskell project into your editor at once.
The option haskell.sessionLoading is deprecated but HLS 2.15.0.0 honours it regardless. If both haskell.componentLoading and haskell.sessionLoading are set, then the former is preferred.

An in-depth summary of these changes will be posted to https://blog.haskell.org/ soon.

Changes

  • Remove hls-retrie-plugin
  • Add hls-case-split-plugin for GHC 9.14 only
  • Add hls-export-plugin
  • Enable hls-semantic-tokens-plugin by default
  • Prefer multi-component loading by default
  • Replace the sessionLoading config with componentsLoading
  • Support for Ormolu and Fourmolu on GHC 9.14
  • Improvements to ghcide
    • Point documentation and source links at Hackage
    • Stop unloading all bytecode whenever new bytecode is generated
    • Unload linkables when any transitive dependency changes
  • Improvements to hls-rename-plugin
    • Improved limited cross-module renaming
  • Improvements to hls-refactor-plugin
    • Code action to delete all unused bindings, including let bindings
  • Improvements to hls-eval-plugin
    • Capture stdout and stderr from evaluated expressions
  • Improvements to hls-splice-plugin
    • Support declaration splices
  • Optimizations
    • Speed up dependency graph building
    • Load core files on demand and improve freshness checking
  • Bug fixes
    • Correct code action edits across several plugins
    • Match GHC when resolving imports and boot files
    • Avoid serving stale completions, documentation and diagnostics

See the plugin support table and GHC version support table for an overview of supported GHC versions and plugins.

Full Changelog is available on GitHub: Release 2.15.0.0 · haskell/haskell-language-server · GitHub

We thank @crtschin for effortlessly managing this release!

32 Likes

That’s a very fast turnaround on the case splitting plugin!

3 Likes

Out of curiosity, what’s there a reason the case splitting isn’t available for previous GHC versions?

The GHC AST exactprint annotations change for each major version in some ways.
This can cause considerable churn and make it hard to work on older GHC versions.

We wanted this plugin to be rock-solid first, with maintainability as the primary goal and an exhaustive test suite, and then expand support for other GHC versions.
Otherwise, the GSoC project might not have successful as you need to do exactprint annotation fine tuning for each GHC version.
We hope, that updating the plugin for new GHC versions is going to be easier/possible.

However, this is not to say that a motivated contributor couldn’t try to add support for GHC 9.12 or 9.10, for example at MuniHac 2026 :wink:

10 Likes

What @fendor said is true, but I’ll add a couple of details:

  • I’m pretty sure I’ve tried running the tests I’ve written for the plugin with -w ghc-9.12.2, and something fails precisely because of changes in the exactprint annotations; I don’t remember what exactly, but I’ve just launched a build&test, and I’ll update this message if any understandable “look at how it would be comeplicated” comes up;
    • well, it didn’t even get as far as compiling successfully:
      [1 of 1] Compiling Ide.Plugin.CaseSplit ( plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs, dist-newstyle/build/x86_64-linux/ghc-9.12.2/haskell-language-server-2.14.0.0/l/hls-case-split-plugin/build/hls-case-split-plugin/Ide/Plugin/CaseSplit.o, dist-newstyle/build/x86_64-linux/ghc-9.12.2/haskell-language-server-2.14.0.0/l/hls-case-split-plugin/build/hls-case-split-plugin/Ide/Plugin/CaseSplit.dyn_o )
      plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs:104:57: error: [GHC-61689]
          Module ‘Development.IDE.GHC.Compat’ does not export ‘HoleKind’.
          |
      104 |                                                         HoleKind (HoleVar),
          |                                                         ^^^^^^^^^^^^^^^^^^
      
      plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs:147:57: error: [GHC-61689]
          Module ‘GHC.Hs’ does not export ‘unnamedHoleRdrName’.
          |
      147 |                                                         unnamedHoleRdrName)
          |                                                         ^^^^^^^^^^^^^^^^^^
      
      plugins/hls-case-split-plugin/src/Ide/Plugin/CaseSplit.hs:185:57: error: [GHC-10237]
          In the import of ‘Language.Haskell.Syntax.Expr’:
            an item called ‘HsExpr’ is exported, but it does not export any children
            (constructors, class methods or field names) called ‘HsHole’.
          |
      185 |                                                         HsExpr (HsCase, HsHole, HsLam),
          |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      
  • furthermore, during the second half (in chronologial sense) of the project, I discovered a bug in ghc-exactprint, as you can see from this message and following ones from @alanz , who fixed the bug here; that bug hasn’t been backported, so I have a dependency on a recent enough ghc-exactprint, which in turn means ghc-9.14 or later.

That’s to say that making the plugin work for earlier GHC versions, means

  1. backporting that solution to one-or-more earlier versions of ghc-exactprint (the fix is a 1-word fix, but I don’t know what impacts it has),
  2. changing possibly quite a bit of core logic of the plugin to handle older EP annotations, both in compile-time terms (see compilation errors above), and in run-time terms (what I’ve alluded to above, but I can’t show any example if I don’t fix the compilation errors first, ahah).
5 Likes

Lot of great stuff here!

I’ve been trying out the new multi-component-loading stuff ("haskell.componentsLoading": "multi: whole-project" in VSCode) for a few weeks and it seems rock-solid already. Looking forward to that becoming the default.

And I’d been waiting years for case splitting to make a comeback. Now I don’t need to be so defensive about Haskell editor tooling around Rust and Agda people. It does seem a bit odd that we’re using unicode arrows, even with -XNoUnicodeSyntax? But I’m sure stuff like this will get ironed out.

Also, HLS Ormolu/Fourmolu support was the last thing stopping me from bumping most of my projects to GHC 9.14, so it’s nice to see that finally land.

Finally, I think “Improvements to hls-splice-plugin” is quite an understatement. Isn’t this the first release in years to include the plugin at all?

5 Likes

Definitely an understatement, very good work on this in #4915! I may have been a bit too summary when making the summary :sweat_smile:

2 Likes

Ha, thanks. I didn’t mean to sound like I was fishing for praise!

Anyway, hopefully the plugin being back and mostly working encourages someone to pick up the work I started on qualifying names. Then we can have dumped splices that always actually compile. I’ve lost my main motivation for this stuff personally, due to the end of a particular work project. And TH internals and the ghc-exactprint API are not exactly things I’m an expert on.

Unicode arrows should only be used if the UnicodeSyntax extension is given, the tests definitely don’t use unicode arrows everywhere :thinking:

EDIT, I see, there is File local `{-# LANGUAGE NoUnicodeSyntax #-}` is mistakenly ignored by case-split plugin if the owning stanza in the .cabal file has `default-extensions: UnicodeSyntax` · Issue #5067 · haskell/haskell-language-server · GitHub

Will this nor support the upcoming GHC 9.14.2? Which was supposed to be released on 13th Aug ?

I don’t know, the code base wasn’t tested with GHC 9.14.2 rcs to the best of my knowledge.
If the codebase compiles and tests are green, then yes, we might add binaries for 9.14.2 via ghcup revisions.

However, we can only say for certain once 9.14.2 is released.

1 Like

Okayy; I want to test the bug fix of Broken Documentation Links in VScode/Emacs which add a cryptic 4 letter hex code in urls

1 Like