diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,74 @@
 # Changelog for haskell-language-server
 
+
+## 2.11.0.0
+
+- Bindists for GHC 9.12.2
+  - Full plugin support, inlcuding refactor plugin
+- Bindists for GHC 9.10.2
+- Bindists for GHC 9.8.4
+- Bindists for GHC 9.6.7
+- Bindists for GHC 9.4.8
+- Dropped support for Centos 7 as this platform is no longer supported by ghc
+- Improved import suggestions for contructors and OverloadedRecordDot fields
+
+### Pull Requests
+
+- Add doc for project-wide renaming
+  ([#4584](https://github.com/haskell/haskell-language-server/pull/4584)) by @jian-lin
+- Use hie-bios 0.15.0
+  ([#4582](https://github.com/haskell/haskell-language-server/pull/4582)) by @fendor
+- Allow building HLS with GHC 9.10.2
+  ([#4581](https://github.com/haskell/haskell-language-server/pull/4581)) by @fendor
+- Fix Plugin support table for 9.12.2
+  ([#4580](https://github.com/haskell/haskell-language-server/pull/4580)) by @fendor
+- Fix misplaced inlay hints by applying PositionMapping
+  ([#4571](https://github.com/haskell/haskell-language-server/pull/4571)) by @jetjinser
+- Enable hls-plugin-gadt for ghc-9.12
+  ([#4568](https://github.com/haskell/haskell-language-server/pull/4568)) by @GuillaumedeVolpiano
+- Remove no longer needed allow-newer
+  ([#4566](https://github.com/haskell/haskell-language-server/pull/4566)) by @jhrcek
+- Add missing golden files for GHC 9.10 config tests
+  ([#4563](https://github.com/haskell/haskell-language-server/pull/4563)) by @jian-lin
+- updating the plugins support table for refactor
+  ([#4560](https://github.com/haskell/haskell-language-server/pull/4560)) by @GuillaumedeVolpiano
+- Enable stylish-haskell for ghc-9.10 and ghc-9.12
+  ([#4559](https://github.com/haskell/haskell-language-server/pull/4559)) by @GuillaumedeVolpiano
+- Bump haskell-actions/setup from 2.7.10 to 2.7.11
+  ([#4557](https://github.com/haskell/haskell-language-server/pull/4557)) by @dependabot[bot]
+- Provide code action in hls-eval-plugin
+  ([#4556](https://github.com/haskell/haskell-language-server/pull/4556)) by @jian-lin
+- enable hlint for ghc-9.12
+  ([#4555](https://github.com/haskell/haskell-language-server/pull/4555)) by @GuillaumedeVolpiano
+- Enable fourmolu and ormolu for GHC 9.12
+  ([#4554](https://github.com/haskell/haskell-language-server/pull/4554)) by @fendor
+- Enable hls-cabal-gild-plugin for GHC 9.12.2
+  ([#4553](https://github.com/haskell/haskell-language-server/pull/4553)) by @fendor
+- Update plugin support table for GHC 9.12.2
+  ([#4552](https://github.com/haskell/haskell-language-server/pull/4552)) by @fendor
+- Remove allow-newer for hiedb
+  ([#4551](https://github.com/haskell/haskell-language-server/pull/4551)) by @jhrcek
+- Fix typo of rename plugin config
+  ([#4546](https://github.com/haskell/haskell-language-server/pull/4546)) by @jian-lin
+- Update the ghcup-metadata generation script
+  ([#4545](https://github.com/haskell/haskell-language-server/pull/4545)) by @fendor
+- porting hls-refactor to ghc-9.12
+  ([#4543](https://github.com/haskell/haskell-language-server/pull/4543)) by @GuillaumedeVolpiano
+- add ghcide-bench flag to .cabal file
+  ([#4542](https://github.com/haskell/haskell-language-server/pull/4542)) by @juhp
+- Revert "link executables dynamically to speed up linking (#4423)"
+  ([#4541](https://github.com/haskell/haskell-language-server/pull/4541)) by @fendor
+- Support PackageImports in hiddenPackageSuggestion
+  ([#4537](https://github.com/haskell/haskell-language-server/pull/4537)) by @jian-lin
+- Improve FreeBSD installation docs
+  ([#4536](https://github.com/haskell/haskell-language-server/pull/4536)) by @arrowd
+- reinstating ignore-plugins-ghc-bounds
+  ([#4532](https://github.com/haskell/haskell-language-server/pull/4532)) by @GuillaumedeVolpiano
+- Simplify FuzzySearch test (avoid dependency on /usr/share/dict/words)
+  ([#4531](https://github.com/haskell/haskell-language-server/pull/4531)) by @jhrcek
+- Import suggestion for missing newtype constructor, all types constructor and indirect overloadedrecorddot fields
+  ([#4516](https://github.com/haskell/haskell-language-server/pull/4516)) by @guibou
+
 ## 2.10.0.0
 
 - Bindists for GHC 9.12.2
diff --git a/ghcide-test/data/watched-files/reload/reload.cabal b/ghcide-test/data/watched-files/reload/reload.cabal
new file mode 100644
--- /dev/null
+++ b/ghcide-test/data/watched-files/reload/reload.cabal
@@ -0,0 +1,12 @@
+cabal-version:      2.4
+name:               reload
+version:            0.1.0.0
+author:             Lin Jian
+maintainer:         me@linj.tech
+build-type:         Simple
+
+library
+  exposed-modules:  MyLib
+  build-depends:    base
+  hs-source-dirs:   src
+  default-language: Haskell2010
diff --git a/ghcide-test/data/watched-files/reload/src/MyLib.hs b/ghcide-test/data/watched-files/reload/src/MyLib.hs
new file mode 100644
--- /dev/null
+++ b/ghcide-test/data/watched-files/reload/src/MyLib.hs
@@ -0,0 +1,6 @@
+module MyLib (someFunc) where
+
+import Data.List.Split
+
+someFunc :: IO ()
+someFunc = putStrLn "someFunc"
diff --git a/ghcide-test/exe/FuzzySearch.hs b/ghcide-test/exe/FuzzySearch.hs
--- a/ghcide-test/exe/FuzzySearch.hs
+++ b/ghcide-test/exe/FuzzySearch.hs
@@ -1,130 +1,52 @@
 module FuzzySearch (tests) where
 
-import           Data.Char                  (toLower)
-import           Data.Maybe                 (catMaybes)
-import qualified Data.Monoid.Textual        as T
-import           Data.Text                  (Text, inits, pack)
-import qualified Data.Text                  as Text
-import           Prelude                    hiding (filter)
-import           System.Directory           (doesFileExist)
-import           System.IO.Unsafe           (unsafePerformIO)
-import           Test.QuickCheck
+import           Data.Maybe            (isJust, mapMaybe)
+import           Data.Text             (Text)
+import qualified Data.Text             as Text
+import           Prelude               hiding (filter)
 import           Test.Tasty
-import           Test.Tasty.ExpectedFailure
-import           Test.Tasty.QuickCheck      (testProperty)
-import qualified Text.Fuzzy                 as Fuzzy
-import           Text.Fuzzy                 (Fuzzy (..))
+import           Test.Tasty.HUnit
+import           Test.Tasty.QuickCheck
 import           Text.Fuzzy.Parallel
 
 tests :: TestTree
 tests =
   testGroup
     "Fuzzy search"
-    [ needDictionary $
-        testGroup
-          "match works as expected on the english dictionary"
-          [ testProperty "for legit words" propLegit,
-            testProperty "for prefixes" propPrefix,
-            testProperty "for typos" propTypo
-          ]
+    [ testGroup "match"
+        [ testCase "empty" $
+            match "" "" @?= Just 0
+        , testCase "camel case" $
+            match "myImportantField" "myImportantField" @?= Just 262124
+        , testCase "a" $
+            mapMaybe (matchInput "a") ["", "a", "aa", "aaa", "A", "AA", "aA", "Aa"]
+              @?= [("a",3),("aa",3),("aaa",3),("aA",3),("Aa",1)]
+        ,  testCase "lowercase words" $
+            mapMaybe (matchInput "abc") ["abc", "abcd", "axbc", "axbxc", "def"]
+              @?= [("abc", 25), ("abcd", 25), ("axbc", 7), ("axbxc", 5)]
+        , testCase "lower upper mix" $
+            mapMaybe (matchInput "abc") ["abc", "aBc", "axbC", "axBxC", "def"]
+              @?= [("abc", 25), ("aBc", 25), ("axbC", 7), ("axBxC", 5)]
+        , testCase "prefixes" $
+            mapMaybe (matchInput "alpha") (Text.inits "alphabet")
+              @?= [("alpha", 119), ("alphab", 119), ("alphabe", 119), ("alphabet", 119)]
+        , testProperty "x `isSubsequenceOf` y => match x y returns Just"
+            prop_matchIfSubsequence
+        ]
     ]
-
-test :: Text -> Bool
-test candidate = do
-  let previous =
-        catMaybes
-          [ (d,) . Fuzzy.score
-              <$> referenceImplementation candidate d "" "" id
-            | d <- dictionary
-          ]
-      new = catMaybes [(d,) <$> match candidate d | d <- dictionary]
-  previous == new
-
-propLegit :: Property
-propLegit = forAll (elements dictionary) test
-
-propPrefix :: Property
-propPrefix = forAll (elements dictionary >>= elements . inits) test
-
-propTypo :: Property
-propTypo = forAll typoGen test
-
-typoGen :: Gen Text
-typoGen = do
-  w <- elements dictionary
-  l <- elements [0 .. Text.length w -1]
-  let wl = Text.index w l
-  c <- elements [ c | c <- ['a' .. 'z'], c /= wl]
-  return $ replaceAt w l c
-
-replaceAt :: Text -> Int -> Char -> Text
-replaceAt t i c =
-  let (l, r) = Text.splitAt i t
-   in l <> Text.singleton c <> r
-
-dictionaryPath :: FilePath
-dictionaryPath = "/usr/share/dict/words"
-
-{-# ANN dictionary ("HLint: ignore Avoid restricted function" :: String) #-}
-{-# NOINLINE dictionary #-}
-dictionary :: [Text]
-dictionary = unsafePerformIO $ do
-  existsDictionary <- doesFileExist dictionaryPath
-  if existsDictionary
-    then map pack . words <$> readFile dictionaryPath
-    else pure []
-
-referenceImplementation :: forall s t.
-  (T.TextualMonoid s) =>
-  -- | Pattern in lowercase except for first character
-  s ->
-  -- | The value containing the text to search in.
-  t ->
-  -- | The text to add before each match.
-  s ->
-  -- | The text to add after each match.
-  s ->
-  -- | The function to extract the text from the container.
-  (t -> s) ->
-  -- | The original value, rendered string and score.
-  Maybe (Fuzzy t s)
-referenceImplementation pat' t pre post extract =
-  if null pat then Just (Fuzzy t result totalScore) else Nothing
   where
-    null :: (T.TextualMonoid s) => s -> Bool
-    null = not . T.any (const True)
+    matchInput :: Text -> Text -> Maybe (Text, Int)
+    matchInput needle candidate = (candidate,) <$> match needle candidate
 
-    s = extract t
-    (totalScore, _currScore, result, pat, _) =
-      T.foldl'
-        undefined
-        ( \(tot, cur, res, pat, isFirst) c ->
-            case T.splitCharacterPrefix pat of
-              Nothing -> (tot, 0, res <> T.singleton c, pat, isFirst)
-              Just (x, xs) ->
-                -- the case of the first character has to match
-                -- otherwise use lower case since the pattern is assumed lower
-                let !c' = if isFirst then c else toLower c
-                 in if x == c'
-                      then
-                        let cur' = cur * 2 + 1
-                         in ( tot + cur',
-                              cur',
-                              res <> pre <> T.singleton c <> post,
-                              xs,
-                              False
-                            )
-                      else (tot, 0, res <> T.singleton c, pat, isFirst)
-        )
-        ( 0,
-          1, -- matching at the start gives a bonus (cur = 1)
-          mempty,
-          pat',
-          True
-        )
-        s
+prop_matchIfSubsequence :: Property
+prop_matchIfSubsequence =
+  forAll genNonEmptyText $ \haystack ->
+    forAll (genSubsequence haystack) $ \needle ->
+        isJust (match needle haystack)
+  where
+    genNonEmptyText =
+      Text.pack <$> listOf1 (elements $ ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'])
 
-needDictionary :: TestTree -> TestTree
-needDictionary
-  | null dictionary = ignoreTestBecause ("not found: " <> dictionaryPath)
-  | otherwise = id
+    genSubsequence :: Text -> Gen Text
+    genSubsequence =
+        fmap Text.pack . sublistOf . Text.unpack
diff --git a/ghcide-test/exe/UnitTests.hs b/ghcide-test/exe/UnitTests.hs
--- a/ghcide-test/exe/UnitTests.hs
+++ b/ghcide-test/exe/UnitTests.hs
@@ -29,8 +29,6 @@
 import           System.IO.Extra                   hiding (withTempDir)
 import           System.Mem                        (performGC)
 import           Test.Hls                          (IdeState, def,
-                                                    ignoreForGhcVersions,
-                                                    GhcVersion(..),
                                                     runSessionWithServerInTmpDir,
                                                     waitForProgressDone)
 import           Test.Tasty
diff --git a/ghcide-test/exe/WatchedFileTests.hs b/ghcide-test/exe/WatchedFileTests.hs
--- a/ghcide-test/exe/WatchedFileTests.hs
+++ b/ghcide-test/exe/WatchedFileTests.hs
@@ -3,11 +3,14 @@
 
 module WatchedFileTests (tests) where
 
-import           Config                          (testWithDummyPluginEmpty')
+import           Config                          (mkIdeTestFs,
+                                                  testWithDummyPlugin',
+                                                  testWithDummyPluginEmpty')
 import           Control.Applicative.Combinators
 import           Control.Monad.IO.Class          (liftIO)
 import qualified Data.Aeson                      as A
 import qualified Data.Text                       as T
+import qualified Data.Text.IO                    as T
 import           Development.IDE.Test            (expectDiagnostics)
 import           Language.LSP.Protocol.Message
 import           Language.LSP.Protocol.Types     hiding
@@ -18,6 +21,7 @@
 import           Language.LSP.Test
 import           System.Directory
 import           System.FilePath
+import           Test.Hls.FileSystem
 import           Test.Tasty
 import           Test.Tasty.HUnit
 
@@ -69,6 +73,17 @@
         sendNotification SMethod_WorkspaceDidChangeWatchedFiles $ DidChangeWatchedFilesParams
                [FileEvent (filePathToUri $ sessionDir </> "B.hs") FileChangeType_Changed ]
         expectDiagnostics [("A.hs", [(DiagnosticSeverity_Error, (3, 4), "Couldn't match expected type '()' with actual type 'Int'", Just "GHC-83865")])]
+      , testWithDummyPlugin' "reload HLS after .cabal file changes" (mkIdeTestFs [copyDir ("watched-files" </> "reload")]) $ \sessionDir -> do
+          let hsFile = "src" </> "MyLib.hs"
+          _ <- openDoc hsFile "haskell"
+          expectDiagnostics [(hsFile, [(DiagnosticSeverity_Error, (2, 7), "Could not load module \8216Data.List.Split\8217", Nothing)])]
+          let cabalFile = "reload.cabal"
+          cabalContent <- liftIO $ T.readFile cabalFile
+          let fix = T.replace "build-depends:    base" "build-depends:    base, split"
+          liftIO $ T.writeFile cabalFile (fix cabalContent)
+          sendNotification SMethod_WorkspaceDidChangeWatchedFiles $ DidChangeWatchedFilesParams
+            [ FileEvent (filePathToUri $ sessionDir </> cabalFile) FileChangeType_Changed ]
+          expectDiagnostics [(hsFile, [])]
     ]
   ]
 
diff --git a/haskell-language-server.cabal b/haskell-language-server.cabal
--- a/haskell-language-server.cabal
+++ b/haskell-language-server.cabal
@@ -1,7 +1,7 @@
 cabal-version:      3.4
 category:           Development
 name:               haskell-language-server
-version:            2.10.0.0
+version:            2.11.0.0
 synopsis:           LSP server for GHC
 description:
   Please see the README on GitHub at <https://github.com/haskell/haskell-language-server#readme>
@@ -117,7 +117,7 @@
   manual:      True
 
 common cabalfmt
-  if flag(cabalfmt)
+  if flag(cabalfmt) && flag(cabal)
     build-depends: haskell-language-server:hls-cabal-fmt-plugin
     cpp-options: -Dhls_cabalfmt
 
@@ -129,15 +129,15 @@
 
 library hls-cabal-fmt-plugin
   import:           defaults, pedantic, warnings
-  if !flag(cabalfmt)
+  if !flag(cabalfmt) || !flag(cabal)
     buildable: False
   exposed-modules:  Ide.Plugin.CabalFmt
   hs-source-dirs:   plugins/hls-cabal-fmt-plugin/src
   build-depends:
     , directory
     , filepath
-    , ghcide          == 2.10.0.0
-    , hls-plugin-api  == 2.10.0.0
+    , ghcide          == 2.11.0.0
+    , hls-plugin-api  == 2.11.0.0
     , lens
     , lsp-types
     , mtl
@@ -157,8 +157,8 @@
     , filepath
     , haskell-language-server:hls-cabal-plugin
     , haskell-language-server:hls-cabal-fmt-plugin
-    , hls-plugin-api        == 2.10.0.0
-    , hls-test-utils        == 2.10.0.0
+    , hls-plugin-api        == 2.11.0.0
+    , hls-test-utils        == 2.11.0.0
 
   if flag(isolateCabalfmtTests)
     build-tool-depends: cabal-fmt:cabal-fmt ^>=0.1.12
@@ -174,7 +174,7 @@
   manual:      True
 
 common cabalgild
-  if flag(cabalgild) && impl(ghc < 9.11)
+  if flag(cabalgild) && flag(cabal)
     build-depends: haskell-language-server:hls-cabal-gild-plugin
     cpp-options: -Dhls_cabalgild
 
@@ -186,15 +186,15 @@
 
 library hls-cabal-gild-plugin
   import:           defaults, pedantic, warnings
-  if !flag(cabalgild) || impl(ghc > 9.11)
+  if !flag(cabalgild) || !flag(cabal)
     buildable: False
   exposed-modules:  Ide.Plugin.CabalGild
   hs-source-dirs:   plugins/hls-cabal-gild-plugin/src
   build-depends:
     , directory
     , filepath
-    , ghcide          == 2.10.0.0
-    , hls-plugin-api  == 2.10.0.0
+    , ghcide          == 2.11.0.0
+    , hls-plugin-api  == 2.11.0.0
     , lsp-types
     , text
     , mtl
@@ -203,7 +203,7 @@
 -- The `hls-cabal-plugin` is needed for tests, as we need to install notification handlers
 test-suite hls-cabal-gild-plugin-tests
   import:           defaults, pedantic, test-defaults, warnings
-  if !flag(cabalgild) || !flag(cabal) || impl(ghc > 9.11)
+  if !flag(cabalgild) || !flag(cabal)
     buildable: False
   type:             exitcode-stdio-1.0
   hs-source-dirs:   plugins/hls-cabal-gild-plugin/test
@@ -213,8 +213,8 @@
     , filepath
     , haskell-language-server:hls-cabal-plugin
     , haskell-language-server:hls-cabal-gild-plugin
-    , hls-plugin-api        == 2.10.0.0
-    , hls-test-utils        == 2.10.0.0
+    , hls-plugin-api        == 2.11.0.0
+    , hls-test-utils        == 2.11.0.0
 
   if flag(isolateCabalGildTests)
     -- https://github.com/tfausak/cabal-gild/issues/89
@@ -269,10 +269,10 @@
     , directory
     , filepath
     , extra                 >=1.7.4
-    , ghcide                == 2.10.0.0
+    , ghcide                == 2.11.0.0
     , hashable
-    , hls-plugin-api        == 2.10.0.0
-    , hls-graph             == 2.10.0.0
+    , hls-plugin-api        == 2.11.0.0
+    , hls-graph             == 2.11.0.0
     , lens
     , lsp                   ^>=2.7
     , lsp-types             ^>=2.3
@@ -311,7 +311,7 @@
     , filepath
     , ghcide
     , haskell-language-server:hls-cabal-plugin
-    , hls-test-utils    == 2.10.0.0
+    , hls-test-utils    == 2.11.0.0
     , lens
     , lsp-types
     , text
@@ -349,9 +349,9 @@
     , extra
     , ghc
     , ghc-exactprint  >= 1.5 && < 1.13.0.0
-    , ghcide          == 2.10.0.0
+    , ghcide          == 2.11.0.0
     , hls-graph
-    , hls-plugin-api  == 2.10.0.0
+    , hls-plugin-api  == 2.11.0.0
     , lens
     , lsp
     , mtl
@@ -372,7 +372,7 @@
   build-depends:
     , filepath
     , haskell-language-server:hls-class-plugin
-    , hls-test-utils     == 2.10.0.0
+    , hls-test-utils     == 2.11.0.0
     , lens
     , lsp-types
     , text
@@ -406,9 +406,9 @@
     , aeson
     , containers
     , extra
-    , ghcide                == 2.10.0.0
-    , hiedb                 ^>= 0.6.0.0
-    , hls-plugin-api        == 2.10.0.0
+    , ghcide                == 2.11.0.0
+    , hiedb                 ^>= 0.6.0.2
+    , hls-plugin-api        == 2.11.0.0
     , lens
     , lsp                    >=2.7
     , sqlite-simple
@@ -429,7 +429,7 @@
     , extra
     , filepath
     , haskell-language-server:hls-call-hierarchy-plugin
-    , hls-test-utils        == 2.10.0.0
+    , hls-test-utils        == 2.11.0.0
     , lens
     , lsp
     , lsp-test
@@ -460,9 +460,9 @@
   hs-source-dirs:     plugins/hls-eval-plugin/src
   other-modules:
     Ide.Plugin.Eval.Code
-    Ide.Plugin.Eval.CodeLens
     Ide.Plugin.Eval.Config
     Ide.Plugin.Eval.GHC
+    Ide.Plugin.Eval.Handlers
     Ide.Plugin.Eval.Parse.Comments
     Ide.Plugin.Eval.Parse.Option
     Ide.Plugin.Eval.Rules
@@ -479,9 +479,9 @@
     , filepath
     , ghc
     , ghc-boot-th
-    , ghcide                == 2.10.0.0
+    , ghcide                == 2.11.0.0
     , hls-graph
-    , hls-plugin-api        == 2.10.0.0
+    , hls-plugin-api        == 2.11.0.0
     , lens
     , lsp
     , lsp-types
@@ -512,7 +512,7 @@
     , filepath
     , haskell-language-server:hls-eval-plugin
     , hls-plugin-api
-    , hls-test-utils   == 2.10.0.0
+    , hls-test-utils   == 2.11.0.0
     , lens
     , lsp-types
     , text
@@ -542,9 +542,9 @@
     , containers
     , deepseq
     , ghc
-    , ghcide                == 2.10.0.0
+    , ghcide                == 2.11.0.0
     , hls-graph
-    , hls-plugin-api        == 2.10.0.0
+    , hls-plugin-api        == 2.11.0.0
     , lens
     , lsp
     , mtl
@@ -565,7 +565,7 @@
     , extra
     , filepath
     , haskell-language-server:hls-explicit-imports-plugin
-    , hls-test-utils   == 2.10.0.0
+    , hls-test-utils   == 2.11.0.0
     , lens
     , lsp-types
     , text
@@ -580,23 +580,23 @@
   manual:      True
 
 common rename
-  if flag(rename) && impl(ghc < 9.11)
+  if flag(rename)
     build-depends: haskell-language-server:hls-rename-plugin
     cpp-options: -Dhls_rename
 
 library hls-rename-plugin
   import:           defaults, pedantic, warnings
-  if !flag(rename) || impl(ghc > 9.11)
+  if !flag(rename)
     buildable: False
   exposed-modules:  Ide.Plugin.Rename
   hs-source-dirs:   plugins/hls-rename-plugin/src
   build-depends:
     , containers
-    , ghcide                == 2.10.0.0
+    , ghcide                == 2.11.0.0
     , hashable
-    , hiedb                 ^>= 0.6.0.0
+    , hiedb                 ^>= 0.6.0.2
     , hie-compat
-    , hls-plugin-api        == 2.10.0.0
+    , hls-plugin-api        == 2.11.0.0
     , haskell-language-server:hls-refactor-plugin
     , lens
     , lsp-types
@@ -610,7 +610,7 @@
 
 test-suite hls-rename-plugin-tests
   import:           defaults, pedantic, test-defaults, warnings
-  if !flag(rename) || impl(ghc > 9.11)
+  if !flag(rename)
     buildable: False
   type:             exitcode-stdio-1.0
   hs-source-dirs:   plugins/hls-rename-plugin/test
@@ -621,7 +621,7 @@
     , filepath
     , hls-plugin-api
     , haskell-language-server:hls-rename-plugin
-    , hls-test-utils             == 2.10.0.0
+    , hls-test-utils             == 2.11.0.0
     , lens
     , lsp-types
     , text
@@ -636,13 +636,13 @@
   manual:      True
 
 common retrie
-  if flag(retrie) && impl(ghc < 9.10)
+  if flag(retrie) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds))
     build-depends: haskell-language-server:hls-retrie-plugin
     cpp-options: -Dhls_retrie
 
 library hls-retrie-plugin
   import:           defaults, pedantic, warnings
-  if !(flag(retrie) && impl(ghc < 9.10))
+  if !(flag(retrie) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds)))
     buildable: False
   exposed-modules:  Ide.Plugin.Retrie
   hs-source-dirs:   plugins/hls-retrie-plugin/src
@@ -652,9 +652,9 @@
     , containers
     , extra
     , ghc
-    , ghcide                == 2.10.0.0
+    , ghcide                == 2.11.0.0
     , hashable
-    , hls-plugin-api        == 2.10.0.0
+    , hls-plugin-api        == 2.11.0.0
     , haskell-language-server:hls-refactor-plugin
     , lens
     , lsp
@@ -673,7 +673,7 @@
 
 test-suite hls-retrie-plugin-tests
   import:           defaults, pedantic, test-defaults, warnings
-  if !(flag(retrie) && impl(ghc < 9.10))
+  if !(flag(retrie) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds)))
     buildable: False
   type:             exitcode-stdio-1.0
   hs-source-dirs:   plugins/hls-retrie-plugin/test
@@ -683,7 +683,7 @@
     , filepath
     , hls-plugin-api
     , haskell-language-server:{hls-refactor-plugin, hls-retrie-plugin}
-    , hls-test-utils             == 2.10.0.0
+    , hls-test-utils             == 2.11.0.0
     , text
 
 -----------------------------
@@ -703,14 +703,14 @@
   manual:      True
 
 common hlint
-  if flag(hlint) && impl(ghc < 9.10)
+  if flag(hlint) && ((impl(ghc < 9.10) || impl(ghc > 9.11)) || flag(ignore-plugins-ghc-bounds))
     build-depends: haskell-language-server:hls-hlint-plugin
     cpp-options: -Dhls_hlint
 
 library hls-hlint-plugin
   import:           defaults, pedantic, warnings
   -- https://github.com/ndmitchell/hlint/pull/1594
-  if !(flag(hlint)) || impl(ghc > 9.10)
+  if !(flag(hlint)) || ((impl(ghc >= 9.10) && impl(ghc < 9.11)) && !flag(ignore-plugins-ghc-bounds))
     buildable: False
   exposed-modules:  Ide.Plugin.Hlint
   hs-source-dirs:   plugins/hls-hlint-plugin/src
@@ -720,10 +720,10 @@
     , containers
     , deepseq
     , filepath
-    , ghcide                == 2.10.0.0
+    , ghcide                == 2.11.0.0
     , hashable
-    , hlint                 >= 3.5 && < 3.9
-    , hls-plugin-api        == 2.10.0.0
+    , hlint                 >= 3.5 && < 3.11
+    , hls-plugin-api        == 2.11.0.0
     , lens
     , mtl
     , refact
@@ -753,7 +753,7 @@
 
 test-suite hls-hlint-plugin-tests
   import:           defaults, pedantic, test-defaults, warnings
-  if (!flag(hlint)) || impl(ghc > 9.10)
+  if !flag(hlint) || ((impl(ghc >= 9.10) && impl(ghc < 9.11)) && !flag(ignore-plugins-ghc-bounds))
     buildable: False
   type:             exitcode-stdio-1.0
   hs-source-dirs:   plugins/hls-hlint-plugin/test
@@ -767,7 +767,7 @@
     , filepath
     , haskell-language-server:hls-hlint-plugin
     , hls-plugin-api
-    , hls-test-utils      == 2.10.0.0
+    , hls-test-utils      == 2.11.0.0
     , lens
     , lsp-types
     , text
@@ -782,13 +782,13 @@
   manual:      True
 
 common stan
-  if flag(stan) && impl(ghc < 9.11)
+  if flag(stan) && (impl(ghc < 9.11) || flag(ignore-plugins-ghc-bounds))
     build-depends: haskell-language-server:hls-stan-plugin
     cpp-options: -Dhls_stan
 
 library hls-stan-plugin
   import:           defaults, pedantic, warnings
-  if !flag(stan) || impl(ghc > 9.11)
+  if !flag(stan) || (impl(ghc > 9.11) && !flag(ignore-plugins-ghc-bounds))
     buildable: False
   exposed-modules:    Ide.Plugin.Stan
   hs-source-dirs:     plugins/hls-stan-plugin/src
@@ -813,7 +813,7 @@
 
 test-suite hls-stan-plugin-tests
   import:           defaults, pedantic, test-defaults, warnings
-  if !flag(stan) || impl(ghc > 9.11)
+  if !flag(stan) || (impl(ghc > 9.11) && !flag(ignore-plugins-ghc-bounds))
     buildable: False
   type:             exitcode-stdio-1.0
   hs-source-dirs:   plugins/hls-stan-plugin/test
@@ -822,7 +822,7 @@
     , filepath
     , haskell-language-server:hls-stan-plugin
     , hls-plugin-api
-    , hls-test-utils      == 2.10.0.0
+    , hls-test-utils      == 2.11.0.0
     , lens
     , lsp-types
     , text
@@ -853,8 +853,8 @@
     , aeson
     , containers
     , filepath
-    , ghcide                == 2.10.0.0
-    , hls-plugin-api        == 2.10.0.0
+    , ghcide                == 2.11.0.0
+    , hls-plugin-api        == 2.11.0.0
     , lsp
     , text
     , text-rope
@@ -871,7 +871,7 @@
   build-depends:
     , filepath
     , haskell-language-server:hls-module-name-plugin
-    , hls-test-utils          == 2.10.0.0
+    , hls-test-utils          == 2.11.0.0
 
 -----------------------------
 -- pragmas plugin
@@ -897,8 +897,8 @@
     , aeson
     , extra
     , fuzzy
-    , ghcide                == 2.10.0.0
-    , hls-plugin-api        == 2.10.0.0
+    , ghcide                == 2.11.0.0
+    , hls-plugin-api        == 2.11.0.0
     , lens
     , lens-aeson
     , lsp
@@ -917,7 +917,7 @@
     , aeson
     , filepath
     , haskell-language-server:hls-pragmas-plugin
-    , hls-test-utils      == 2.10.0.0
+    , hls-test-utils      == 2.11.0.0
     , lens
     , lsp-types
     , text
@@ -932,13 +932,13 @@
   manual:      True
 
 common splice
-  if flag(splice) && impl(ghc < 9.10)
+  if flag(splice) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds))
     build-depends: haskell-language-server:hls-splice-plugin
     cpp-options: -Dhls_splice
 
 library hls-splice-plugin
   import:           defaults, pedantic, warnings
-  if !(flag(splice) && impl(ghc < 9.10))
+  if !(flag(splice) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds)))
     buildable: False
   exposed-modules:
     Ide.Plugin.Splice
@@ -950,8 +950,8 @@
     , extra
     , foldl
     , ghc
-    , ghcide                == 2.10.0.0
-    , hls-plugin-api        == 2.10.0.0
+    , ghcide                == 2.11.0.0
+    , hls-plugin-api        == 2.11.0.0
     , haskell-language-server:hls-refactor-plugin
     , lens
     , lsp
@@ -966,7 +966,7 @@
 
 test-suite hls-splice-plugin-tests
   import:           defaults, pedantic, test-defaults, warnings
-  if !(flag(splice) && impl(ghc < 9.10))
+  if !(flag(splice) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds)))
     buildable: False
   type:             exitcode-stdio-1.0
   hs-source-dirs:   plugins/hls-splice-plugin/test
@@ -974,7 +974,7 @@
   build-depends:
     , filepath
     , haskell-language-server:hls-splice-plugin
-    , hls-test-utils == 2.10.0.0
+    , hls-test-utils == 2.11.0.0
     , text
 
 -----------------------------
@@ -1001,10 +1001,10 @@
   build-depends:
     , containers
     , extra
-    , ghcide               == 2.10.0.0
+    , ghcide               == 2.11.0.0
     , ghc-boot-th
     , hls-graph
-    , hls-plugin-api       == 2.10.0.0
+    , hls-plugin-api       == 2.11.0.0
     , lens
     , lsp                  ^>=2.7
     , mtl
@@ -1029,7 +1029,7 @@
   build-depends:
     , filepath
     , haskell-language-server:hls-alternate-number-format-plugin
-    , hls-test-utils       == 2.10.0.0
+    , hls-test-utils       == 2.11.0.0
     , regex-tdfa
     , tasty-quickcheck
     , text
@@ -1061,8 +1061,8 @@
   hs-source-dirs:   plugins/hls-qualify-imported-names-plugin/src
   build-depends:
     , containers
-    , ghcide                == 2.10.0.0
-    , hls-plugin-api        == 2.10.0.0
+    , ghcide                == 2.11.0.0
+    , hls-plugin-api        == 2.11.0.0
     , lens
     , lsp
     , text
@@ -1084,7 +1084,7 @@
     , text
     , filepath
     , haskell-language-server:hls-qualify-imported-names-plugin
-    , hls-test-utils             == 2.10.0.0
+    , hls-test-utils             == 2.11.0.0
 
 -----------------------------
 -- code range plugin
@@ -1114,9 +1114,9 @@
     , containers
     , deepseq
     , extra
-    , ghcide           == 2.10.0.0
+    , ghcide           == 2.11.0.0
     , hashable
-    , hls-plugin-api   == 2.10.0.0
+    , hls-plugin-api   == 2.11.0.0
     , lens
     , lsp
     , mtl
@@ -1138,7 +1138,7 @@
     , bytestring
     , filepath
     , haskell-language-server:hls-code-range-plugin
-    , hls-test-utils             == 2.10.0.0
+    , hls-test-utils             == 2.11.0.0
     , lens
     , lsp
     , lsp-test
@@ -1166,8 +1166,8 @@
   exposed-modules:  Ide.Plugin.ChangeTypeSignature
   hs-source-dirs:   plugins/hls-change-type-signature-plugin/src
   build-depends:
-    , ghcide           == 2.10.0.0
-    , hls-plugin-api   == 2.10.0.0
+    , ghcide           == 2.11.0.0
+    , hls-plugin-api   == 2.11.0.0
     , lsp-types
     , regex-tdfa
     , syb
@@ -1191,7 +1191,7 @@
   build-depends:
     , filepath
     , haskell-language-server:hls-change-type-signature-plugin
-    , hls-test-utils       == 2.10.0.0
+    , hls-test-utils       == 2.11.0.0
     , regex-tdfa
     , text
   default-extensions:
@@ -1208,13 +1208,13 @@
   manual:      True
 
 common gadt
-  if flag(gadt) && impl(ghc < 9.11)
+  if flag(gadt)
     build-depends: haskell-language-server:hls-gadt-plugin
     cpp-options: -Dhls_gadt
 
 library hls-gadt-plugin
   import:           defaults, pedantic, warnings
-  if !flag(gadt) || impl(ghc > 9.11)
+  if !flag(gadt)
     buildable: False
   exposed-modules:  Ide.Plugin.GADT
   other-modules:    Ide.Plugin.GHC
@@ -1224,9 +1224,9 @@
     , containers
     , extra
     , ghc
-    , ghcide                 == 2.10.0.0
+    , ghcide                 == 2.11.0.0
     , ghc-exactprint
-    , hls-plugin-api         == 2.10.0.0
+    , hls-plugin-api         == 2.11.0.0
     , haskell-language-server:hls-refactor-plugin
     , lens
     , lsp                    >=2.7
@@ -1238,7 +1238,7 @@
 
 test-suite hls-gadt-plugin-tests
   import:           defaults, pedantic, test-defaults, warnings
-  if !flag(gadt) || impl(ghc > 9.11)
+  if !flag(gadt)
     buildable: False
   type:             exitcode-stdio-1.0
   hs-source-dirs:   plugins/hls-gadt-plugin/test
@@ -1246,7 +1246,7 @@
   build-depends:
     , filepath
     , haskell-language-server:hls-gadt-plugin
-    , hls-test-utils              == 2.10.0.0
+    , hls-test-utils              == 2.11.0.0
     , text
 
 -----------------------------
@@ -1273,9 +1273,9 @@
     , containers
     , deepseq
     , extra
-    , ghcide                == 2.10.0.0
+    , ghcide                == 2.11.0.0
     , hashable
-    , hls-plugin-api        == 2.10.0.0
+    , hls-plugin-api        == 2.11.0.0
     , lsp                   >=2.7
     , text
 
@@ -1291,7 +1291,7 @@
   build-depends:
     , filepath
     , haskell-language-server:hls-explicit-fixity-plugin
-    , hls-test-utils              == 2.10.0.0
+    , hls-test-utils              == 2.11.0.0
     , text
 
 -----------------------------
@@ -1314,8 +1314,8 @@
     buildable: False
   exposed-modules:  Ide.Plugin.ExplicitFields
   build-depends:
-    , ghcide                == 2.10.0.0
-    , hls-plugin-api        == 2.10.0.0
+    , ghcide                == 2.11.0.0
+    , hls-plugin-api        == 2.11.0.0
     , lsp
     , lens
     , hls-graph
@@ -1341,7 +1341,7 @@
     , text
     , ghcide
     , haskell-language-server:hls-explicit-record-fields-plugin
-    , hls-test-utils              == 2.10.0.0
+    , hls-test-utils              == 2.11.0.0
 
 -----------------------------
 -- overloaded record dot plugin
@@ -1387,7 +1387,7 @@
     , filepath
     , text
     , haskell-language-server:hls-overloaded-record-dot-plugin
-    , hls-test-utils              == 2.10.0.0
+    , hls-test-utils              == 2.11.0.0
 
 
 -----------------------------
@@ -1400,21 +1400,21 @@
   manual:      True
 
 common floskell
-  if flag(floskell) && impl(ghc < 9.10)
+  if flag(floskell) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds))
     build-depends: haskell-language-server:hls-floskell-plugin
     cpp-options: -Dhls_floskell
 
 library hls-floskell-plugin
   import:           defaults, pedantic, warnings
   -- https://github.com/ennocramer/floskell/pull/82
-  if !(flag(floskell) && impl(ghc < 9.10))
+  if !(flag(floskell) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds)))
     buildable: False
   exposed-modules:  Ide.Plugin.Floskell
   hs-source-dirs:   plugins/hls-floskell-plugin/src
   build-depends:
     , floskell        ^>=0.11.0
-    , ghcide          == 2.10.0.0
-    , hls-plugin-api  == 2.10.0.0
+    , ghcide          == 2.11.0.0
+    , hls-plugin-api  == 2.11.0.0
     , lsp-types       ^>=2.3
     , mtl
     , text
@@ -1422,7 +1422,7 @@
 
 test-suite hls-floskell-plugin-tests
   import:           defaults, pedantic, test-defaults, warnings
-  if !(flag(floskell) && impl(ghc < 9.10))
+  if !(flag(floskell) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds)))
     buildable: False
   type:             exitcode-stdio-1.0
   hs-source-dirs:   plugins/hls-floskell-plugin/test
@@ -1430,7 +1430,7 @@
   build-depends:
     , filepath
     , haskell-language-server:hls-floskell-plugin
-    , hls-test-utils       == 2.10.0.0
+    , hls-test-utils       == 2.11.0.0
 
 -----------------------------
 -- fourmolu plugin
@@ -1442,22 +1442,22 @@
   manual:      True
 
 common fourmolu
-  if flag(fourmolu) && impl(ghc < 9.11)
+  if flag(fourmolu)
     build-depends: haskell-language-server:hls-fourmolu-plugin
     cpp-options: -Dhls_fourmolu
 
 library hls-fourmolu-plugin
   import:           defaults, pedantic, warnings
-  if !flag(fourmolu) || impl(ghc > 9.11)
+  if !flag(fourmolu)
     buildable: False
   exposed-modules:  Ide.Plugin.Fourmolu
   hs-source-dirs:   plugins/hls-fourmolu-plugin/src
   build-depends:
     , filepath
-    , fourmolu        ^>= 0.14 || ^>= 0.15 || ^>= 0.16
+    , fourmolu        ^>= 0.14 || ^>= 0.15 || ^>= 0.16 || ^>=0.17 || ^>=0.18
     , ghc-boot-th
-    , ghcide          == 2.10.0.0
-    , hls-plugin-api  == 2.10.0.0
+    , ghcide          == 2.11.0.0
+    , hls-plugin-api  == 2.11.0.0
     , lens
     , lsp
     , mtl
@@ -1468,7 +1468,7 @@
 
 test-suite hls-fourmolu-plugin-tests
   import:           defaults, pedantic, test-defaults, warnings
-  if !flag(fourmolu) || impl(ghc > 9.11)
+  if !flag(fourmolu)
     buildable: False
   type:             exitcode-stdio-1.0
   hs-source-dirs:   plugins/hls-fourmolu-plugin/test
@@ -1483,7 +1483,7 @@
     , filepath
     , haskell-language-server:hls-fourmolu-plugin
     , hls-plugin-api
-    , hls-test-utils       == 2.10.0.0
+    , hls-test-utils       == 2.11.0.0
     , lsp-test
 
 -----------------------------
@@ -1496,13 +1496,13 @@
   manual:      True
 
 common ormolu
-  if flag(ormolu) && impl(ghc < 9.11)
+  if flag(ormolu)
     build-depends: haskell-language-server:hls-ormolu-plugin
     cpp-options: -Dhls_ormolu
 
 library hls-ormolu-plugin
   import:           defaults, pedantic, warnings
-  if !flag(ormolu) || impl(ghc > 9.11)
+  if !flag(ormolu)
     buildable: False
   exposed-modules:  Ide.Plugin.Ormolu
   hs-source-dirs:   plugins/hls-ormolu-plugin/src
@@ -1510,19 +1510,19 @@
     , extra
     , filepath
     , ghc-boot-th
-    , ghcide          == 2.10.0.0
-    , hls-plugin-api  == 2.10.0.0
+    , ghcide          == 2.11.0.0
+    , hls-plugin-api  == 2.11.0.0
     , lsp
     , mtl
     , process-extras  >= 0.7.1
-    , ormolu          ^>=0.1.2 || ^>= 0.2 || ^>= 0.3 || ^>= 0.5 || ^>= 0.6 || ^>= 0.7
+    , ormolu          ^>=0.5.3 || ^>= 0.6 || ^>= 0.7 || ^>=0.8
     , text
     , transformers
 
 
 test-suite hls-ormolu-plugin-tests
   import:           defaults, pedantic, test-defaults, warnings
-  if !flag(ormolu) || impl(ghc > 9.11)
+  if !flag(ormolu)
     buildable: False
   type:             exitcode-stdio-1.0
   hs-source-dirs:   plugins/hls-ormolu-plugin/test
@@ -1537,7 +1537,7 @@
     , filepath
     , haskell-language-server:hls-ormolu-plugin
     , hls-plugin-api
-    , hls-test-utils     == 2.10.0.0
+    , hls-test-utils     == 2.11.0.0
     , lsp-types
     , ormolu
 
@@ -1551,14 +1551,14 @@
   manual:      True
 
 common stylishHaskell
-  if flag(stylishHaskell) && impl(ghc < 9.10)
+  if flag(stylishHaskell)
     build-depends: haskell-language-server:hls-stylish-haskell-plugin
     cpp-options: -Dhls_stylishHaskell
 
 library hls-stylish-haskell-plugin
   import:           defaults, pedantic, warnings
   -- https://github.com/haskell/stylish-haskell/issues/479
-  if !(flag(stylishHaskell) && impl(ghc < 9.10))
+  if !flag(stylishHaskell)
     buildable: False
   exposed-modules:  Ide.Plugin.StylishHaskell
   hs-source-dirs:   plugins/hls-stylish-haskell-plugin/src
@@ -1566,17 +1566,17 @@
     , directory
     , filepath
     , ghc-boot-th
-    , ghcide           == 2.10.0.0
-    , hls-plugin-api   == 2.10.0.0
+    , ghcide           == 2.11.0.0
+    , hls-plugin-api   == 2.11.0.0
     , lsp-types
     , mtl
-    , stylish-haskell  ^>=0.12 || ^>=0.13 || ^>=0.14
+    , stylish-haskell  >=0.12 && <0.16
     , text
 
 
 test-suite hls-stylish-haskell-plugin-tests
   import:           defaults, pedantic, test-defaults, warnings
-  if !(flag(stylishHaskell) && impl(ghc < 9.10))
+  if !flag(stylishHaskell)
     buildable: False
   type:             exitcode-stdio-1.0
   hs-source-dirs:   plugins/hls-stylish-haskell-plugin/test
@@ -1584,7 +1584,7 @@
   build-depends:
     , filepath
     , haskell-language-server:hls-stylish-haskell-plugin
-    , hls-test-utils              == 2.10.0.0
+    , hls-test-utils              == 2.11.0.0
 
 -----------------------------
 -- refactor plugin
@@ -1596,13 +1596,13 @@
   manual:      True
 
 common refactor
-  if flag(refactor) && impl(ghc < 9.11)
+  if flag(refactor)
     build-depends: haskell-language-server:hls-refactor-plugin
     cpp-options: -Dhls_refactor
 
 library hls-refactor-plugin
   import:           defaults, pedantic, warnings
-  if !flag(refactor) || impl(ghc > 9.11)
+  if !flag(refactor)
     buildable: False
   exposed-modules:  Development.IDE.GHC.ExactPrint
                     Development.IDE.GHC.Compat.ExactPrint
@@ -1636,8 +1636,8 @@
     , bytestring
     , ghc-boot
     , regex-tdfa
-    , ghcide                == 2.10.0.0
-    , hls-plugin-api        == 2.10.0.0
+    , ghcide                == 2.11.0.0
+    , hls-plugin-api        == 2.11.0.0
     , lsp
     , text
     , text-rope
@@ -1661,7 +1661,7 @@
 
 test-suite hls-refactor-plugin-tests
   import:           defaults, pedantic, test-defaults, warnings
-  if !flag(refactor) || impl(ghc > 9.11)
+  if !flag(refactor)
     buildable: False
   type:             exitcode-stdio-1.0
   hs-source-dirs:   plugins/hls-refactor-plugin/test
@@ -1675,7 +1675,7 @@
     , filepath
     , ghcide:ghcide
     , haskell-language-server:hls-refactor-plugin
-    , hls-test-utils      == 2.10.0.0
+    , hls-test-utils      == 2.11.0.0
     , lens
     , lsp-test
     , lsp-types
@@ -1722,8 +1722,8 @@
     , extra
     , text-rope
     , mtl                   >= 2.2
-    , ghcide                == 2.10.0.0
-    , hls-plugin-api        == 2.10.0.0
+    , ghcide                == 2.11.0.0
+    , hls-plugin-api        == 2.11.0.0
     , lens
     , lsp                    >=2.6
     , text
@@ -1733,7 +1733,7 @@
     , array
     , deepseq
     , dlist
-    , hls-graph == 2.10.0.0
+    , hls-graph == 2.11.0.0
     , template-haskell
     , data-default
     , stm
@@ -1754,10 +1754,10 @@
     , containers
     , data-default
     , filepath
-    , ghcide                == 2.10.0.0
+    , ghcide                == 2.11.0.0
     , haskell-language-server:hls-semantic-tokens-plugin
-    , hls-plugin-api        == 2.10.0.0
-    , hls-test-utils        == 2.10.0.0
+    , hls-plugin-api        == 2.11.0.0
+    , hls-test-utils        == 2.11.0.0
     , lens
     , lsp
     , lsp-test
@@ -1787,9 +1787,9 @@
   hs-source-dirs:     plugins/hls-notes-plugin/src
   build-depends:
     , array
-    , ghcide == 2.10.0.0
-    , hls-graph == 2.10.0.0
-    , hls-plugin-api == 2.10.0.0
+    , ghcide == 2.11.0.0
+    , hls-graph == 2.11.0.0
+    , hls-plugin-api == 2.11.0.0
     , lens
     , lsp >=2.7
     , mtl >= 2.2
@@ -1815,7 +1815,7 @@
   build-depends:
     , filepath
     , haskell-language-server:hls-notes-plugin
-    , hls-test-utils == 2.10.0.0
+    , hls-test-utils == 2.11.0.0
   default-extensions: OverloadedStrings
 
 ----------------------------
@@ -1875,10 +1875,10 @@
     , extra
     , filepath
     , ghc
-    , ghcide                == 2.10.0.0
+    , ghcide                == 2.11.0.0
     , githash               >=0.1.6.1
     , hie-bios
-    , hls-plugin-api        == 2.10.0.0
+    , hls-plugin-api        == 2.11.0.0
     , optparse-applicative
     , optparse-simple
     , prettyprinter         >= 1.7
@@ -1981,7 +1981,7 @@
     , ghcide:ghcide
     , hashable
     , hls-plugin-api
-    , hls-test-utils == 2.10.0.0
+    , hls-test-utils == 2.11.0.0
     , lens
     , lsp-test
     , lsp-types
@@ -2007,11 +2007,11 @@
   if flag(eval)
     cpp-options: -Dhls_eval
 -- formatters
-  if flag(floskell) && impl(ghc < 9.10)
+  if flag(floskell) && (impl(ghc < 9.10) || flag(ignore-plugins-ghc-bounds))
     cpp-options: -Dhls_floskell
-  if flag(fourmolu) && impl(ghc < 9.11)
+  if flag(fourmolu)
     cpp-options: -Dhls_fourmolu
-  if flag(ormolu) && impl(ghc < 9.11)
+  if flag(ormolu)
     cpp-options: -Dhls_ormolu
 
 test-suite wrapper-test
@@ -2025,7 +2025,7 @@
 
   build-depends:
     , extra
-    , hls-test-utils              == 2.10.0.0
+    , hls-test-utils              == 2.11.0.0
     , process
 
   hs-source-dirs:     test/wrapper
@@ -2094,7 +2094,6 @@
     , enummapset
     , extra
     , filepath
-    , fuzzy
     , ghcide
     , hls-plugin-api
     , lens
@@ -2102,7 +2101,6 @@
     , lsp
     , lsp-test                ^>=0.17.1
     , lsp-types
-    , monoid-subclasses
     , mtl
     , network-uri
     , QuickCheck
@@ -2120,7 +2118,7 @@
     , text
     , text-rope
     , unordered-containers
-    , hls-test-utils == 2.10.0.0
+    , hls-test-utils == 2.11.0.0
 
   if impl(ghc <9.3)
     build-depends: ghc-typelits-knownnat
@@ -2174,9 +2172,14 @@
     RecordWildCards
     ViewPatterns
 
+flag ghcide-bench
+  description: Build the ghcide-bench executable
+  default:     True
 
 executable ghcide-bench
     import: defaults
+    if !flag(ghcide-bench)
+      buildable: False
     build-depends:
         aeson,
         bytestring,
diff --git a/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/CabalAdd.hs b/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/CabalAdd.hs
--- a/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/CabalAdd.hs
+++ b/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/CabalAdd.hs
@@ -190,6 +190,12 @@
 -- > It is a member of the hidden package ‘split-0.2.5’.
 -- > Perhaps you need to add ‘split’ to the build-depends in your .cabal file."
 --
+-- or this if PackageImports extension is used:
+--
+-- > "Could not find module ‘Data.List.Split’
+-- > Perhaps you meant
+-- >   Data.List.Split (needs flag -package-id split-0.2.5)"
+--
 -- It extracts mentioned package names and version numbers.
 -- In this example, it will be @[("split", "0.2.5")]@
 --
@@ -204,13 +210,18 @@
     msg :: T.Text
     msg = _message diag
     regex :: T.Text -- TODO: Support multiple packages suggestion
-    regex = "It is a member of the hidden package [\8216']([a-zA-Z0-9-]*[a-zA-Z0-9])(-([0-9\\.]*))?[\8217']"
+    regex =
+        let regex' = "([a-zA-Z0-9-]*[a-zA-Z0-9])(-([0-9\\.]*))?"
+        in "It is a member of the hidden package [\8216']" <> regex' <> "[\8217']"
+           <> "|"
+           <> "needs flag -package-id " <> regex'
     -- Have to do this matching because `Regex.TDFA` doesn't(?) support
     -- not-capturing groups like (?:message)
     getMatch :: (T.Text, T.Text, T.Text, [T.Text]) -> [(T.Text, T.Text)]
     getMatch (_, _, _, []) = []
-    getMatch (_, _, _, [dependency, _, cleanVersion]) = [(dependency, cleanVersion)]
-    getMatch (_, _, _, _) = error "Impossible pattern matching case"
+    getMatch (_, _, _, [dependency, _, cleanVersion, "", "", ""]) = [(dependency, cleanVersion)]
+    getMatch (_, _, _, ["", "", "", dependency, _, cleanVersion]) = [(dependency, cleanVersion)]
+    getMatch (_, _, _, _) = []
 
 command :: Recorder (WithPriority Log) -> CommandFunction IdeState CabalAddCommandParams
 command recorder state _ params@(CabalAddCommandParams {cabalPath = path, verTxtDocId = verTxtDocId, buildTarget = target, dependency = dep, version = mbVer}) = do
diff --git a/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/Completer/Paths.hs b/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/Completer/Paths.hs
--- a/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/Completer/Paths.hs
+++ b/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/Completer/Paths.hs
@@ -7,6 +7,7 @@
                                                     BuildInfo (..),
                                                     CondTree (condTreeData),
                                                     Executable (..),
+                                                    ForeignLib (..),
                                                     GenericPackageDescription (..),
                                                     Library (..),
                                                     UnqualComponentName,
@@ -117,6 +118,10 @@
 -- | Extracts the source directories of benchmark stanza with the given name.
 sourceDirsExtractionBenchmark :: Maybe StanzaName -> GenericPackageDescription -> [FilePath]
 sourceDirsExtractionBenchmark name gpd = extractRelativeDirsFromStanza name gpd condBenchmarks benchmarkBuildInfo
+
+-- | Extracts the source directories of foreign-lib stanza with the given name.
+sourceDirsExtractionForeignLib :: Maybe StanzaName -> GenericPackageDescription -> [FilePath]
+sourceDirsExtractionForeignLib name gpd = extractRelativeDirsFromStanza name gpd condForeignLibs foreignLibBuildInfo
 
 {- | Takes a possible stanza name, a GenericPackageDescription,
   a function to access the stanza information we are interested in
diff --git a/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/Data.hs b/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/Data.hs
--- a/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/Data.hs
+++ b/plugins/hls-cabal-plugin/src/Ide/Plugin/Cabal/Completion/Data.hs
@@ -1,8 +1,5 @@
 {-# LANGUAGE OverloadedStrings #-}
-{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
 
-{-# HLINT ignore "Redundant bracket" #-}
-
 module Ide.Plugin.Cabal.Completion.Data where
 
 import           Data.Map                                       (Map)
@@ -19,6 +16,17 @@
 import           Ide.Plugin.Cabal.Completion.Types
 import           Ide.Plugin.Cabal.LicenseSuggest                (licenseNames)
 
+-- | Ad-hoc data type for modelling the available top-level stanzas.
+-- Not intended right now for anything else but to avoid string
+-- comparisons in 'stanzaKeywordMap' and 'libExecTestBenchCommons'.
+data TopLevelStanza
+  = Library
+  | Executable
+  | TestSuite
+  | Benchmark
+  | ForeignLib
+  | Common
+
 -- ----------------------------------------------------------------
 -- Completion Data
 -- ----------------------------------------------------------------
@@ -71,12 +79,13 @@
 stanzaKeywordMap :: Map StanzaType (Map KeyWordName Completer)
 stanzaKeywordMap =
   Map.fromList
-    [ ("library", libraryFields <> libExecTestBenchCommons),
-      ("executable", executableFields <> libExecTestBenchCommons),
-      ("test-suite", testSuiteFields <> libExecTestBenchCommons),
-      ("benchmark", benchmarkFields <> libExecTestBenchCommons),
-      ("foreign-library", foreignLibraryFields <> libExecTestBenchCommons),
-      ("common", libExecTestBenchCommons),
+    [ ("library", libraryFields <> libExecTestBenchCommons Library),
+      ("executable", executableFields <> libExecTestBenchCommons Executable),
+      ("test-suite", testSuiteFields <> libExecTestBenchCommons TestSuite),
+      ("benchmark", benchmarkFields <> libExecTestBenchCommons Benchmark),
+      ("foreign-library", foreignLibraryFields <> libExecTestBenchCommons ForeignLib),
+      ("common", libExecTestBenchCommons Library),
+      ("common", libExecTestBenchCommons Common),
       ("flag", flagFields),
       ("source-repository", sourceRepositoryFields)
     ]
@@ -162,8 +171,8 @@
       ("lib-version-linux:", noopCompleter)
     ]
 
-libExecTestBenchCommons :: Map KeyWordName Completer
-libExecTestBenchCommons =
+libExecTestBenchCommons :: TopLevelStanza -> Map KeyWordName Completer
+libExecTestBenchCommons st =
   Map.fromList
     [ ("import:", importCompleter),
       ("build-depends:", noopCompleter),
@@ -183,6 +192,8 @@
       ("includes:", filePathCompleter),
       ("install-includes:", filePathCompleter),
       ("include-dirs:", directoryCompleter),
+      ("autogen-includes:", filePathCompleter),
+      ("autogen-modules:", moduleCompleterByTopLevelStanza),
       ("c-sources:", filePathCompleter),
       ("cxx-sources:", filePathCompleter),
       ("asm-sources:", filePathCompleter),
@@ -203,6 +214,26 @@
       ("extra-framework-dirs:", directoryCompleter),
       ("mixins:", noopCompleter)
     ]
+  where
+    --
+    moduleCompleterByTopLevelStanza = case st of
+      Library -> modulesCompleter sourceDirsExtractionLibrary
+      Executable -> modulesCompleter sourceDirsExtractionExecutable
+      TestSuite -> modulesCompleter sourceDirsExtractionTestSuite
+      Benchmark -> modulesCompleter sourceDirsExtractionBenchmark
+      ForeignLib -> modulesCompleter sourceDirsExtractionForeignLib
+      Common ->
+        -- TODO: We can't provide a module completer because we provide
+        -- module completions based on the "hs-source-dirs" after parsing the file,
+        -- i.e. based on the 'PackageDescription'.
+        -- "common" stanzas are erased in the 'PackageDescription' representation,
+        -- thus we can't provide accurate module completers right now, as we don't
+        -- know what the 'hs-source-dirs' in the "common" stanza are.
+        --
+        -- A potential fix would be to introduce an intermediate representation that
+        -- parses the '.cabal' file s.t. that we have access to the 'hs-source-dirs',
+        -- but not have erased the "common" stanza.
+        noopCompleter
 
 -- | Contains a map of the most commonly used licenses, weighted by their popularity.
 --
diff --git a/plugins/hls-cabal-plugin/test/CabalAdd.hs b/plugins/hls-cabal-plugin/test/CabalAdd.hs
--- a/plugins/hls-cabal-plugin/test/CabalAdd.hs
+++ b/plugins/hls-cabal-plugin/test/CabalAdd.hs
@@ -33,6 +33,8 @@
         (generateAddDependencyTestSession "cabal-add-lib.cabal" ("src" </> "MyLib.hs") "split" [348])
     , runHaskellTestCaseSession "Code Actions - Can add hidden package to a test" ("cabal-add-testdata" </> "cabal-add-tests")
         (generateAddDependencyTestSession "cabal-add-tests.cabal" ("test" </> "Main.hs") "split" [478])
+    , runHaskellTestCaseSession "Code Actions - Can add hidden package to a test with PackageImports" ("cabal-add-testdata" </> "cabal-add-tests")
+        (generateAddDependencyTestSession "cabal-add-tests.cabal" ("test" </> "MainPackageImports.hs") "split" [731])
     , runHaskellTestCaseSession "Code Actions - Can add hidden package to a benchmark" ("cabal-add-testdata" </> "cabal-add-bench")
         (generateAddDependencyTestSession "cabal-add-bench.cabal" ("bench" </> "Main.hs") "split" [403])
 
@@ -121,6 +123,23 @@
                                    ]
                                    [ ("3d-graphics-examples", T.empty)
                                    , ("3d-graphics-examples", "1.1.6")
+                                   ]
+    , testHiddenPackageSuggestions "Check CabalAdd's parser, with version, with PackageImports"
+                                   [ "(needs flag -package-id base-0.1.0.0)"
+                                   , "(needs flag -package-id Blammo-wai-0.11.0)"
+                                   , "(needs flag -package-id BlastHTTP-2.6.4.3)"
+                                   , "(needs flag -package-id CC-delcont-ref-tf-0.0.0.2)"
+                                   , "(needs flag -package-id 3d-graphics-examples-1.1.6)"
+                                   , "(needs flag -package-id AAI-0.1)"
+                                   , "(needs flag -package-id AWin32Console-1.19.1)"
+                                   ]
+                                   [ ("base","0.1.0.0")
+                                   , ("Blammo-wai", "0.11.0")
+                                   , ("BlastHTTP", "2.6.4.3")
+                                   , ("CC-delcont-ref-tf", "0.0.0.2")
+                                   , ("3d-graphics-examples", "1.1.6")
+                                   , ("AAI", "0.1")
+                                   , ("AWin32Console", "1.19.1")
                                    ]
     ]
  where
diff --git a/plugins/hls-cabal-plugin/test/Completer.hs b/plugins/hls-cabal-plugin/test/Completer.hs
--- a/plugins/hls-cabal-plugin/test/Completer.hs
+++ b/plugins/hls-cabal-plugin/test/Completer.hs
@@ -7,6 +7,7 @@
 
 import           Control.Lens                                   ((^.), (^?))
 import           Control.Lens.Prism
+import           Control.Monad                                  (forM_)
 import qualified Data.ByteString                                as ByteString
 import qualified Data.ByteString.Char8                          as BS8
 import           Data.Maybe                                     (mapMaybe)
@@ -40,7 +41,8 @@
       completionHelperTests,
       filePathExposedModulesTests,
       exposedModuleCompleterTests,
-      importCompleterTests
+      importCompleterTests,
+      autogenFieldCompletionTests
     ]
 
 basicCompleterTests :: TestTree
@@ -335,6 +337,26 @@
           (Syntax.Name (Syntax.Position row col) "common")
           [Syntax.SecArgName (Syntax.Position row (col + 7)) (BS8.pack name)]
           []
+
+autogenFieldCompletionTests :: TestTree
+autogenFieldCompletionTests =
+  testGroup "Autogen Field Completer Tests"
+    [ testAutogenField "library"         "completion/autogen-completion.cabal" (Position 6 9)  ["autogen-modules:", "autogen-includes:"]
+    , testAutogenField "executable"      "completion/autogen-completion.cabal" (Position 11 9) ["autogen-modules:", "autogen-includes:"]
+    , testAutogenField "test-suite"      "completion/autogen-completion.cabal" (Position 16 9) ["autogen-modules:", "autogen-includes:"]
+    , testAutogenField "benchmark"       "completion/autogen-completion.cabal" (Position 21 9) ["autogen-modules:", "autogen-includes:"]
+    , testAutogenField "common"          "completion/autogen-completion.cabal" (Position 24 9) ["autogen-modules:", "autogen-includes:"]
+    ]
+
+  where
+    testAutogenField :: String -> FilePath -> Position -> [T.Text] -> TestTree
+    testAutogenField section file pos expected = runCabalTestCaseSession ("autogen-modules completion in " <> section) "" $ do
+      doc <- openDoc file "cabal"
+      items <- getCompletions doc pos
+      let labels = map (^. L.label) items
+      liftIO $ forM_ expected $ \expect ->
+        assertBool (T.unpack expect <> " not found in " <> section) $
+          any (expect `T.isInfixOf`) labels
 
 simpleCompleterData :: Maybe StanzaName -> FilePath -> T.Text -> CompleterData
 simpleCompleterData sName dir pref = do
diff --git a/plugins/hls-cabal-plugin/test/Main.hs b/plugins/hls-cabal-plugin/test/Main.hs
--- a/plugins/hls-cabal-plugin/test/Main.hs
+++ b/plugins/hls-cabal-plugin/test/Main.hs
@@ -131,29 +131,6 @@
                 expectNoMoreDiagnostics 1 hsDoc "typechecking"
                 cabalDoc <- openDoc "simple-cabal.cabal" "cabal"
                 expectNoMoreDiagnostics 1 cabalDoc "parsing"
-            , runCabalTestCaseSession "Diagnostics in .hs files from invalid .cabal file" "simple-cabal" $ do
-                    hsDoc <- openDoc "A.hs" "haskell"
-                    expectNoMoreDiagnostics 1 hsDoc "typechecking"
-                    cabalDoc <- openDoc "simple-cabal.cabal" "cabal"
-                    expectNoMoreDiagnostics 1 cabalDoc "parsing"
-                    let theRange = Range (Position 3 20) (Position 3 23)
-                    -- Invalid license
-                    changeDoc
-                        cabalDoc
-                        [ TextDocumentContentChangeEvent $
-                            InL TextDocumentContentChangePartial
-                                { _range = theRange
-                                , _rangeLength = Nothing
-                                , _text = "MIT3"
-                                }
-                        ]
-                    cabalDiags <- waitForDiagnosticsFrom cabalDoc
-                    unknownLicenseDiag <- liftIO $ inspectDiagnostic cabalDiags ["Unknown SPDX license identifier: 'MIT3'"]
-                    expectNoMoreDiagnostics 1 hsDoc "typechecking"
-                    liftIO $ do
-                        length cabalDiags @?= 1
-                        unknownLicenseDiag ^. L.range @?= Range (Position 3 24) (Position 4 0)
-                        unknownLicenseDiag ^. L.severity @?= Just DiagnosticSeverity_Error
             ]
         ]
 -- ----------------------------------------------------------------------------
diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/cabal-add-tests.cabal b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/cabal-add-tests.cabal
--- a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/cabal-add-tests.cabal
+++ b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/cabal-add-tests.cabal
@@ -16,3 +16,11 @@
     hs-source-dirs:   test
     main-is:          Main.hs
     build-depends:    base
+
+test-suite cabal-add-tests-test-package-imports
+    import:           warnings
+    default-language: Haskell2010
+    type:             exitcode-stdio-1.0
+    hs-source-dirs:   test
+    main-is:          MainPackageImports.hs
+    build-depends:    base
diff --git a/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/test/MainPackageImports.hs b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/test/MainPackageImports.hs
new file mode 100644
--- /dev/null
+++ b/plugins/hls-cabal-plugin/test/testdata/cabal-add-testdata/cabal-add-tests/test/MainPackageImports.hs
@@ -0,0 +1,8 @@
+{-# LANGUAGE PackageImports #-}
+
+module Main (main) where
+
+import "split" Data.List.Split
+
+main :: IO ()
+main = putStrLn "Test suite not yet implemented."
diff --git a/plugins/hls-cabal-plugin/test/testdata/completion/autogen-completion.cabal b/plugins/hls-cabal-plugin/test/testdata/completion/autogen-completion.cabal
new file mode 100644
--- /dev/null
+++ b/plugins/hls-cabal-plugin/test/testdata/completion/autogen-completion.cabal
@@ -0,0 +1,25 @@
+cabal-version: 3.0
+name: autogen-completion
+version: 0.1.0.0
+
+library
+  hs-source-dirs: src
+  autogen-
+
+executable autoexe
+  main-is: Main.hs
+  hs-source-dirs: src
+  autogen-
+
+test-suite autotest
+  type: exitcode-stdio-1.0
+  hs-source-dirs: src
+  autogen-
+
+benchmark autobench
+  type: exitcode-stdio-1.0
+  hs-source-dirs: src
+  autogen-
+
+common defaults
+  autogen-
diff --git a/plugins/hls-eval-plugin/src/Ide/Plugin/Eval.hs b/plugins/hls-eval-plugin/src/Ide/Plugin/Eval.hs
--- a/plugins/hls-eval-plugin/src/Ide/Plugin/Eval.hs
+++ b/plugins/hls-eval-plugin/src/Ide/Plugin/Eval.hs
@@ -13,8 +13,8 @@
 
 import           Development.IDE               (IdeState)
 import           Ide.Logger                    (Recorder, WithPriority)
-import qualified Ide.Plugin.Eval.CodeLens      as CL
 import           Ide.Plugin.Eval.Config
+import qualified Ide.Plugin.Eval.Handlers      as Handlers
 import           Ide.Plugin.Eval.Rules         (rules)
 import qualified Ide.Plugin.Eval.Types         as Eval
 import           Ide.Types                     (ConfigDescriptor (..),
@@ -27,9 +27,12 @@
 -- |Plugin descriptor
 descriptor :: Recorder (WithPriority Eval.Log) -> PluginId -> PluginDescriptor IdeState
 descriptor recorder plId =
-    (defaultPluginDescriptor plId "Provies a code lens to evaluate expressions in doctest comments")
-        { pluginHandlers = mkPluginHandler SMethod_TextDocumentCodeLens (CL.codeLens recorder)
-        , pluginCommands = [CL.evalCommand recorder plId]
+    (defaultPluginDescriptor plId "Provies code action and lens to evaluate expressions in doctest comments")
+        { pluginHandlers = mconcat
+            [ mkPluginHandler SMethod_TextDocumentCodeAction (Handlers.codeAction recorder)
+            , mkPluginHandler SMethod_TextDocumentCodeLens (Handlers.codeLens recorder)
+            ]
+        , pluginCommands = [Handlers.evalCommand recorder plId]
         , pluginRules = rules recorder
         , pluginConfigDescriptor = defaultConfigDescriptor
                                    { configCustomConfig = mkCustomConfig properties
diff --git a/plugins/hls-eval-plugin/src/Ide/Plugin/Eval/CodeLens.hs b/plugins/hls-eval-plugin/src/Ide/Plugin/Eval/CodeLens.hs
deleted file mode 100644
--- a/plugins/hls-eval-plugin/src/Ide/Plugin/Eval/CodeLens.hs
+++ /dev/null
@@ -1,675 +0,0 @@
-{-# LANGUAGE CPP                       #-}
-{-# LANGUAGE DuplicateRecordFields     #-}
-{-# LANGUAGE ExtendedDefaultRules      #-}
-{-# LANGUAGE NoMonomorphismRestriction #-}
-{-# LANGUAGE OverloadedStrings         #-}
-{-# LANGUAGE RecordWildCards           #-}
-{-# LANGUAGE ViewPatterns              #-}
-{-# OPTIONS_GHC -Wno-type-defaults #-}
-
-{- |
-A plugin inspired by the REPLoid feature of <https://github.com/jyp/dante Dante>, <https://www.haskell.org/haddock/doc/html/ch03s08.html#idm140354810775744 Haddock>'s Examples and Properties and <https://hackage.haskell.org/package/doctest Doctest>.
-
-For a full example see the "Ide.Plugin.Eval.Tutorial" module.
--}
-module Ide.Plugin.Eval.CodeLens (
-    codeLens,
-    evalCommand,
-) where
-
-import           Control.Applicative                          (Alternative ((<|>)))
-import           Control.Arrow                                (second)
-import           Control.Exception                            (bracket_)
-import qualified Control.Exception                            as E
-import           Control.Lens                                 (ix, (%~), (^.))
-import           Control.Monad                                (guard, void,
-                                                               when)
-import           Control.Monad.IO.Class                       (MonadIO (liftIO))
-import           Control.Monad.Trans.Except                   (ExceptT (..),
-                                                               runExceptT)
-import           Data.Aeson                                   (toJSON)
-import           Data.Char                                    (isSpace)
-import           Data.Foldable                                (toList)
-import           Data.List                                    (dropWhileEnd,
-                                                               find,
-                                                               intercalate,
-                                                               intersperse)
-import qualified Data.Map                                     as Map
-import           Data.Maybe                                   (catMaybes)
-import           Data.String                                  (IsString)
-import           Data.Text                                    (Text)
-import qualified Data.Text                                    as T
-import qualified Data.Text.Utf16.Rope.Mixed                   as Rope
-import           Development.IDE.Core.FileStore               (getUriContents)
-import           Development.IDE.Core.Rules                   (IdeState,
-                                                               runAction)
-import           Development.IDE.Core.RuleTypes               (LinkableResult (linkableHomeMod),
-                                                               TypeCheck (..),
-                                                               tmrTypechecked)
-import           Development.IDE.Core.Shake                   (useNoFile_, use_,
-                                                               uses_)
-import           Development.IDE.GHC.Compat                   hiding (typeKind,
-                                                               unitState)
-import           Development.IDE.GHC.Compat.Util              (OverridingBool (..))
-import           Development.IDE.GHC.Util                     (evalGhcEnv,
-                                                               modifyDynFlags)
-import           Development.IDE.Import.DependencyInformation (transitiveDeps,
-                                                               transitiveModuleDeps)
-import           Development.IDE.Types.Location               (toNormalizedFilePath')
-import           GHC                                          (ClsInst,
-                                                               ExecOptions (execLineNumber, execSourceFile),
-                                                               FamInst,
-                                                               GhcMonad,
-                                                               NamedThing (getName),
-                                                               defaultFixity,
-                                                               execOptions,
-                                                               exprType,
-                                                               getInfo,
-                                                               getInteractiveDynFlags,
-                                                               isImport, isStmt,
-                                                               parseName,
-                                                               pprFamInst,
-                                                               pprInstance,
-                                                               typeKind)
-
-
-import           Development.IDE.Core.RuleTypes               (GetLinkable (GetLinkable),
-                                                               GetModSummary (GetModSummary),
-                                                               GetModuleGraph (GetModuleGraph),
-                                                               GhcSessionDeps (GhcSessionDeps),
-                                                               ModSummaryResult (msrModSummary))
-import           Development.IDE.Core.Shake                   (VFSModified (VFSUnmodified))
-import qualified Development.IDE.GHC.Compat.Core              as Compat (InteractiveImport (IIModule))
-import qualified Development.IDE.GHC.Compat.Core              as SrcLoc (unLoc)
-import           Development.IDE.Types.HscEnvEq               (HscEnvEq (hscEnv))
-import qualified GHC.LanguageExtensions.Type                  as LangExt (Extension (..))
-
-import           Development.IDE.Core.FileStore               (setSomethingModified)
-import           Development.IDE.Core.PluginUtils
-import           Development.IDE.Types.Shake                  (toKey)
-import           GHC.Types.SrcLoc                             (UnhelpfulSpanReason (UnhelpfulInteractive))
-import           Ide.Logger                                   (Priority (..),
-                                                               Recorder,
-                                                               WithPriority,
-                                                               logWith)
-import           Ide.Plugin.Error                             (PluginError (PluginInternalError),
-                                                               handleMaybeM)
-import           Ide.Plugin.Eval.Code                         (Statement,
-                                                               asStatements,
-                                                               myExecStmt,
-                                                               propSetup,
-                                                               resultRange,
-                                                               testCheck,
-                                                               testRanges)
-import           Ide.Plugin.Eval.Config                       (EvalConfig (..),
-                                                               getEvalConfig)
-import           Ide.Plugin.Eval.GHC                          (addImport,
-                                                               addPackages,
-                                                               hasPackage,
-                                                               setSessionAndInteractiveDynFlags)
-import           Ide.Plugin.Eval.Parse.Comments               (commentsToSections)
-import           Ide.Plugin.Eval.Parse.Option                 (parseSetFlags)
-import           Ide.Plugin.Eval.Rules                        (queueForEvaluation,
-                                                               unqueueForEvaluation)
-import           Ide.Plugin.Eval.Types
-import           Ide.Plugin.Eval.Util                         (gStrictTry,
-                                                               isLiterate,
-                                                               prettyWarnings,
-                                                               response', timed)
-import           Ide.Types
-import qualified Language.LSP.Protocol.Lens                   as L
-import           Language.LSP.Protocol.Message
-import           Language.LSP.Protocol.Types
-import           Language.LSP.Server
-#if MIN_VERSION_ghc(9,11,0)
-import           GHC.Unit.Module.ModIface                     (IfaceTopEnv (..))
-#endif
-
-
-{- | Code Lens provider
- NOTE: Invoked every time the document is modified, not just when the document is saved.
--}
-codeLens :: Recorder (WithPriority Log) -> PluginMethodHandler IdeState Method_TextDocumentCodeLens
-codeLens recorder st plId CodeLensParams{_textDocument} =
-    let dbg = logWith recorder Debug
-        perf = timed (\lbl duration -> dbg $ LogExecutionTime lbl duration)
-     in perf "codeLens" $
-            do
-                let TextDocumentIdentifier uri = _textDocument
-                fp <- uriToFilePathE uri
-                let nfp = toNormalizedFilePath' fp
-                    isLHS = isLiterate fp
-                dbg $ LogCodeLensFp fp
-                (comments, _) <-
-                    runActionE "eval.GetParsedModuleWithComments" st $ useWithStaleE GetEvalComments nfp
-                dbg $ LogCodeLensComments comments
-
-                -- Extract tests from source code
-                let Sections{..} = commentsToSections isLHS comments
-                    tests = testsBySection nonSetupSections
-                    cmd = mkLspCommand plId evalCommandName "Evaluate=..." (Just [])
-                let lenses =
-                        [ CodeLens testRange (Just cmd') Nothing
-                        | (section, ident, test) <- tests
-                        , let (testRange, resultRange) = testRanges test
-                              args = EvalParams (setupSections ++ [section]) _textDocument ident
-                              cmd' =
-                                (cmd :: Command)
-                                    { _arguments = Just [toJSON args]
-                                    , _title =
-                                        if trivial resultRange
-                                            then "Evaluate..."
-                                            else "Refresh..."
-                                    }
-                        ]
-
-                perf "tests" $
-                    dbg $ LogTests
-                            (length tests)
-                            (length nonSetupSections)
-                            (length setupSections)
-                            (length lenses)
-
-                return $ InL lenses
-  where
-    trivial (Range p p') = p == p'
-
-evalCommandName :: CommandId
-evalCommandName = "evalCommand"
-
-evalCommand :: Recorder (WithPriority Log) -> PluginId -> PluginCommand IdeState
-evalCommand recorder plId = PluginCommand evalCommandName "evaluate" (runEvalCmd recorder plId)
-
-type EvalId = Int
-
-runEvalCmd :: Recorder (WithPriority Log) -> PluginId -> CommandFunction IdeState EvalParams
-runEvalCmd recorder plId st mtoken EvalParams{..} =
-    let dbg = logWith recorder Debug
-        perf = timed (\lbl duration -> dbg $ LogExecutionTime lbl duration)
-        cmd :: ExceptT PluginError (HandlerM Config) WorkspaceEdit
-        cmd = do
-            let tests = map (\(a,_,b) -> (a,b)) $ testsBySection sections
-
-            let TextDocumentIdentifier{_uri} = module_
-            fp <- uriToFilePathE _uri
-            let nfp = toNormalizedFilePath' fp
-            mdlText <- moduleText st _uri
-
-            -- enable codegen for the module which we need to evaluate.
-            final_hscEnv <- liftIO $ bracket_
-              (setSomethingModified VFSUnmodified st "Eval" $ do
-                queueForEvaluation st nfp
-                return [toKey IsEvaluating nfp]
-                )
-              (setSomethingModified VFSUnmodified st "Eval" $ do
-                unqueueForEvaluation st nfp
-                return [toKey IsEvaluating nfp]
-                )
-              (initialiseSessionForEval (needsQuickCheck tests) st nfp)
-
-            evalCfg <- liftIO $ runAction "eval: config" st $ getEvalConfig plId
-
-            -- Perform the evaluation of the command
-            edits <-
-                perf "edits" $
-                    liftIO $
-                        evalGhcEnv final_hscEnv $ do
-                            runTests recorder evalCfg fp tests
-
-            let workspaceEditsMap = Map.singleton _uri (addFinalReturn mdlText edits)
-            let workspaceEdits = WorkspaceEdit (Just workspaceEditsMap) Nothing Nothing
-
-            return workspaceEdits
-     in perf "evalCmd" $ ExceptT $
-            pluginWithIndefiniteProgress "Evaluating" mtoken Cancellable $ \_updater ->
-                runExceptT $ response' cmd
-
--- | Create an HscEnv which is suitable for performing interactive evaluation.
--- All necessary home modules will have linkables and the current module will
--- also be loaded into the environment.
---
--- The interactive context and interactive dynamic flags are also set appropiately.
-initialiseSessionForEval :: Bool -> IdeState -> NormalizedFilePath -> IO HscEnv
-initialiseSessionForEval needs_quickcheck st nfp = do
-  (ms, env1) <- runAction "runEvalCmd" st $ do
-
-    ms <- msrModSummary <$> use_ GetModSummary nfp
-    deps_hsc <- hscEnv <$> use_ GhcSessionDeps nfp
-
-    linkables_needed <- transitiveDeps <$> useNoFile_ GetModuleGraph <*> pure nfp
-    linkables <- uses_ GetLinkable (nfp : maybe [] transitiveModuleDeps linkables_needed)
-    -- We unset the global rdr env in mi_globals when we generate interfaces
-    -- See Note [Clearing mi_globals after generating an iface]
-    -- However, the eval plugin (setContext specifically) requires the rdr_env
-    -- for the current module - so get it from the Typechecked Module and add
-    -- it back to the iface for the current module.
-    tm <- tmrTypechecked <$> use_ TypeCheck nfp
-    let rdr_env = tcg_rdr_env tm
-    let linkable_hsc = loadModulesHome (map (addRdrEnv . linkableHomeMod) linkables) deps_hsc
-        addRdrEnv hmi
-          | iface <- hm_iface hmi
-          , ms_mod ms == mi_module iface
-#if MIN_VERSION_ghc(9,11,0)
-          = hmi { hm_iface = set_mi_top_env (Just $ IfaceTopEnv (forceGlobalRdrEnv (globalRdrEnvLocal rdr_env)) (mkIfaceImports $ tcg_import_decls tm)) iface}
-#else
-          = hmi { hm_iface = iface { mi_globals = Just $!
-#if MIN_VERSION_ghc(9,8,0)
-                    forceGlobalRdrEnv
-#endif
-                      rdr_env
-                }}
-#endif
-          | otherwise = hmi
-
-    return (ms, linkable_hsc)
-  -- Bit awkward we need to use evalGhcEnv here but setContext requires to run
-  -- in the Ghc monad
-  env2 <- liftIO $ evalGhcEnv env1 $ do
-            setContext [Compat.IIModule (moduleName (ms_mod ms))]
-            let df = flip xopt_set    LangExt.ExtendedDefaultRules
-                   . flip xopt_unset  LangExt.MonomorphismRestriction
-                   . flip gopt_set    Opt_ImplicitImportQualified
-                   . flip gopt_unset  Opt_DiagnosticsShowCaret
-                   . setBackend ghciBackend
-                   $ (ms_hspp_opts ms) {
-                        useColor = Never
-                      , canUseColor = False }
-            modifyDynFlags (const df)
-            when needs_quickcheck $ void $ addPackages ["QuickCheck"]
-            getSession
-  return env2
-
-#if MIN_VERSION_ghc(9,11,0)
-mkIfaceImports :: [ImportUserSpec] -> [IfaceImport]
-mkIfaceImports = map go
-  where
-    go (ImpUserSpec decl ImpUserAll) = IfaceImport decl ImpIfaceAll
-    go (ImpUserSpec decl (ImpUserExplicit env)) = IfaceImport decl (ImpIfaceExplicit (forceGlobalRdrEnv env))
-    go (ImpUserSpec decl (ImpUserEverythingBut ns)) = IfaceImport decl (ImpIfaceEverythingBut ns)
-#endif
-
-addFinalReturn :: Text -> [TextEdit] -> [TextEdit]
-addFinalReturn mdlText edits
-    | not (null edits) && not (T.null mdlText) && T.last mdlText /= '\n' =
-        finalReturn mdlText : edits
-    | otherwise = edits
-
-finalReturn :: Text -> TextEdit
-finalReturn txt =
-    let ls = T.lines txt
-        l = fromIntegral $ length ls -1
-        c = fromIntegral $ T.length . last $ ls
-        p = Position l c
-     in TextEdit (Range p p) "\n"
-
-moduleText :: IdeState -> Uri -> ExceptT PluginError (HandlerM config) Text
-moduleText state uri = do
-    contents <-
-        handleMaybeM (PluginInternalError "mdlText") $
-            liftIO $
-                runAction "eval.getUriContents" state $
-                    getUriContents $
-                        toNormalizedUri uri
-    pure $ Rope.toText contents
-
-testsBySection :: [Section] -> [(Section, EvalId, Test)]
-testsBySection sections =
-    [(section, ident, test)
-    | (ident, section) <- zip [0..] sections
-    , test <- sectionTests section
-    ]
-
-type TEnv = String
--- |GHC declarations required for expression evaluation
-evalSetup :: Ghc ()
-evalSetup = do
-    preludeAsP <- parseImportDecl "import qualified Prelude as P"
-    context <- getContext
-    setContext (IIDecl preludeAsP : context)
-
-runTests :: Recorder (WithPriority Log) -> EvalConfig -> TEnv -> [(Section, Test)] -> Ghc [TextEdit]
-runTests recorder EvalConfig{..} e tests = do
-    df <- getInteractiveDynFlags
-    evalSetup
-    when (hasQuickCheck df && needsQuickCheck tests) $ void $ evals recorder True e df propSetup
-
-    mapM (processTest e df) tests
-  where
-    processTest :: TEnv -> DynFlags -> (Section, Test) -> Ghc TextEdit
-    processTest fp df (section, test) = do
-        let dbg = logWith recorder Debug
-        let pad = pad_ $ (if isLiterate fp then ("> " `T.append`) else id) $ padPrefix (sectionFormat section)
-        rs <- runTest e df test
-        dbg $ LogRunTestResults rs
-
-        let checkedResult = testCheck eval_cfg_diff (section, test) rs
-        let resultLines = concatMap T.lines checkedResult
-
-        let edit = asEdit (sectionFormat section) test (map pad resultLines)
-        dbg $ LogRunTestEdits edit
-        return edit
-
-    -- runTest :: String -> DynFlags -> Loc Test -> Ghc [Text]
-    runTest _ df test
-        | not (hasQuickCheck df) && isProperty test =
-            return $
-                singleLine
-                    "Add QuickCheck to your cabal dependencies to run this test."
-    runTest e df test = evals recorder (eval_cfg_exception && not (isProperty test)) e df (asStatements test)
-
-asEdit :: Format -> Test -> [Text] -> TextEdit
-asEdit (MultiLine commRange) test resultLines
-    -- A test in a block comment, ending with @-\}@ without newline in-between.
-    | testRange test ^. L.end . L.line == commRange ^. L.end . L.line
-    =
-    TextEdit
-        (Range
-            (testRange test ^. L.end)
-            (resultRange test ^. L.end)
-        )
-        ("\n" <> T.unlines (resultLines <> ["-}"]))
-asEdit _ test resultLines =
-    TextEdit (resultRange test) (T.unlines resultLines)
-
-{- |
-The result of evaluating a test line can be:
-* a value
-* nothing
-* a (possibly multiline) error message
-
-A value is returned for a correct expression.
-
-Either a pure value:
->>> 'h' :"askell"
-"haskell"
-
-Or an 'IO a' (output on stdout/stderr is ignored):
->>> print "OK" >> return "ABC"
-"ABC"
-
-Nothing is returned for a correct directive:
-
->>>:set -XFlexibleInstances
->>> import Data.Maybe
-
-Nothing is returned for a correct declaration (let..,x=, data, class)
-
->>> let x = 11
->>> y = 22
->>> data B = T | F
->>> class C a
-
-Nothing is returned for an empty line:
-
->>>
-
-A, possibly multi line, error is returned for a wrong declaration, directive or value or an exception thrown by the evaluated code:
-
->>>:set -XNonExistent
-Some flags have not been recognized: -XNonExistent
-
->>> cls C
-Variable not in scope: cls :: t0 -> t
-Data constructor not in scope: C
-
->>> "A
-lexical error in string/character literal at end of input
-
-Exceptions are shown as if printed, but it can be configured to include prefix like
-in GHCi or doctest. This allows it to be used as a hack to simulate print until we
-get proper IO support. See #1977
-
->>> 3 `div` 0
-divide by zero
-
->>> error "Something went wrong\nbad times" :: E.SomeException
-Something went wrong
-bad times
-
-Or for a value that does not have a Show instance and can therefore not be displayed:
->>> data V = V
->>> V
-No instance for (Show V) arising from a use of ‘evalPrint’
--}
-evals :: Recorder (WithPriority Log) -> Bool -> TEnv -> DynFlags -> [Statement] -> Ghc [Text]
-evals recorder mark_exception fp df stmts = do
-    er <- gStrictTry $ mapM eval stmts
-    return $ case er of
-        Left err -> errorLines err
-        Right rs -> concat . catMaybes $ rs
-  where
-    dbg = logWith recorder Debug
-    eval :: Statement -> Ghc (Maybe [Text])
-    eval (Located l stmt)
-        | -- GHCi flags
-          Just (words -> flags) <- parseSetFlags stmt = do
-            dbg $ LogEvalFlags flags
-            ndf <- getInteractiveDynFlags
-            dbg $ LogEvalPreSetDynFlags ndf
-            eans <-
-                liftIO $ try @GhcException $
-                parseDynamicFlagsCmdLine ndf
-                (map (L $ UnhelpfulSpan unhelpfulReason) flags)
-            dbg $ LogEvalParsedFlags eans
-            case eans of
-                Left err -> pure $ Just $ errorLines $ show err
-                Right (df', ignoreds, warns) -> do
-                    let warnings = do
-                            guard $ not $ null warns
-                            pure $ errorLines $
-                                prettyWarnings warns
-                        igns = do
-                            guard $ not $ null ignoreds
-                            pure
-                                ["Some flags have not been recognized: "
-                                <> T.pack (intercalate ", " $ map SrcLoc.unLoc ignoreds)
-                                ]
-                    dbg $ LogEvalPostSetDynFlags df'
-                    setSessionAndInteractiveDynFlags df'
-                    pure $ warnings <> igns
-        | -- A type/kind command
-          Just (cmd, arg) <- parseGhciLikeCmd $ T.pack stmt =
-            evalGhciLikeCmd cmd arg
-        | -- A statement
-          isStmt pf stmt =
-            do
-                dbg $ LogEvalStmtStart stmt
-                res <- exec stmt l
-                let r = case res of
-                        Left err -> Just . (if mark_exception then exceptionLines else errorLines) $ err
-                        Right x  -> singleLine <$> x
-                dbg $ LogEvalStmtResult r
-                return r
-        | -- An import
-          isImport pf stmt =
-            do
-                dbg $ LogEvalImport stmt
-                _ <- addImport stmt
-                return Nothing
-        | -- A declaration
-          otherwise =
-            do
-                dbg $ LogEvalDeclaration stmt
-                void $ runDecls stmt
-                return Nothing
-    pf = initParserOpts df
-    unhelpfulReason = UnhelpfulInteractive
-    exec stmt l =
-        let opts = execOptions{execSourceFile = fp, execLineNumber = l}
-         in myExecStmt stmt opts
-
-needsQuickCheck :: [(Section, Test)] -> Bool
-needsQuickCheck = any (isProperty . snd)
-
-hasQuickCheck :: DynFlags -> Bool
-hasQuickCheck df = hasPackage df "QuickCheck"
-
-singleLine :: String -> [Text]
-singleLine s = [T.pack s]
-
-{- |
- Convert error messages to a list of text lines
- Remove unnecessary information.
--}
-errorLines :: String -> [Text]
-errorLines =
-        dropWhileEnd T.null
-        . takeWhile (not . (\x -> "CallStack" `T.isPrefixOf` x || "HasCallStack" `T.isPrefixOf` x))
-        . T.lines
-        . T.pack
-
-{- |
- Convert exception messages to a list of text lines
- Remove unnecessary information and mark it as exception.
- We use '*** Exception:' to make it identical to doctest
- output, see #2353.
--}
-exceptionLines :: String -> [Text]
-exceptionLines = (ix 0 %~ ("*** Exception: " <>)) . errorLines
-
-{- |
->>> map (pad_ (T.pack "--")) (map T.pack ["2+2",""])
-["--2+2","--<BLANKLINE>"]
--}
-pad_ :: Text -> Text -> Text
-pad_ prefix = (prefix `T.append`) . convertBlank
-
-convertBlank :: Text -> Text
-convertBlank x
-    | T.null x = "<BLANKLINE>"
-    | otherwise = x
-
-padPrefix :: IsString p => Format -> p
-padPrefix SingleLine = "-- "
-padPrefix _          = ""
-
-{- | Resulting @Text@ MUST NOT prefix each line with @--@
-   Such comment-related post-process will be taken place
-   solely in 'evalGhciLikeCmd'.
--}
-type GHCiLikeCmd = DynFlags -> Text -> Ghc (Maybe Text)
-
--- Should we use some sort of trie here?
-ghciLikeCommands :: [(Text, GHCiLikeCmd)]
-ghciLikeCommands =
-    [ ("info", doInfoCmd False)
-    , ("info!", doInfoCmd True)
-    , ("kind", doKindCmd False)
-    , ("kind!", doKindCmd True)
-    , ("type", doTypeCmd)
-    ]
-
-evalGhciLikeCmd :: Text -> Text -> Ghc (Maybe [Text])
-evalGhciLikeCmd cmd arg = do
-    df <- getSessionDynFlags
-    case lookup cmd ghciLikeCommands
-        <|> snd
-        <$> find (T.isPrefixOf cmd . fst) ghciLikeCommands of
-        Just hndler ->
-            fmap
-                T.lines
-                <$> hndler df arg
-        _ -> E.throw $ GhciLikeCmdNotImplemented cmd arg
-
-doInfoCmd :: Bool -> DynFlags -> Text -> Ghc (Maybe Text)
-doInfoCmd allInfo dflags s = do
-    sdocs <- mapM infoThing (T.words s)
-    pure $ Just $ T.pack $ showSDoc dflags (vcat sdocs)
-    where
-        infoThing :: GHC.GhcMonad m => Text -> m SDoc
-        infoThing (T.unpack -> str) = do
-            names     <- GHC.parseName str
-            mb_stuffs <- mapM (GHC.getInfo allInfo) names
-            let filtered = filterOutChildren (\(t,_f,_ci,_fi,_sd) -> t)
-                                            (catMaybes $ toList mb_stuffs)
-            return $ vcat (intersperse (text "") $ map pprInfo filtered)
-
-        filterOutChildren :: (a -> TyThing) -> [a] -> [a]
-        filterOutChildren get_thing xs
-            = filter (not . has_parent) xs
-            where
-                all_names = mkNameSet (map (getName . get_thing) xs)
-                has_parent x = case tyThingParent_maybe (get_thing x) of
-                                Just p  -> getName p `elemNameSet` all_names
-                                Nothing -> False
-
-        pprInfo :: (TyThing, Fixity, [GHC.ClsInst], [GHC.FamInst], SDoc) -> SDoc
-        pprInfo (thing, fixity, cls_insts, fam_insts, docs)
-            =  docs
-            $$ pprTyThingInContextLoc thing
-            $$ showFixity thing fixity
-            $$ vcat (map GHC.pprInstance cls_insts)
-            $$ vcat (map GHC.pprFamInst  fam_insts)
-
-        pprTyThingInContextLoc :: TyThing -> SDoc
-        pprTyThingInContextLoc tyThing
-            = showWithLoc (pprDefinedAt (getName tyThing))
-                          (pprTyThingInContext showToHeader tyThing)
-
-        showWithLoc :: SDoc -> SDoc -> SDoc
-        showWithLoc loc doc
-            = hang doc 2 (text "\t--" <+> loc)
-
-        showFixity :: TyThing -> Fixity -> SDoc
-        showFixity thing fixity
-            | fixity /= GHC.defaultFixity || isSymOcc (getOccName thing)
-                = ppr fixity <+> pprInfixName (GHC.getName thing)
-            | otherwise = empty
-
-doKindCmd :: Bool -> DynFlags -> Text -> Ghc (Maybe Text)
-doKindCmd False df arg = do
-    let input = T.strip arg
-    (_, kind) <- typeKind False $ T.unpack input
-    let kindText = text (T.unpack input) <+> "::" <+> pprSigmaType kind
-    pure $ Just $ T.pack (showSDoc df kindText)
-doKindCmd True df arg = do
-    let input = T.strip arg
-    (ty, kind) <- typeKind True $ T.unpack input
-    let kindDoc = text (T.unpack input) <+> "::" <+> pprSigmaType kind
-        tyDoc = "=" <+> pprSigmaType ty
-    pure $ Just $ T.pack (showSDoc df $ kindDoc $$ tyDoc)
-
-doTypeCmd :: DynFlags -> Text -> Ghc (Maybe Text)
-doTypeCmd dflags arg = do
-    let (emod, expr) = parseExprMode arg
-    ty <- GHC.exprType emod $ T.unpack expr
-    let rawType = T.strip $ T.pack $ showSDoc dflags $ pprSigmaType ty
-        broken = T.any (\c -> c == '\r' || c == '\n') rawType
-    pure $
-        Just $
-            if broken
-                then
-                    T.pack $
-                        showSDoc dflags $
-                            text (T.unpack expr)
-                                $$ nest 2 ("::" <+> pprSigmaType ty)
-                else expr <> " :: " <> rawType <> "\n"
-
-parseExprMode :: Text -> (TcRnExprMode, T.Text)
-parseExprMode rawArg = case T.break isSpace rawArg of
-    ("+d", rest) -> (TM_Default, T.strip rest)
-    _            -> (TM_Inst, rawArg)
-
-data GhciLikeCmdException = GhciLikeCmdNotImplemented
-    { ghciCmdName :: Text
-    , ghciCmdArg  :: Text
-    }
-
-instance Show GhciLikeCmdException where
-    showsPrec _ GhciLikeCmdNotImplemented{..} =
-        showString "unknown command '"
-            . showString (T.unpack ghciCmdName)
-            . showChar '\''
-
-instance E.Exception GhciLikeCmdException
-
-{-
->>> parseGhciLikeCmd (T.pack ":kind! N + M + 1")
-Just ("kind!","N + M + 1")
->>> parseGhciLikeCmd (T.pack ":kind a")
-Just ("kind","a")
--}
-parseGhciLikeCmd :: Text -> Maybe (Text, Text)
-parseGhciLikeCmd input = do
-    (':', rest) <- T.uncons $ T.stripStart input
-    pure $ second T.strip $ T.break isSpace rest
diff --git a/plugins/hls-eval-plugin/src/Ide/Plugin/Eval/Handlers.hs b/plugins/hls-eval-plugin/src/Ide/Plugin/Eval/Handlers.hs
new file mode 100644
--- /dev/null
+++ b/plugins/hls-eval-plugin/src/Ide/Plugin/Eval/Handlers.hs
@@ -0,0 +1,695 @@
+{-# LANGUAGE CPP                       #-}
+{-# LANGUAGE DuplicateRecordFields     #-}
+{-# LANGUAGE ExtendedDefaultRules      #-}
+{-# LANGUAGE NoMonomorphismRestriction #-}
+{-# LANGUAGE OverloadedStrings         #-}
+{-# LANGUAGE RecordWildCards           #-}
+{-# LANGUAGE ViewPatterns              #-}
+{-# OPTIONS_GHC -Wno-type-defaults #-}
+
+{- |
+A plugin inspired by the REPLoid feature of <https://github.com/jyp/dante Dante>, <https://www.haskell.org/haddock/doc/html/ch03s08.html#idm140354810775744 Haddock>'s Examples and Properties and <https://hackage.haskell.org/package/doctest Doctest>.
+
+For a full example see the "Ide.Plugin.Eval.Tutorial" module.
+-}
+module Ide.Plugin.Eval.Handlers (
+    codeAction,
+    codeLens,
+    evalCommand,
+) where
+
+import           Control.Applicative                          (Alternative ((<|>)))
+import           Control.Arrow                                (second)
+import           Control.Exception                            (bracket_)
+import qualified Control.Exception                            as E
+import           Control.Lens                                 (ix, (%~), (^.))
+import           Control.Monad                                (guard, void,
+                                                               when)
+import           Control.Monad.IO.Class                       (MonadIO (liftIO))
+import           Control.Monad.Trans.Except                   (ExceptT (..),
+                                                               runExceptT)
+import           Data.Aeson                                   (toJSON)
+import           Data.Char                                    (isSpace)
+import           Data.Foldable                                (toList)
+import           Data.List                                    (dropWhileEnd,
+                                                               find,
+                                                               intercalate,
+                                                               intersperse)
+import qualified Data.Map                                     as Map
+import           Data.Maybe                                   (catMaybes)
+import           Data.String                                  (IsString)
+import           Data.Text                                    (Text)
+import qualified Data.Text                                    as T
+import qualified Data.Text.Utf16.Rope.Mixed                   as Rope
+import           Development.IDE.Core.FileStore               (getUriContents)
+import           Development.IDE.Core.Rules                   (IdeState,
+                                                               runAction)
+import           Development.IDE.Core.RuleTypes               (LinkableResult (linkableHomeMod),
+                                                               TypeCheck (..),
+                                                               tmrTypechecked)
+import           Development.IDE.Core.Shake                   (useNoFile_, use_,
+                                                               uses_)
+import           Development.IDE.GHC.Compat                   hiding (typeKind,
+                                                               unitState)
+import           Development.IDE.GHC.Compat.Util              (OverridingBool (..))
+import           Development.IDE.GHC.Util                     (evalGhcEnv,
+                                                               modifyDynFlags)
+import           Development.IDE.Import.DependencyInformation (transitiveDeps,
+                                                               transitiveModuleDeps)
+import           Development.IDE.Types.Location               (toNormalizedFilePath')
+import           GHC                                          (ClsInst,
+                                                               ExecOptions (execLineNumber, execSourceFile),
+                                                               FamInst,
+                                                               GhcMonad,
+                                                               NamedThing (getName),
+                                                               defaultFixity,
+                                                               execOptions,
+                                                               exprType,
+                                                               getInfo,
+                                                               getInteractiveDynFlags,
+                                                               isImport, isStmt,
+                                                               parseName,
+                                                               pprFamInst,
+                                                               pprInstance,
+                                                               typeKind)
+
+
+import           Development.IDE.Core.RuleTypes               (GetLinkable (GetLinkable),
+                                                               GetModSummary (GetModSummary),
+                                                               GetModuleGraph (GetModuleGraph),
+                                                               GhcSessionDeps (GhcSessionDeps),
+                                                               ModSummaryResult (msrModSummary))
+import           Development.IDE.Core.Shake                   (VFSModified (VFSUnmodified))
+import qualified Development.IDE.GHC.Compat.Core              as Compat (InteractiveImport (IIModule))
+import qualified Development.IDE.GHC.Compat.Core              as SrcLoc (unLoc)
+import           Development.IDE.Types.HscEnvEq               (HscEnvEq (hscEnv))
+import qualified GHC.LanguageExtensions.Type                  as LangExt (Extension (..))
+
+import           Data.List.Extra                              (unsnoc)
+import           Development.IDE.Core.FileStore               (setSomethingModified)
+import           Development.IDE.Core.PluginUtils
+import           Development.IDE.Types.Shake                  (toKey)
+import           GHC.Types.SrcLoc                             (UnhelpfulSpanReason (UnhelpfulInteractive))
+import           Ide.Logger                                   (Priority (..),
+                                                               Recorder,
+                                                               WithPriority,
+                                                               logWith)
+import           Ide.Plugin.Error                             (PluginError (PluginInternalError),
+                                                               handleMaybeM)
+import           Ide.Plugin.Eval.Code                         (Statement,
+                                                               asStatements,
+                                                               myExecStmt,
+                                                               propSetup,
+                                                               resultRange,
+                                                               testCheck,
+                                                               testRanges)
+import           Ide.Plugin.Eval.Config                       (EvalConfig (..),
+                                                               getEvalConfig)
+import           Ide.Plugin.Eval.GHC                          (addImport,
+                                                               addPackages,
+                                                               hasPackage,
+                                                               setSessionAndInteractiveDynFlags)
+import           Ide.Plugin.Eval.Parse.Comments               (commentsToSections)
+import           Ide.Plugin.Eval.Parse.Option                 (parseSetFlags)
+import           Ide.Plugin.Eval.Rules                        (queueForEvaluation,
+                                                               unqueueForEvaluation)
+import           Ide.Plugin.Eval.Types
+import           Ide.Plugin.Eval.Util                         (gStrictTry,
+                                                               isLiterate,
+                                                               prettyWarnings,
+                                                               response', timed)
+import           Ide.Types
+import qualified Language.LSP.Protocol.Lens                   as L
+import           Language.LSP.Protocol.Message
+import           Language.LSP.Protocol.Types
+import           Language.LSP.Server
+#if MIN_VERSION_ghc(9,11,0)
+import           GHC.Unit.Module.ModIface                     (IfaceTopEnv (..))
+#endif
+
+codeAction :: Recorder (WithPriority Log) -> PluginMethodHandler IdeState Method_TextDocumentCodeAction
+codeAction recorder st plId CodeActionParams{_textDocument,_range} = do
+    rangeCommands <- mkRangeCommands recorder st plId _textDocument
+    pure
+        $ InL
+            [ InL command
+            | (testRange, command) <- rangeCommands
+            , _range `isSubrangeOf` testRange
+            ]
+
+{- | Code Lens provider
+ NOTE: Invoked every time the document is modified, not just when the document is saved.
+-}
+codeLens :: Recorder (WithPriority Log) -> PluginMethodHandler IdeState Method_TextDocumentCodeLens
+codeLens recorder st plId CodeLensParams{_textDocument} = do
+    rangeCommands <- mkRangeCommands recorder st plId _textDocument
+    pure
+        $ InL
+            [ CodeLens range (Just command) Nothing
+            | (range, command) <- rangeCommands
+            ]
+
+mkRangeCommands :: Recorder (WithPriority Log) -> IdeState -> PluginId -> TextDocumentIdentifier -> ExceptT PluginError (HandlerM Config) [(Range, Command)]
+mkRangeCommands recorder st plId textDocument =
+    let dbg = logWith recorder Debug
+        perf = timed (\lbl duration -> dbg $ LogExecutionTime lbl duration)
+     in perf "evalMkRangeCommands" $
+            do
+                let TextDocumentIdentifier uri = textDocument
+                fp <- uriToFilePathE uri
+                let nfp = toNormalizedFilePath' fp
+                    isLHS = isLiterate fp
+                dbg $ LogCodeLensFp fp
+                (comments, _) <-
+                    runActionE "eval.GetParsedModuleWithComments" st $ useWithStaleE GetEvalComments nfp
+                dbg $ LogCodeLensComments comments
+
+                -- Extract tests from source code
+                let Sections{..} = commentsToSections isLHS comments
+                    tests = testsBySection nonSetupSections
+                    cmd = mkLspCommand plId evalCommandName "Evaluate=..." (Just [])
+                let rangeCommands =
+                        [ (testRange, cmd')
+                        | (section, ident, test) <- tests
+                        , let (testRange, resultRange) = testRanges test
+                              args = EvalParams (setupSections ++ [section]) textDocument ident
+                              cmd' =
+                                (cmd :: Command)
+                                    { _arguments = Just [toJSON args]
+                                    , _title =
+                                        if trivial resultRange
+                                            then "Evaluate..."
+                                            else "Refresh..."
+                                    }
+                        ]
+
+                perf "tests" $
+                    dbg $ LogTests
+                            (length tests)
+                            (length nonSetupSections)
+                            (length setupSections)
+                            (length rangeCommands)
+
+                pure rangeCommands
+  where
+    trivial (Range p p') = p == p'
+
+evalCommandName :: CommandId
+evalCommandName = "evalCommand"
+
+evalCommand :: Recorder (WithPriority Log) -> PluginId -> PluginCommand IdeState
+evalCommand recorder plId = PluginCommand evalCommandName "evaluate" (runEvalCmd recorder plId)
+
+type EvalId = Int
+
+runEvalCmd :: Recorder (WithPriority Log) -> PluginId -> CommandFunction IdeState EvalParams
+runEvalCmd recorder plId st mtoken EvalParams{..} =
+    let dbg = logWith recorder Debug
+        perf = timed (\lbl duration -> dbg $ LogExecutionTime lbl duration)
+        cmd :: ExceptT PluginError (HandlerM Config) WorkspaceEdit
+        cmd = do
+            let tests = map (\(a,_,b) -> (a,b)) $ testsBySection sections
+
+            let TextDocumentIdentifier{_uri} = module_
+            fp <- uriToFilePathE _uri
+            let nfp = toNormalizedFilePath' fp
+            mdlText <- moduleText st _uri
+
+            -- enable codegen for the module which we need to evaluate.
+            final_hscEnv <- liftIO $ bracket_
+              (setSomethingModified VFSUnmodified st "Eval" $ do
+                queueForEvaluation st nfp
+                return [toKey IsEvaluating nfp]
+                )
+              (setSomethingModified VFSUnmodified st "Eval" $ do
+                unqueueForEvaluation st nfp
+                return [toKey IsEvaluating nfp]
+                )
+              (initialiseSessionForEval (needsQuickCheck tests) st nfp)
+
+            evalCfg <- liftIO $ runAction "eval: config" st $ getEvalConfig plId
+
+            -- Perform the evaluation of the command
+            edits <-
+                perf "edits" $
+                    liftIO $
+                        evalGhcEnv final_hscEnv $ do
+                            runTests recorder evalCfg fp tests
+
+            let workspaceEditsMap = Map.singleton _uri (addFinalReturn mdlText edits)
+            let workspaceEdits = WorkspaceEdit (Just workspaceEditsMap) Nothing Nothing
+
+            return workspaceEdits
+     in perf "evalCmd" $ ExceptT $
+            pluginWithIndefiniteProgress "Evaluating" mtoken Cancellable $ \_updater ->
+                runExceptT $ response' cmd
+
+-- | Create an HscEnv which is suitable for performing interactive evaluation.
+-- All necessary home modules will have linkables and the current module will
+-- also be loaded into the environment.
+--
+-- The interactive context and interactive dynamic flags are also set appropiately.
+initialiseSessionForEval :: Bool -> IdeState -> NormalizedFilePath -> IO HscEnv
+initialiseSessionForEval needs_quickcheck st nfp = do
+  (ms, env1) <- runAction "runEvalCmd" st $ do
+
+    ms <- msrModSummary <$> use_ GetModSummary nfp
+    deps_hsc <- hscEnv <$> use_ GhcSessionDeps nfp
+
+    linkables_needed <- transitiveDeps <$> useNoFile_ GetModuleGraph <*> pure nfp
+    linkables <- uses_ GetLinkable (nfp : maybe [] transitiveModuleDeps linkables_needed)
+    -- We unset the global rdr env in mi_globals when we generate interfaces
+    -- See Note [Clearing mi_globals after generating an iface]
+    -- However, the eval plugin (setContext specifically) requires the rdr_env
+    -- for the current module - so get it from the Typechecked Module and add
+    -- it back to the iface for the current module.
+    tm <- tmrTypechecked <$> use_ TypeCheck nfp
+    let rdr_env = tcg_rdr_env tm
+    let linkable_hsc = loadModulesHome (map (addRdrEnv . linkableHomeMod) linkables) deps_hsc
+        addRdrEnv hmi
+          | iface <- hm_iface hmi
+          , ms_mod ms == mi_module iface
+#if MIN_VERSION_ghc(9,11,0)
+          = hmi { hm_iface = set_mi_top_env (Just $ IfaceTopEnv (forceGlobalRdrEnv (globalRdrEnvLocal rdr_env)) (mkIfaceImports $ tcg_import_decls tm)) iface}
+#else
+          = hmi { hm_iface = iface { mi_globals = Just $!
+#if MIN_VERSION_ghc(9,8,0)
+                    forceGlobalRdrEnv
+#endif
+                      rdr_env
+                }}
+#endif
+          | otherwise = hmi
+
+    return (ms, linkable_hsc)
+  -- Bit awkward we need to use evalGhcEnv here but setContext requires to run
+  -- in the Ghc monad
+  env2 <- liftIO $ evalGhcEnv env1 $ do
+            setContext [Compat.IIModule (moduleName (ms_mod ms))]
+            let df = flip xopt_set    LangExt.ExtendedDefaultRules
+                   . flip xopt_unset  LangExt.MonomorphismRestriction
+                   . flip gopt_set    Opt_ImplicitImportQualified
+                   . flip gopt_unset  Opt_DiagnosticsShowCaret
+                   . setBackend ghciBackend
+                   $ (ms_hspp_opts ms) {
+                        useColor = Never
+                      , canUseColor = False }
+            modifyDynFlags (const df)
+            when needs_quickcheck $ void $ addPackages ["QuickCheck"]
+            getSession
+  return env2
+
+#if MIN_VERSION_ghc(9,11,0)
+mkIfaceImports :: [ImportUserSpec] -> [IfaceImport]
+mkIfaceImports = map go
+  where
+    go (ImpUserSpec decl ImpUserAll) = IfaceImport decl ImpIfaceAll
+    go (ImpUserSpec decl (ImpUserExplicit env)) = IfaceImport decl (ImpIfaceExplicit (forceGlobalRdrEnv env))
+    go (ImpUserSpec decl (ImpUserEverythingBut ns)) = IfaceImport decl (ImpIfaceEverythingBut ns)
+#endif
+
+addFinalReturn :: Text -> [TextEdit] -> [TextEdit]
+addFinalReturn mdlText edits
+    | not (null edits) && not (T.null mdlText) && T.last mdlText /= '\n' =
+        finalReturn mdlText : edits
+    | otherwise = edits
+
+finalReturn :: Text -> TextEdit
+finalReturn txt =
+    let ls = T.lines txt
+        l = fromIntegral $ length ls -1
+        c = fromIntegral $ T.length $ maybe T.empty snd (unsnoc ls)
+        p = Position l c
+     in TextEdit (Range p p) "\n"
+
+moduleText :: IdeState -> Uri -> ExceptT PluginError (HandlerM config) Text
+moduleText state uri = do
+    contents <-
+        handleMaybeM (PluginInternalError "mdlText") $
+            liftIO $
+                runAction "eval.getUriContents" state $
+                    getUriContents $
+                        toNormalizedUri uri
+    pure $ Rope.toText contents
+
+testsBySection :: [Section] -> [(Section, EvalId, Test)]
+testsBySection sections =
+    [(section, ident, test)
+    | (ident, section) <- zip [0..] sections
+    , test <- sectionTests section
+    ]
+
+type TEnv = String
+-- |GHC declarations required for expression evaluation
+evalSetup :: Ghc ()
+evalSetup = do
+    preludeAsP <- parseImportDecl "import qualified Prelude as P"
+    context <- getContext
+    setContext (IIDecl preludeAsP : context)
+
+runTests :: Recorder (WithPriority Log) -> EvalConfig -> TEnv -> [(Section, Test)] -> Ghc [TextEdit]
+runTests recorder EvalConfig{..} e tests = do
+    df <- getInteractiveDynFlags
+    evalSetup
+    when (hasQuickCheck df && needsQuickCheck tests) $ void $ evals recorder True e df propSetup
+
+    mapM (processTest e df) tests
+  where
+    processTest :: TEnv -> DynFlags -> (Section, Test) -> Ghc TextEdit
+    processTest fp df (section, test) = do
+        let dbg = logWith recorder Debug
+        let pad = pad_ $ (if isLiterate fp then ("> " `T.append`) else id) $ padPrefix (sectionFormat section)
+        rs <- runTest e df test
+        dbg $ LogRunTestResults rs
+
+        let checkedResult = testCheck eval_cfg_diff (section, test) rs
+        let resultLines = concatMap T.lines checkedResult
+
+        let edit = asEdit (sectionFormat section) test (map pad resultLines)
+        dbg $ LogRunTestEdits edit
+        return edit
+
+    -- runTest :: String -> DynFlags -> Loc Test -> Ghc [Text]
+    runTest _ df test
+        | not (hasQuickCheck df) && isProperty test =
+            return $
+                singleLine
+                    "Add QuickCheck to your cabal dependencies to run this test."
+    runTest e df test = evals recorder (eval_cfg_exception && not (isProperty test)) e df (asStatements test)
+
+asEdit :: Format -> Test -> [Text] -> TextEdit
+asEdit (MultiLine commRange) test resultLines
+    -- A test in a block comment, ending with @-\}@ without newline in-between.
+    | testRange test ^. L.end . L.line == commRange ^. L.end . L.line
+    =
+    TextEdit
+        (Range
+            (testRange test ^. L.end)
+            (resultRange test ^. L.end)
+        )
+        ("\n" <> T.unlines (resultLines <> ["-}"]))
+asEdit _ test resultLines =
+    TextEdit (resultRange test) (T.unlines resultLines)
+
+{- |
+The result of evaluating a test line can be:
+* a value
+* nothing
+* a (possibly multiline) error message
+
+A value is returned for a correct expression.
+
+Either a pure value:
+>>> 'h' :"askell"
+"haskell"
+
+Or an 'IO a' (output on stdout/stderr is ignored):
+>>> print "OK" >> return "ABC"
+"ABC"
+
+Nothing is returned for a correct directive:
+
+>>>:set -XFlexibleInstances
+>>> import Data.Maybe
+
+Nothing is returned for a correct declaration (let..,x=, data, class)
+
+>>> let x = 11
+>>> y = 22
+>>> data B = T | F
+>>> class C a
+
+Nothing is returned for an empty line:
+
+>>>
+
+A, possibly multi line, error is returned for a wrong declaration, directive or value or an exception thrown by the evaluated code:
+
+>>>:set -XNonExistent
+Some flags have not been recognized: -XNonExistent
+
+>>> cls C
+Variable not in scope: cls :: t0 -> t
+Data constructor not in scope: C
+
+>>> "A
+lexical error in string/character literal at end of input
+
+Exceptions are shown as if printed, but it can be configured to include prefix like
+in GHCi or doctest. This allows it to be used as a hack to simulate print until we
+get proper IO support. See #1977
+
+>>> 3 `div` 0
+divide by zero
+
+>>> error "Something went wrong\nbad times" :: E.SomeException
+Something went wrong
+bad times
+
+Or for a value that does not have a Show instance and can therefore not be displayed:
+>>> data V = V
+>>> V
+No instance for (Show V) arising from a use of ‘evalPrint’
+-}
+evals :: Recorder (WithPriority Log) -> Bool -> TEnv -> DynFlags -> [Statement] -> Ghc [Text]
+evals recorder mark_exception fp df stmts = do
+    er <- gStrictTry $ mapM eval stmts
+    return $ case er of
+        Left err -> errorLines err
+        Right rs -> concat . catMaybes $ rs
+  where
+    dbg = logWith recorder Debug
+    eval :: Statement -> Ghc (Maybe [Text])
+    eval (Located l stmt)
+        | -- GHCi flags
+          Just (words -> flags) <- parseSetFlags stmt = do
+            dbg $ LogEvalFlags flags
+            ndf <- getInteractiveDynFlags
+            dbg $ LogEvalPreSetDynFlags ndf
+            eans <-
+                liftIO $ try @GhcException $
+                parseDynamicFlagsCmdLine ndf
+                (map (L $ UnhelpfulSpan unhelpfulReason) flags)
+            dbg $ LogEvalParsedFlags eans
+            case eans of
+                Left err -> pure $ Just $ errorLines $ show err
+                Right (df', ignoreds, warns) -> do
+                    let warnings = do
+                            guard $ not $ null warns
+                            pure $ errorLines $
+                                prettyWarnings warns
+                        igns = do
+                            guard $ not $ null ignoreds
+                            pure
+                                ["Some flags have not been recognized: "
+                                <> T.pack (intercalate ", " $ map SrcLoc.unLoc ignoreds)
+                                ]
+                    dbg $ LogEvalPostSetDynFlags df'
+                    setSessionAndInteractiveDynFlags df'
+                    pure $ warnings <> igns
+        | -- A type/kind command
+          Just (cmd, arg) <- parseGhciLikeCmd $ T.pack stmt =
+            evalGhciLikeCmd cmd arg
+        | -- A statement
+          isStmt pf stmt =
+            do
+                dbg $ LogEvalStmtStart stmt
+                res <- exec stmt l
+                let r = case res of
+                        Left err -> Just . (if mark_exception then exceptionLines else errorLines) $ err
+                        Right x  -> singleLine <$> x
+                dbg $ LogEvalStmtResult r
+                return r
+        | -- An import
+          isImport pf stmt =
+            do
+                dbg $ LogEvalImport stmt
+                _ <- addImport stmt
+                return Nothing
+        | -- A declaration
+          otherwise =
+            do
+                dbg $ LogEvalDeclaration stmt
+                void $ runDecls stmt
+                return Nothing
+    pf = initParserOpts df
+    unhelpfulReason = UnhelpfulInteractive
+    exec stmt l =
+        let opts = execOptions{execSourceFile = fp, execLineNumber = l}
+         in myExecStmt stmt opts
+
+needsQuickCheck :: [(Section, Test)] -> Bool
+needsQuickCheck = any (isProperty . snd)
+
+hasQuickCheck :: DynFlags -> Bool
+hasQuickCheck df = hasPackage df "QuickCheck"
+
+singleLine :: String -> [Text]
+singleLine s = [T.pack s]
+
+{- |
+ Convert error messages to a list of text lines
+ Remove unnecessary information.
+-}
+errorLines :: String -> [Text]
+errorLines =
+        dropWhileEnd T.null
+        . takeWhile (not . (\x -> "CallStack" `T.isPrefixOf` x || "HasCallStack" `T.isPrefixOf` x))
+        . T.lines
+        . T.pack
+
+{- |
+ Convert exception messages to a list of text lines
+ Remove unnecessary information and mark it as exception.
+ We use '*** Exception:' to make it identical to doctest
+ output, see #2353.
+-}
+exceptionLines :: String -> [Text]
+exceptionLines = (ix 0 %~ ("*** Exception: " <>)) . errorLines
+
+{- |
+>>> map (pad_ (T.pack "--")) (map T.pack ["2+2",""])
+["--2+2","--<BLANKLINE>"]
+-}
+pad_ :: Text -> Text -> Text
+pad_ prefix = (prefix `T.append`) . convertBlank
+
+convertBlank :: Text -> Text
+convertBlank x
+    | T.null x = "<BLANKLINE>"
+    | otherwise = x
+
+padPrefix :: IsString p => Format -> p
+padPrefix SingleLine = "-- "
+padPrefix _          = ""
+
+{- | Resulting @Text@ MUST NOT prefix each line with @--@
+   Such comment-related post-process will be taken place
+   solely in 'evalGhciLikeCmd'.
+-}
+type GHCiLikeCmd = DynFlags -> Text -> Ghc (Maybe Text)
+
+-- Should we use some sort of trie here?
+ghciLikeCommands :: [(Text, GHCiLikeCmd)]
+ghciLikeCommands =
+    [ ("info", doInfoCmd False)
+    , ("info!", doInfoCmd True)
+    , ("kind", doKindCmd False)
+    , ("kind!", doKindCmd True)
+    , ("type", doTypeCmd)
+    ]
+
+evalGhciLikeCmd :: Text -> Text -> Ghc (Maybe [Text])
+evalGhciLikeCmd cmd arg = do
+    df <- getSessionDynFlags
+    case lookup cmd ghciLikeCommands
+        <|> snd
+        <$> find (T.isPrefixOf cmd . fst) ghciLikeCommands of
+        Just hndler ->
+            fmap
+                T.lines
+                <$> hndler df arg
+        _ -> E.throw $ GhciLikeCmdNotImplemented cmd arg
+
+doInfoCmd :: Bool -> DynFlags -> Text -> Ghc (Maybe Text)
+doInfoCmd allInfo dflags s = do
+    sdocs <- mapM infoThing (T.words s)
+    pure $ Just $ T.pack $ showSDoc dflags (vcat sdocs)
+    where
+        infoThing :: GHC.GhcMonad m => Text -> m SDoc
+        infoThing (T.unpack -> str) = do
+            names     <- GHC.parseName str
+            mb_stuffs <- mapM (GHC.getInfo allInfo) names
+            let filtered = filterOutChildren (\(t,_f,_ci,_fi,_sd) -> t)
+                                            (catMaybes $ toList mb_stuffs)
+            return $ vcat (intersperse (text "") $ map pprInfo filtered)
+
+        filterOutChildren :: (a -> TyThing) -> [a] -> [a]
+        filterOutChildren get_thing xs
+            = filter (not . has_parent) xs
+            where
+                all_names = mkNameSet (map (getName . get_thing) xs)
+                has_parent x = case tyThingParent_maybe (get_thing x) of
+                                Just p  -> getName p `elemNameSet` all_names
+                                Nothing -> False
+
+        pprInfo :: (TyThing, Fixity, [GHC.ClsInst], [GHC.FamInst], SDoc) -> SDoc
+        pprInfo (thing, fixity, cls_insts, fam_insts, docs)
+            =  docs
+            $$ pprTyThingInContextLoc thing
+            $$ showFixity thing fixity
+            $$ vcat (map GHC.pprInstance cls_insts)
+            $$ vcat (map GHC.pprFamInst  fam_insts)
+
+        pprTyThingInContextLoc :: TyThing -> SDoc
+        pprTyThingInContextLoc tyThing
+            = showWithLoc (pprDefinedAt (getName tyThing))
+                          (pprTyThingInContext showToHeader tyThing)
+
+        showWithLoc :: SDoc -> SDoc -> SDoc
+        showWithLoc loc doc
+            = hang doc 2 (text "\t--" <+> loc)
+
+        showFixity :: TyThing -> Fixity -> SDoc
+        showFixity thing fixity
+            | fixity /= GHC.defaultFixity || isSymOcc (getOccName thing)
+                = ppr fixity <+> pprInfixName (GHC.getName thing)
+            | otherwise = empty
+
+doKindCmd :: Bool -> DynFlags -> Text -> Ghc (Maybe Text)
+doKindCmd False df arg = do
+    let input = T.strip arg
+    (_, kind) <- typeKind False $ T.unpack input
+    let kindText = text (T.unpack input) <+> "::" <+> pprSigmaType kind
+    pure $ Just $ T.pack (showSDoc df kindText)
+doKindCmd True df arg = do
+    let input = T.strip arg
+    (ty, kind) <- typeKind True $ T.unpack input
+    let kindDoc = text (T.unpack input) <+> "::" <+> pprSigmaType kind
+        tyDoc = "=" <+> pprSigmaType ty
+    pure $ Just $ T.pack (showSDoc df $ kindDoc $$ tyDoc)
+
+doTypeCmd :: DynFlags -> Text -> Ghc (Maybe Text)
+doTypeCmd dflags arg = do
+    let (emod, expr) = parseExprMode arg
+    ty <- GHC.exprType emod $ T.unpack expr
+    let rawType = T.strip $ T.pack $ showSDoc dflags $ pprSigmaType ty
+        broken = T.any (\c -> c == '\r' || c == '\n') rawType
+    pure $
+        Just $
+            if broken
+                then
+                    T.pack $
+                        showSDoc dflags $
+                            text (T.unpack expr)
+                                $$ nest 2 ("::" <+> pprSigmaType ty)
+                else expr <> " :: " <> rawType <> "\n"
+
+parseExprMode :: Text -> (TcRnExprMode, T.Text)
+parseExprMode rawArg = case T.break isSpace rawArg of
+    ("+d", rest) -> (TM_Default, T.strip rest)
+    _            -> (TM_Inst, rawArg)
+
+data GhciLikeCmdException = GhciLikeCmdNotImplemented
+    { ghciCmdName :: Text
+    , ghciCmdArg  :: Text
+    }
+
+instance Show GhciLikeCmdException where
+    showsPrec _ GhciLikeCmdNotImplemented{..} =
+        showString "unknown command '"
+            . showString (T.unpack ghciCmdName)
+            . showChar '\''
+
+instance E.Exception GhciLikeCmdException
+
+{-
+>>> parseGhciLikeCmd (T.pack ":kind! N + M + 1")
+Just ("kind!","N + M + 1")
+>>> parseGhciLikeCmd (T.pack ":kind a")
+Just ("kind","a")
+-}
+parseGhciLikeCmd :: Text -> Maybe (Text, Text)
+parseGhciLikeCmd input = do
+    (':', rest) <- T.uncons $ T.stripStart input
+    pure $ second T.strip $ T.break isSpace rest
diff --git a/plugins/hls-eval-plugin/test/Main.hs b/plugins/hls-eval-plugin/test/Main.hs
--- a/plugins/hls-eval-plugin/test/Main.hs
+++ b/plugins/hls-eval-plugin/test/Main.hs
@@ -6,13 +6,15 @@
   ) where
 
 import           Control.Lens               (_Just, folded, preview, view, (^.),
-                                             (^..))
+                                             (^..), (^?))
+import           Control.Monad              (join)
 import           Data.Aeson                 (Value (Object), fromJSON, object,
                                              (.=))
 import           Data.Aeson.Types           (Pair, Result (Success))
 import           Data.List                  (isInfixOf)
 import           Data.List.Extra            (nubOrdOn)
 import qualified Data.Map                   as Map
+import qualified Data.Maybe                 as Maybe
 import qualified Data.Text                  as T
 import           Ide.Plugin.Config          (Config)
 import qualified Ide.Plugin.Config          as Plugin
@@ -59,6 +61,9 @@
         lenses <- getCodeLenses doc
         liftIO $ map (view range) lenses @?= [Range (Position 4 0) (Position 5 0)]
 
+  , goldenWithEvalForCodeAction "Evaluation of expressions via code action" "T1" "hs"
+  , goldenWithEvalForCodeAction "Reevaluation of expressions via code action" "T2" "hs"
+
   , goldenWithEval "Evaluation of expressions" "T1" "hs"
   , goldenWithEval "Reevaluation of expressions" "T2" "hs"
   , goldenWithEval "Evaluation of expressions w/ imports" "T3" "hs"
@@ -221,6 +226,10 @@
 goldenWithEval title path ext =
   goldenWithHaskellDocInTmpDir def evalPlugin title (mkFs $ FS.directProject (path <.> ext)) path "expected" ext executeLensesBackwards
 
+goldenWithEvalForCodeAction :: TestName -> FilePath -> FilePath -> TestTree
+goldenWithEvalForCodeAction title path ext =
+  goldenWithHaskellDocInTmpDir def evalPlugin title (mkFs $ FS.directProject (path <.> ext)) path "expected" ext executeCodeActionsBackwards
+
 goldenWithEvalAndFs :: TestName -> [FS.FileTree] -> FilePath -> FilePath -> TestTree
 goldenWithEvalAndFs title tree path ext =
   goldenWithHaskellDocInTmpDir def evalPlugin title (mkFs tree) path  "expected" ext executeLensesBackwards
@@ -239,14 +248,24 @@
 -- | Execute lenses backwards, to avoid affecting their position in the source file
 executeLensesBackwards :: TextDocumentIdentifier -> Session ()
 executeLensesBackwards doc = do
-  codeLenses <- reverse <$> getCodeLenses doc
+  codeLenses <- getCodeLenses doc
   -- liftIO $ print codeLenses
+  executeCmdsBackwards [c | CodeLens{_command = Just c} <- codeLenses]
 
-  -- Execute sequentially, nubbing elements to avoid
-  -- evaluating the same section with multiple tests
-  -- more than twice
-  mapM_ executeCmd $
-    nubOrdOn actSectionId [c | CodeLens{_command = Just c} <- codeLenses]
+executeCodeActionsBackwards :: TextDocumentIdentifier -> Session ()
+executeCodeActionsBackwards doc = do
+  codeLenses <- getCodeLenses doc
+  let ranges = [_range | CodeLens{_range} <- codeLenses]
+  -- getAllCodeActions cannot get our code actions because they have no diagnostics
+  codeActions <- join <$> traverse (getCodeActions doc) ranges
+  let cmds = Maybe.mapMaybe (^? _L) codeActions
+  executeCmdsBackwards cmds
+
+-- Execute commands backwards, nubbing elements to avoid
+-- evaluating the same section with multiple tests
+-- more than twice
+executeCmdsBackwards :: [Command] -> Session ()
+executeCmdsBackwards = mapM_ executeCmd . nubOrdOn actSectionId . reverse
 
 actSectionId :: Command -> Int
 actSectionId Command{_arguments = Just [fromJSON -> Success EvalParams{..}]} = evalId
diff --git a/plugins/hls-explicit-imports-plugin/src/Ide/Plugin/ExplicitImports.hs b/plugins/hls-explicit-imports-plugin/src/Ide/Plugin/ExplicitImports.hs
--- a/plugins/hls-explicit-imports-plugin/src/Ide/Plugin/ExplicitImports.hs
+++ b/plugins/hls-explicit-imports-plugin/src/Ide/Plugin/ExplicitImports.hs
@@ -25,7 +25,6 @@
 import qualified Data.Aeson                           as A (ToJSON (toJSON))
 import           Data.Aeson.Types                     (FromJSON)
 import           Data.Char                            (isSpace)
-import           Data.Functor                         ((<&>))
 import qualified Data.IntMap                          as IM (IntMap, elems,
                                                              fromList, (!?))
 import           Data.IORef                           (readIORef)
@@ -218,16 +217,18 @@
     --                  |^-_paddingLeft
     --                  ^-_position
     generateInlayHints :: Range -> ImportEdit -> PositionMapping -> Maybe InlayHint
-    generateInlayHints (Range _ end) ie pm = mkLabel ie <&> \label ->
-      InlayHint { _position = end
-                , _label = InL label
-                , _kind = Nothing -- neither a type nor a parameter
-                , _textEdits = fmap singleton $ toTEdit pm ie
-                , _tooltip = Just $ InL "Make this import explicit" -- simple enough, no need to resolve
-                , _paddingLeft = Just True -- show an extra space before the inlay hint
-                , _paddingRight = Nothing
-                , _data_ = Nothing
-                }
+    generateInlayHints (Range _ end) ie pm = do
+      label <- mkLabel ie
+      currentEnd <- toCurrentPosition pm end
+      return InlayHint { _position = currentEnd
+                       , _label = InL label
+                       , _kind = Nothing -- neither a type nor a parameter
+                       , _textEdits = fmap singleton $ toTEdit pm ie
+                       , _tooltip = Just $ InL "Make this import explicit" -- simple enough, no need to resolve
+                       , _paddingLeft = Just True -- show an extra space before the inlay hint
+                       , _paddingRight = Nothing
+                       , _data_ = Nothing
+                       }
     mkLabel :: ImportEdit -> Maybe T.Text
     mkLabel (ImportEdit{ieResType, ieText}) =
       let title ExplicitImport = Just $ abbreviateImportTitleWithoutModule ieText
diff --git a/plugins/hls-explicit-record-fields-plugin/src/Ide/Plugin/ExplicitFields.hs b/plugins/hls-explicit-record-fields-plugin/src/Ide/Plugin/ExplicitFields.hs
--- a/plugins/hls-explicit-record-fields-plugin/src/Ide/Plugin/ExplicitFields.hs
+++ b/plugins/hls-explicit-record-fields-plugin/src/Ide/Plugin/ExplicitFields.hs
@@ -43,7 +43,9 @@
                                                        srcSpanToLocation,
                                                        srcSpanToRange, viaShow)
 import           Development.IDE.Core.PluginUtils
-import           Development.IDE.Core.PositionMapping (toCurrentRange)
+import           Development.IDE.Core.PositionMapping (PositionMapping,
+                                                       toCurrentPosition,
+                                                       toCurrentRange)
 import           Development.IDE.Core.RuleTypes       (TcModuleResult (..),
                                                        TypeCheck (..))
 import qualified Development.IDE.Core.Shake           as Shake
@@ -204,19 +206,19 @@
                     | record <- records
                     , pos <- maybeToList $ fmap _start $ recordInfoToDotDotRange record ]
     defnLocsList <- lift $ sequence locations
-    pure $ InL $ mapMaybe (mkInlayHint crr pragma) defnLocsList
+    pure $ InL $ mapMaybe (mkInlayHint crr pragma pm) defnLocsList
    where
-     mkInlayHint :: CollectRecordsResult -> NextPragmaInfo -> (Maybe [(Location, Identifier)], RecordInfo) -> Maybe InlayHint
-     mkInlayHint CRR {enabledExtensions, nameMap} pragma (defnLocs, record) =
+     mkInlayHint :: CollectRecordsResult -> NextPragmaInfo -> PositionMapping -> (Maybe [(Location, Identifier)], RecordInfo) -> Maybe InlayHint
+     mkInlayHint CRR {enabledExtensions, nameMap} pragma pm (defnLocs, record) =
        let range = recordInfoToDotDotRange record
            textEdits = maybeToList (renderRecordInfoAsTextEdit nameMap record)
                     <> maybeToList (pragmaEdit enabledExtensions pragma)
            names = renderRecordInfoAsDotdotLabelName record
        in do
-         end <- fmap _end range
+         currentEnd <- range >>= toCurrentPosition pm . _end
          names' <- names
          defnLocs' <- defnLocs
-         let excludeDotDot (Location _ (Range _ end')) = end' /= end
+         let excludeDotDot (Location _ (Range _ end)) = end /= currentEnd
              -- find location from dotdot definitions that name equal to label name
              findLocation name locations =
                let -- filter locations not within dotdot range
@@ -227,7 +229,7 @@
              valueWithLoc = [ (T.pack $ printName name, findLocation name defnLocs') | name <- names' ]
              -- use `, ` to separate labels with definition location
              label = intersperse (mkInlayHintLabelPart (", ", Nothing)) $ fmap mkInlayHintLabelPart valueWithLoc
-         pure $ InlayHint { _position = end -- at the end of dotdot
+         pure $ InlayHint { _position = currentEnd -- at the end of dotdot
                           , _label = InR label
                           , _kind = Nothing -- neither a type nor a parameter
                           , _textEdits = Just textEdits -- same as CodeAction
@@ -248,20 +250,22 @@
                   | Just range <- [toCurrentRange pm visibleRange]
                   , uid <- RangeMap.elementsInRange range crCodeActions
                   , Just record <- [IntMap.lookup uid crCodeActionResolve] ]
-    pure $ InL (concatMap (mkInlayHints nameMap) records)
+    pure $ InL (concatMap (mkInlayHints nameMap pm) records)
    where
-     mkInlayHints :: UniqFM Name [Name] -> RecordInfo -> [InlayHint]
-     mkInlayHints nameMap record@(RecordInfoApp _ (RecordAppExpr _ fla)) =
+     mkInlayHints :: UniqFM Name [Name] -> PositionMapping -> RecordInfo -> [InlayHint]
+     mkInlayHints nameMap pm record@(RecordInfoApp _ (RecordAppExpr _ fla)) =
        let textEdits = renderRecordInfoAsTextEdit nameMap record
-       in mapMaybe (mkInlayHint textEdits) fla
-     mkInlayHints _       _              = []
-     mkInlayHint :: Maybe TextEdit -> (Located FieldLabel, HsExpr GhcTc) -> Maybe InlayHint
-     mkInlayHint te (label, _) =
+       in mapMaybe (mkInlayHint textEdits pm) fla
+     mkInlayHints _ _ _ = []
+
+     mkInlayHint :: Maybe TextEdit -> PositionMapping -> (Located FieldLabel, HsExpr GhcTc) -> Maybe InlayHint
+     mkInlayHint te pm (label, _) =
        let (name, loc) = ((flSelector . unLoc) &&& (srcSpanToLocation . getLoc)) label
            fieldDefLoc = srcSpanToLocation (nameSrcSpan name)
        in do
          (Location _ recRange) <- loc
-         pure InlayHint { _position = _start recRange
+         currentStart <- toCurrentPosition pm (_start recRange)
+         pure InlayHint { _position = currentStart
                         , _label = InR $ pure (mkInlayHintLabelPart name fieldDefLoc)
                         , _kind = Nothing -- neither a type nor a parameter
                         , _textEdits = Just (maybeToList te) -- same as CodeAction
@@ -270,6 +274,7 @@
                         , _paddingRight = Nothing
                         , _data_ = Nothing
                         }
+
      mkInlayHintLabelPart name loc = InlayHintLabelPart (printOutputable (pprNameUnqualified name) <> "=") Nothing loc Nothing
 
 mkTitle :: [Extension] -> Text
diff --git a/plugins/hls-gadt-plugin/src/Ide/Plugin/GHC.hs b/plugins/hls-gadt-plugin/src/Ide/Plugin/GHC.hs
--- a/plugins/hls-gadt-plugin/src/Ide/Plugin/GHC.hs
+++ b/plugins/hls-gadt-plugin/src/Ide/Plugin/GHC.hs
@@ -7,16 +7,20 @@
 {-# OPTIONS_GHC -Wno-overlapping-patterns #-}
 module Ide.Plugin.GHC where
 
+#if !MIN_VERSION_ghc(9,11,0)
 import           Data.Functor                            ((<&>))
+#endif
 import           Data.List.Extra                         (stripInfix)
 import qualified Data.Text                               as T
 import           Development.IDE
 import           Development.IDE.GHC.Compat
 import           Development.IDE.GHC.Compat.ExactPrint
-import           GHC.Parser.Annotation                   (AddEpAnn (..),
-                                                          DeltaPos (..),
+import           GHC.Parser.Annotation                   (DeltaPos (..),
                                                           EpAnn (..),
                                                           EpAnnComments (EpaComments))
+#if MIN_VERSION_ghc(9,11,0)
+import           GHC.Parser.Annotation                   (EpToken (..))
+#endif
 import           Ide.PluginUtils                         (subRange)
 import           Language.Haskell.GHC.ExactPrint.Parsers (parseDecl)
 
@@ -44,6 +48,11 @@
 import           Language.Haskell.GHC.ExactPrint.Utils   (showAst)
 #endif
 
+#if MIN_VERSION_ghc(9,11,0)
+import           GHC.Types.SrcLoc                        (UnhelpfulSpanReason (..))
+#else
+import           GHC.Parser.Annotation                   (AddEpAnn (..))
+#endif
 
 type GP = GhcPass Parsed
 
@@ -97,7 +106,9 @@
 h98ToGADTConDecl dataName tyVars ctxt = \case
     ConDeclH98{..} ->
         ConDeclGADT
-#if MIN_VERSION_ghc(9,9,0)
+#if MIN_VERSION_ghc(9,11,0)
+            (AnnConDeclGADT [] [] NoEpUniTok)
+#elif MIN_VERSION_ghc(9,9,0)
             (NoEpUniTok, con_ext)
 #else
             con_ext
@@ -209,7 +220,11 @@
         adjustDataDecl DataDecl{..} = DataDecl
             { tcdDExt = adjustWhere tcdDExt
             , tcdDataDefn = tcdDataDefn
-                { dd_cons =
+                {
+#if MIN_VERSION_ghc(9,11,0)
+                dd_ext = adjustDefnWhere (dd_ext tcdDataDefn),
+#endif
+                dd_cons =
                       fmap adjustCon (dd_cons tcdDataDefn)
                 }
             , ..
@@ -218,8 +233,12 @@
 
         -- Make every data constructor start with a new line and 2 spaces
         adjustCon :: LConDecl GP -> LConDecl GP
-#if MIN_VERSION_ghc(9,9,0)
+#if MIN_VERSION_ghc(9,11,0)
         adjustCon (L _ r) =
+            let delta = EpaDelta (UnhelpfulSpan UnhelpfulNoLocationInfo) (DifferentLine 1 2) []
+            in L (EpAnn delta (AnnListItem []) (EpaComments [])) r
+#elif MIN_VERSION_ghc(9,9,0)
+        adjustCon (L _ r) =
             let delta = EpaDelta (DifferentLine 1 3) []
             in L (EpAnn delta (AnnListItem []) (EpaComments [])) r
 #else
@@ -229,6 +248,10 @@
 #endif
 
         -- Adjust where annotation to the same line of the type constructor
+#if MIN_VERSION_ghc(9,11,0)
+        -- tcdDext is just a placeholder in ghc-9.12
+        adjustWhere = id
+#else
         adjustWhere tcdDExt = tcdDExt <&>
 #if !MIN_VERSION_ghc(9,9,0)
             map
@@ -238,7 +261,16 @@
                 then AddEpAnn AnnWhere d1
                 else AddEpAnn ann l
             )
+#endif
 
+#if MIN_VERSION_ghc(9,11,0)
+        adjustDefnWhere annDataDefn
+          | andd_where annDataDefn == NoEpTok = annDataDefn
+          | otherwise = annDataDefn {andd_where = andd_where'}
+          where
+            (EpTok (EpaSpan aw)) = andd_where annDataDefn
+            andd_where' = EpTok (EpaDelta aw (SameLine 1) [])
+#endif
         -- Remove the first extra line if exist
         removeExtraEmptyLine s = case stripInfix "\n\n" s of
             Just (x, xs) -> x <> "\n" <> xs
@@ -257,6 +289,10 @@
 #endif
 
 pattern UserTyVar' :: LIdP pass -> HsTyVarBndr flag pass
+#if MIN_VERSION_ghc(9,11,0)
+pattern UserTyVar' s <- HsTvb _ _ (HsBndrVar _ s) _
+#else
 pattern UserTyVar' s <- UserTyVar _ _ s
+#endif
 
 implicitTyVars = wrapXRec @GP mkHsOuterImplicit
diff --git a/plugins/hls-hlint-plugin/test/Main.hs b/plugins/hls-hlint-plugin/test/Main.hs
--- a/plugins/hls-hlint-plugin/test/Main.hs
+++ b/plugins/hls-hlint-plugin/test/Main.hs
@@ -276,14 +276,24 @@
                              , "g = 2"
                              , "#endif", ""
                              ]
-        expectedComments =  [ "-- comment before header"
-                             , "module Comments where", ""
-                             , "{-# standalone annotation #-}", ""
-                             , "-- standalone comment", ""
-                             , "-- | haddock comment"
-                             , "f = {- inline comment -} {- inline comment inside refactored code -}1 -- ending comment", ""
-                             , "-- final comment"
-                             ]
+        expectedComments = case ghcVersion of
+                             GHC912 -> [ "-- comment before header"
+                              , "module Comments where", ""
+                              , "{-# standalone annotation #-}", ""
+                              , "-- standalone comment", ""
+                              , "-- | haddock comment"
+                              , "f = {- inline comment -}{- inline comment inside refactored code -} 1 -- ending comment", ""
+                              , "-- final comment"
+                              ]
+
+                             _ -> [ "-- comment before header"
+                              , "module Comments where", ""
+                              , "{-# standalone annotation #-}", ""
+                              , "-- standalone comment", ""
+                              , "-- | haddock comment"
+                              , "f = {- inline comment -} {- inline comment inside refactored code -}1 -- ending comment", ""
+                              , "-- final comment"
+                              ]
         expectedComments2 =  [ "module TwoHintsAndComment where"
                              , "biggest = foldr1 max -- the line above will show two hlint hints, \"eta reduce\" and \"use maximum\""
                              ]
diff --git a/plugins/hls-refactor-plugin/src/Development/IDE/GHC/ExactPrint.hs b/plugins/hls-refactor-plugin/src/Development/IDE/GHC/ExactPrint.hs
--- a/plugins/hls-refactor-plugin/src/Development/IDE/GHC/ExactPrint.hs
+++ b/plugins/hls-refactor-plugin/src/Development/IDE/GHC/ExactPrint.hs
@@ -106,6 +106,9 @@
                                                           deltaPos)
 import           GHC.Types.SrcLoc                        (generatedSrcSpan)
 #endif
+#if MIN_VERSION_ghc(9,11,0)
+import           GHC.Types.SrcLoc (UnhelpfulSpanReason(..))
+#endif
 
 #if MIN_VERSION_ghc(9,9,0)
 import           GHC                                     (
@@ -116,6 +119,9 @@
                                                           EpAnn (..),
                                                           EpaLocation,
                                                           EpaLocation' (..),
+#if MIN_VERSION_ghc(9,11,0)
+                                                          EpToken (..),
+#endif
                                                           NameAdornment (..),
                                                           NameAnn (..),
                                                           SrcSpanAnnA,
@@ -124,7 +130,6 @@
                                                           emptyComments,
                                                           spanAsAnchor)
 #endif
-
 setPrecedingLines ::
 #if !MIN_VERSION_ghc(9,9,0)
      Default t =>
@@ -168,6 +173,10 @@
     (makeDeltaAst ps)
 #endif
 
+#if MIN_VERSION_ghc(9,11,0)
+type Anchor = EpaLocation
+#endif
+
 ------------------------------------------------------------------------------
 
 {- | A transformation for grafting source trees together. Use the semigroup
@@ -466,8 +475,11 @@
             False -> first (DL.singleton ldecl <>) <$> modifyMatchingDecl rest
   modifyDeclsT' (fmap (first DL.toList) . modifyMatchingDecl) a
 
-#if MIN_VERSION_ghc(9,9,0)
+#if MIN_VERSION_ghc(9,11,0)
 generatedAnchor :: DeltaPos -> Anchor
+generatedAnchor dp = EpaDelta (UnhelpfulSpan UnhelpfulNoLocationInfo) dp []
+#elif MIN_VERSION_ghc(9,9,0)
+generatedAnchor :: DeltaPos -> Anchor
 generatedAnchor dp = EpaDelta dp []
 #else
 generatedAnchor :: AnchorOperation -> Anchor
@@ -766,15 +778,28 @@
 addParensToCtxt :: Maybe EpaLocation -> AnnContext -> AnnContext
 addParensToCtxt close_dp = addOpen . addClose
   where
+#if MIN_VERSION_ghc(9,11,0)
+      addOpen it@AnnContext{ac_open = []} = it{ac_open = [EpTok (epl 0)]}
+#else
       addOpen it@AnnContext{ac_open = []} = it{ac_open = [epl 0]}
+#endif
       addOpen other                       = other
       addClose it
+#if MIN_VERSION_ghc(9,11,0)
+        | Just c <- close_dp = it{ac_close = [EpTok c]}
+        | AnnContext{ac_close = []} <- it = it{ac_close = [EpTok (epl 0)]}
+#else
         | Just c <- close_dp = it{ac_close = [c]}
         | AnnContext{ac_close = []} <- it = it{ac_close = [epl 0]}
+#endif
         | otherwise = it
 
 epl :: Int -> EpaLocation
+#if MIN_VERSION_ghc(9,11,0)
+epl n = EpaDelta (UnhelpfulSpan UnhelpfulNoLocationInfo) (SameLine n) []
+#else
 epl n = EpaDelta (SameLine n) []
+#endif
 
 epAnn :: SrcSpan -> ann -> EpAnn ann
 epAnn srcSpan anns = EpAnn (spanAsAnchor srcSpan) anns emptyComments
@@ -803,14 +828,25 @@
 #endif
 
 addParens :: Bool -> GHC.NameAnn -> GHC.NameAnn
+#if MIN_VERSION_ghc(9,11,0)
 addParens True it@NameAnn{} =
-        it{nann_adornment = NameParens, nann_open = epl 0, nann_close = epl 0 }
+        it{nann_adornment = NameParens (EpTok (epl 0)) (EpTok (epl 0)) }
 addParens True it@NameAnnCommas{} =
-        it{nann_adornment = NameParens, nann_open = epl 0, nann_close = epl 0 }
+        it{nann_adornment = NameParens (EpTok (epl 0)) (EpTok (epl 0)) }
 addParens True it@NameAnnOnly{} =
-        it{nann_adornment = NameParens, nann_open = epl 0, nann_close = epl 0 }
+        it{nann_adornment = NameParens (EpTok (epl 0)) (EpTok (epl 0)) }
+addParens True it@NameAnnTrailing{} =
+  NameAnn{nann_adornment = NameParens (EpTok (epl 0)) (EpTok (epl 0)), nann_name = epl 0, nann_trailing = nann_trailing it}
+#else
+addParens True it@NameAnn{} =
+        it{nann_adornment = NameParens, nann_open=epl 0, nann_close=epl 0 }
+addParens True it@NameAnnCommas{} =
+        it{nann_adornment = NameParens, nann_open=epl 0, nann_close=epl 0 }
+addParens True it@NameAnnOnly{} =
+        it{nann_adornment = NameParens, nann_open=epl 0, nann_close=epl 0 }
 addParens True NameAnnTrailing{..} =
-        NameAnn{nann_adornment = NameParens, nann_open = epl 0, nann_close = epl 0, nann_name = epl 0, ..}
+        NameAnn{nann_adornment = NameParens, nann_open=epl 0, nann_close=epl 0, nann_name = epl 0, ..}
+#endif
 addParens _ it = it
 
 removeTrailingComma :: GenLocated SrcSpanAnnA ast -> GenLocated SrcSpanAnnA ast
diff --git a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs
--- a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs
+++ b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction.hs
@@ -12,7 +12,9 @@
     fillHolePluginDescriptor,
     extendImportPluginDescriptor,
     -- * For testing
-    matchRegExMultipleImports
+    matchRegExMultipleImports,
+    extractNotInScopeName,
+    NotInScope(..)
     ) where
 
 import           Control.Applicative                               ((<|>))
@@ -48,7 +50,9 @@
 import           Development.IDE.Core.Shake                        hiding (Log)
 import           Development.IDE.GHC.Compat                        hiding
                                                                    (ImplicitPrelude)
+#if !MIN_VERSION_ghc(9,11,0)
 import           Development.IDE.GHC.Compat.Util
+#endif
 import           Development.IDE.GHC.Error
 import           Development.IDE.GHC.ExactPrint
 import qualified Development.IDE.GHC.ExactPrint                    as E
@@ -69,8 +73,7 @@
 import           Development.IDE.Types.Exports
 import           Development.IDE.Types.Location
 import           Development.IDE.Types.Options
-import           GHC                                               (AddEpAnn (AddEpAnn),
-                                                                    AnnsModule (am_main),
+import           GHC                                               (
                                                                     DeltaPos (..),
                                                                     EpAnn (..),
                                                                     LEpaComment)
@@ -105,18 +108,31 @@
 
 #if !MIN_VERSION_ghc(9,9,0)
 import           Development.IDE.GHC.Compat.ExactPrint             (makeDeltaAst)
-import           GHC                                               (Anchor (anchor_op),
+import           GHC                                               (AddEpAnn (AddEpAnn),
+                                                                    AnnsModule (am_main),
+                                                                    Anchor (anchor_op),
                                                                     AnchorOperation (..),
                                                                     EpaLocation (..))
 #endif
 
-#if MIN_VERSION_ghc(9,9,0)
-import           GHC                                               (EpaLocation,
+#if MIN_VERSION_ghc(9,9,0) && !MIN_VERSION_ghc(9,11,0)
+import           GHC                                               (AddEpAnn (AddEpAnn),
+                                                                    AnnsModule (am_main),
+                                                                    EpaLocation,
                                                                     EpaLocation' (..),
                                                                     HasLoc (..))
 import           GHC.Types.SrcLoc                                  (srcSpanToRealSrcSpan)
 #endif
+#if MIN_VERSION_ghc(9,11,0)
+import           GHC                                               (EpaLocation,
+                                                                    AnnsModule (am_where),
+                                                                    EpaLocation' (..),
+                                                                    HasLoc (..),
+                                                                    EpToken (..))
+import           GHC.Types.SrcLoc                                  (srcSpanToRealSrcSpan)
+#endif
 
+
 -------------------------------------------------------------------------------------------------
 
 -- | Generate code actions.
@@ -339,7 +355,11 @@
         case unLoc <$> findDeclContainingLoc (_start range) lsigs of
           Just sig' -> Just sig'
           Nothing -> do
+#if MIN_VERSION_ghc(9,11,0)
+            lHsBindLR <- findDeclContainingLoc (_start range) binds
+#else
             lHsBindLR <- findDeclContainingLoc (_start range) (bagToList binds)
+#endif
             findSigOfBind range (unLoc lHsBindLR)
     go _ = Nothing
 
@@ -420,7 +440,11 @@
   modName
   importSpan
     | occ <- mkVarOcc identifier,
+#if MIN_VERSION_ghc(9,11,0)
+      impModsVals <- importedByUser . concat $ M.elems imp_mods,
+#else
       impModsVals <- importedByUser . concat $ moduleEnvElts imp_mods,
+#endif
       Just rdrEnv <-
         listToMaybe
           [ imv_all_exports
@@ -659,7 +683,11 @@
         name
         (L _ Match{m_grhss=GRHSs{grhssLocalBinds}}) = do
         let go bag lsigs =
+#if MIN_VERSION_ghc(9,11,0)
+                if null bag
+#else
                 if isEmptyBag bag
+#endif
                 then []
                 else concatMap (findRelatedSpanForHsBind indexedContent name lsigs) bag
         case grhssLocalBinds of
@@ -1572,13 +1600,34 @@
         modNameP = fmap snd $ RE.withMatched $ conIDP `sepBy1` RE.sym '.'
 
 
+-- | A Backward compatible implementation of `lookupOccEnv_AllNameSpaces` for
+-- GHC <=9.6
+--
+-- It looks for a symbol name in all known namespaces, including types,
+-- variables, and fieldnames.
+--
+-- Note that on GHC >= 9.8, the record selectors are not in the `mkVarOrDataOcc`
+-- anymore, but are in a custom namespace, see
+-- https://gitlab.haskell.org/ghc/ghc/-/wikis/migration/9.8#new-namespace-for-record-fields,
+-- hence we need to use this "AllNamespaces" implementation, otherwise we'll
+-- miss them.
+lookupOccEnvAllNamespaces :: ExportsMap -> T.Text -> [IdentInfo]
+#if MIN_VERSION_ghc(9,7,0)
+lookupOccEnvAllNamespaces exportsMap name = Set.toList $ mconcat (lookupOccEnv_AllNameSpaces (getExportsMap exportsMap) (mkTypeOcc name))
+#else
+lookupOccEnvAllNamespaces exportsMap name = maybe [] Set.toList $
+                            lookupOccEnv (getExportsMap exportsMap) (mkVarOrDataOcc name)
+                          <> lookupOccEnv (getExportsMap exportsMap) (mkTypeOcc name) -- look up the modified unknown name in the export map
+#endif
+
+
 constructNewImportSuggestions
   :: ExportsMap -> (Maybe T.Text, NotInScope) -> Maybe [T.Text] -> QualifiedImportStyle -> [ImportSuggestion]
 constructNewImportSuggestions exportsMap (qual, thingMissing) notTheseModules qis = nubOrdBy simpleCompareImportSuggestion
   [ suggestion
   | Just name <- [T.stripPrefix (maybe "" (<> ".") qual) $ notInScope thingMissing] -- strip away qualified module names from the unknown name
-  , identInfo <- maybe [] Set.toList $ lookupOccEnv (getExportsMap exportsMap) (mkVarOrDataOcc name)
-                                    <> lookupOccEnv (getExportsMap exportsMap) (mkTypeOcc name) -- look up the modified unknown name in the export map
+
+  , identInfo <- lookupOccEnvAllNamespaces exportsMap name -- look up the modified unknown name in the export map
   , canUseIdent thingMissing identInfo                                              -- check if the identifier information retrieved can be used
   , moduleNameText identInfo `notElem` fromMaybe [] notTheseModules                 -- check if the module of the identifier is allowed
   , suggestion <- renderNewImport identInfo                                         -- creates a list of import suggestions for the retrieved identifier information
@@ -1700,13 +1749,22 @@
 #endif
         EpAnn _ annsModule _ -> do
             -- Find the first 'where'
+#if MIN_VERSION_ghc(9,11,0)
+            whereLocation <- filterWhere $ am_where annsModule
+#else
             whereLocation <- listToMaybe . mapMaybe filterWhere $ am_main annsModule
+#endif
             epaLocationToLine whereLocation
 #if !MIN_VERSION_ghc(9,9,0)
         EpAnnNotUsed -> Nothing
 #endif
+#if MIN_VERSION_ghc(9,11,0)
+    filterWhere (EpTok loc) = Just loc
+    filterWhere _ = Nothing
+#else
     filterWhere (AddEpAnn AnnWhere loc) = Just loc
     filterWhere _                       = Nothing
+#endif
 
     epaLocationToLine :: EpaLocation -> Maybe Int
 #if MIN_VERSION_ghc(9,9,0)
@@ -1719,12 +1777,19 @@
     epaLocationToLine (EpaSpan sp)
       = Just . srcLocLine . realSrcSpanEnd $ sp
 #endif
+#if MIN_VERSION_ghc(9,11,0)
+    epaLocationToLine (EpaDelta _ (SameLine _) priorComments) = Just $ sumCommentsOffset priorComments
+    -- 'priorComments' contains the comments right before the current EpaLocation
+    -- Summing line offset of priorComments is necessary, as 'line' is the gap between the last comment and
+    -- the current AST node
+    epaLocationToLine (EpaDelta _ (DifferentLine line _) priorComments) = Just (line + sumCommentsOffset priorComments)
+#else
     epaLocationToLine (EpaDelta (SameLine _) priorComments) = Just $ sumCommentsOffset priorComments
     -- 'priorComments' contains the comments right before the current EpaLocation
     -- Summing line offset of priorComments is necessary, as 'line' is the gap between the last comment and
     -- the current AST node
     epaLocationToLine (EpaDelta (DifferentLine line _) priorComments) = Just (line + sumCommentsOffset priorComments)
-
+#endif
     sumCommentsOffset :: [LEpaComment] -> Int
 #if MIN_VERSION_ghc(9,9,0)
     sumCommentsOffset = sum . fmap (\(L anchor _) -> anchorOpLine anchor)
@@ -1732,9 +1797,14 @@
     sumCommentsOffset = sum . fmap (\(L anchor _) -> anchorOpLine (anchor_op anchor))
 #endif
 
-#if MIN_VERSION_ghc(9,9,0)
+#if MIN_VERSION_ghc(9,11,0)
     anchorOpLine :: EpaLocation' a -> Int
     anchorOpLine EpaSpan{}                           = 0
+    anchorOpLine (EpaDelta _ (SameLine _) _)           = 0
+    anchorOpLine (EpaDelta _ (DifferentLine line _) _) = line
+#elif MIN_VERSION_ghc(9,9,0)
+    anchorOpLine :: EpaLocation' a -> Int
+    anchorOpLine EpaSpan{}                           = 0
     anchorOpLine (EpaDelta (SameLine _) _)           = 0
     anchorOpLine (EpaDelta (DifferentLine line _) _) = line
 #else
@@ -1825,7 +1895,7 @@
     = NotInScopeDataConstructor T.Text
     | NotInScopeTypeConstructorOrClass T.Text
     | NotInScopeThing T.Text
-    deriving Show
+    deriving (Show, Eq)
 
 notInScope :: NotInScope -> T.Text
 notInScope (NotInScopeDataConstructor t)        = t
@@ -1840,6 +1910,38 @@
   = Just $ NotInScopeDataConstructor name
   | Just [name] <- matchRegexUnifySpaces x "ot in scope: type constructor or class [^‘]*‘([^’]*)’"
   = Just $ NotInScopeTypeConstructorOrClass name
+  | Just [name] <- matchRegexUnifySpaces x "The data constructors of ‘([^ ]+)’ are not all in scope"
+  = Just $ NotInScopeDataConstructor name
+  | Just [name] <- matchRegexUnifySpaces x "of newtype ‘([^’]*)’ is not in scope"
+  = Just $ NotInScopeThing name
+  -- Match for HasField "foo" Bar String in the context where, e.g. x.foo is
+  -- used, and x :: Bar.
+  --
+  -- This usually mean that the field is not in scope and the correct fix is to
+  -- import (Bar(foo)) or (Bar(..)).
+  --
+  -- However, it is more reliable to match for the type name instead of the field
+  -- name, and most of the time you'll want to import the complete type with all
+  -- their fields instead of the specific field.
+  --
+  -- The regex is convoluted because it accounts for:
+  --
+  -- - Qualified (or not) `HasField`
+  -- - The type bar is always qualified. If it is unqualified, it means that the
+  -- parent module is already imported, and in this context it uses an hint
+  -- already available in the GHC error message. However this regex accounts for
+  -- qualified or not, it does not cost much and should be more robust if the
+  -- hint changes in the future
+  -- - Next regex will account for polymorphic types, which appears as `HasField
+  -- "foo" (Bar Int)...`, e.g. see the parenthesis
+  | Just [_module, name] <- matchRegexUnifySpaces x "No instance for [‘(].*HasField \"[^\"]+\" ([^ (.]+\\.)*([^ (.]+).*[’)]"
+  = Just $ NotInScopeThing name
+  | Just [_module, name] <- matchRegexUnifySpaces x "No instance for [‘(].*HasField \"[^\"]+\" \\(([^ .]+\\.)*([^ .]+)[^)]*\\).*[’)]"
+  = Just $ NotInScopeThing name
+  -- The order of the "Not in scope" is important, for example, some of the
+  -- matcher may catch the "record" value instead of the value later.
+  | Just [name] <- matchRegexUnifySpaces x "Not in scope: record field ‘([^’]*)’"
+  = Just $ NotInScopeThing name
   | Just [name] <- matchRegexUnifySpaces x "ot in scope: \\(([^‘ ]+)\\)"
   = Just $ NotInScopeThing name
   | Just [name] <- matchRegexUnifySpaces x "ot in scope: ([^‘ ]+)"
@@ -1881,14 +1983,11 @@
 --         ‘Data.Functor’ nor ‘Data.Text’ exports ‘putStrLn’.
 extractDoesNotExportModuleName :: T.Text -> Maybe T.Text
 extractDoesNotExportModuleName x
-  | Just [m] <-
-#if MIN_VERSION_ghc(9,4,0)
-    matchRegexUnifySpaces x "the module ‘([^’]*)’ does not export"
-      <|> matchRegexUnifySpaces x "nor ‘([^’]*)’ export"
-#else
-    matchRegexUnifySpaces x "Module ‘([^’]*)’ does not export"
-      <|> matchRegexUnifySpaces x "nor ‘([^’]*)’ exports"
-#endif
+  | Just [m] <- case ghcVersion of
+                  GHC912 -> matchRegexUnifySpaces x "The module ‘([^’]*)’ does not export"
+                            <|> matchRegexUnifySpaces x "nor ‘([^’]*)’ export"
+                  _ ->      matchRegexUnifySpaces x "the module ‘([^’]*)’ does not export"
+                            <|> matchRegexUnifySpaces x "nor ‘([^’]*)’ export"
   = Just m
   | otherwise
   = Nothing
diff --git a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs
--- a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs
+++ b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/CodeAction/ExactPrint.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE GADTs        #-}
 {-# LANGUAGE TypeFamilies #-}
 module Development.IDE.Plugin.CodeAction.ExactPrint (
@@ -35,10 +36,8 @@
 import           Data.Bifunctor                         (first)
 import           Data.Maybe                             (fromMaybe, mapMaybe)
 import           Development.IDE.Plugin.CodeAction.Util
-import           GHC                                    (AddEpAnn (..),
-                                                         AnnContext (..),
+import           GHC                                    (AnnContext (..),
                                                          AnnList (..),
-                                                         AnnParen (..),
                                                          DeltaPos (SameLine),
                                                          EpAnn (..),
                                                          IsUnicodeSyntax (NormalSyntax),
@@ -46,8 +45,17 @@
                                                          TrailingAnn (AddCommaAnn),
                                                          emptyComments, reAnnL)
 
+
 -- See Note [Guidelines For Using CPP In GHCIDE Import Statements]
 
+#if MIN_VERSION_ghc(9,11,0)
+import GHC (EpToken (..)
+           , AnnListBrackets (..)
+           , EpUniToken (..))
+#else
+import GHC (AddEpAnn (..),
+                                                         AnnParen (..))
+#endif
 #if !MIN_VERSION_ghc(9,9,0)
 import           Data.Default                           (Default (..))
 import           GHC                                    (addAnns, ann)
@@ -179,7 +187,9 @@
     -- For singleton constraints, the close Paren DP is attached to an HsPar wrapping the constraint
     -- we have to reposition it manually into the AnnContext
         close_dp = case ctxt of
-#if MIN_VERSION_ghc(9,9,0)
+#if MIN_VERSION_ghc(9,11,0)
+            [L _ (HsParTy (_, (EpTok ap_close)) _)] -> Just ap_close
+#elif MIN_VERSION_ghc(9,9,0)
             [L _ (HsParTy AnnParen{ap_close} _)] -> Just ap_close
 #else
             [L _ (HsParTy EpAnn{anns=AnnParen{ap_close}} _)] -> Just ap_close
@@ -203,7 +213,11 @@
 #else
     let context = Just $ reAnnL annCtxt emptyComments $ L lContext [resetEntryDP constraint]
 #endif
+#if MIN_VERSION_ghc(9,11,0)
+        annCtxt = AnnContext (Just (EpUniTok (epl 1) NormalSyntax)) [EpTok (epl 0) | needsParens] [EpTok (epl 0) | needsParens]
+#else
         annCtxt = AnnContext (Just (NormalSyntax, epl 1)) [epl 0 | needsParens] [epl 0 | needsParens]
+#endif
         needsParens = hsTypeNeedsParens sigPrec $ unLoc constraint
     ast <- pure $ setEntryDP (makeDeltaAst ast) (SameLine 1)
 
@@ -346,7 +360,9 @@
 #endif
                                              childRdr
           x :: LIE GhcPs = L ll' $ IEThingWith
-#if MIN_VERSION_ghc(9,9,0)
+#if MIN_VERSION_ghc(9,11,0)
+                                     (Nothing, (EpTok d1, NoEpTok, NoEpTok, EpTok noAnn))
+#elif MIN_VERSION_ghc(9,9,0)
                                      (Nothing, [AddEpAnn AnnOpenP d1, AddEpAnn AnnCloseP noAnn])
 #elif MIN_VERSION_ghc(9,7,0)
                                      (Nothing, addAnns mempty [AddEpAnn AnnOpenP d1, AddEpAnn AnnCloseP def] emptyComments)
@@ -384,6 +400,8 @@
 #endif
 #if MIN_VERSION_ghc(9,7,0) && !MIN_VERSION_ghc(9,9,0)
             newl = fmap (\ann -> ann ++ [AddEpAnn AnnDotdot d0]) <$> l'''
+#elif MIN_VERSION_ghc(9,11,0)
+            newl = (\(open, _, comma, close)  -> (open, EpTok d0, comma, close)) <$> l'''
 #else
             newl = (\ann -> ann ++ [AddEpAnn AnnDotdot d0]) <$> l'''
 #endif
@@ -427,21 +445,31 @@
       parentRdr <- liftParseAST df parent
       let childRdr = reLocA $ L srcChild $ mkRdrUnqual $ mkVarOcc child
           isParentOperator = hasParen parent
+#if MIN_VERSION_ghc(9,11,0)
+      let parentLIE = reLocA $ L srcParent $ if isParentOperator then IEType (EpTok (epl 0)) parentRdr'
+#else
       let parentLIE = reLocA $ L srcParent $ if isParentOperator then IEType (epl 0) parentRdr'
+#endif
                                                else IEName
 #if MIN_VERSION_ghc(9,5,0)
                                                       noExtField
 #endif
                                                       parentRdr'
           parentRdr' = modifyAnns parentRdr $ \case
+#if MIN_VERSION_ghc(9,11,0)
+              it@NameAnn{nann_adornment = NameParens _ _} -> it{nann_adornment=NameParens (EpTok (epl 1)) (EpTok (epl 0))}
+#else
               it@NameAnn{nann_adornment = NameParens} -> it{nann_open = epl 1, nann_close = epl 0}
+#endif
               other -> other
           childLIE = reLocA $ L srcChild $ IEName
 #if MIN_VERSION_ghc(9,5,0)
                                              noExtField
 #endif
                                              childRdr
-#if MIN_VERSION_ghc(9,9,0)
+#if MIN_VERSION_ghc(9,11,0)
+          listAnn = (Nothing, (EpTok (epl 1), NoEpTok, NoEpTok, EpTok (epl 0)))
+#elif MIN_VERSION_ghc(9,9,0)
           listAnn = (Nothing, [AddEpAnn AnnOpenP (epl 1), AddEpAnn AnnCloseP (epl 0)])
 #elif MIN_VERSION_ghc(9,7,0)
           listAnn = (Nothing, epAnn srcParent [AddEpAnn AnnOpenP (epl 1), AddEpAnn AnnCloseP (epl 0)])
@@ -538,7 +566,10 @@
 extendHiding symbol (L l idecls) mlies df = do
   L l' lies <- case mlies of
     Nothing -> do
-#if MIN_VERSION_ghc(9,9,0)
+#if MIN_VERSION_ghc(9,11,0)
+        let ann :: EpAnn (AnnList (EpToken "hiding", [EpToken ","]))
+            ann = noAnnSrcSpanDP0 
+#elif MIN_VERSION_ghc(9,9,0)
         let ann = noAnnSrcSpanDP0
 #else
         src <- uniqueSrcSpanT
@@ -549,9 +580,14 @@
 #else
             ann' = flip (fmap.fmap) ann $ \x -> x
 #endif
+#if MIN_VERSION_ghc(9,11,0)
+                {al_rest = (EpTok (epl 1), [NoEpTok])
+                ,al_brackets=ListParens (EpTok (epl 1)) (EpTok (epl 0))
+#else
                 {al_rest = [AddEpAnn AnnHiding (epl 1)]
                 ,al_open = Just $ AddEpAnn AnnOpenP (epl 1)
                 ,al_close = Just $ AddEpAnn AnnCloseP (epl 0)
+#endif
                 }
         return $ L ann' []
     Just pr -> pure pr
diff --git a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/AddArgument.hs b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/AddArgument.hs
--- a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/AddArgument.hs
+++ b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/AddArgument.hs
@@ -50,7 +50,9 @@
                                                             IsUnicodeSyntax (NormalSyntax))
 import           Language.Haskell.GHC.ExactPrint           (d1, setEntryDP)
 #endif
-
+#if MIN_VERSION_ghc(9,11,0)
+import GHC.Parser.Annotation (EpToken(..))
+#endif
 
 -- When GHC tells us that a variable is not bound, it will tell us either:
 --  - there is an unbound variable with a given type
@@ -77,19 +79,28 @@
 --      addArgToMatch "foo" `bar arg1 arg2 = ...`
 --   => (`bar arg1 arg2 foo = ...`, 2)
 addArgToMatch :: T.Text -> GenLocated l (Match GhcPs (LocatedA (HsExpr GhcPs))) -> (GenLocated l (Match GhcPs (LocatedA (HsExpr GhcPs))), Int)
+#if MIN_VERSION_ghc(9,11,0)
+addArgToMatch name (L locMatch (Match xMatch ctxMatch (L l pats) rhs)) =
+#else
 addArgToMatch name (L locMatch (Match xMatch ctxMatch pats rhs)) =
-  let unqualName = mkRdrUnqual $ mkVarOcc $ T.unpack name
+#endif
 #if MIN_VERSION_ghc(9,9,0)
+  let unqualName = mkRdrUnqual $ mkVarOcc $ T.unpack name
       newPat = L noAnnSrcSpanDP1 $ VarPat NoExtField $ L noAnn unqualName
       -- The intention is to move `= ...` (right-hand side with equals) to the right so there's 1 space between
       -- the newly added pattern and the rest
       indentRhs :: GRHSs GhcPs (LocatedA (HsExpr GhcPs)) -> GRHSs GhcPs (LocatedA (HsExpr GhcPs))
       indentRhs rhs@GRHSs{grhssGRHSs} = rhs {grhssGRHSs = fmap (`setEntryDP` (SameLine 1)) grhssGRHSs }
 #else
+  let unqualName = mkRdrUnqual $ mkVarOcc $ T.unpack name
       newPat = L (noAnnSrcSpanDP1 generatedSrcSpan) $ VarPat NoExtField (noLocA unqualName)
       indentRhs = id
 #endif
+#if MIN_VERSION_ghc(9,11,0)
+  in (L locMatch (Match xMatch ctxMatch (L l (pats <> [newPat])) (indentRhs rhs)), Prelude.length pats)
+#else
   in (L locMatch (Match xMatch ctxMatch (pats <> [newPat]) (indentRhs rhs)), Prelude.length pats)
+#endif
 
 -- Attempt to insert a binding pattern into each match for the given LHsDecl; succeeds only if the function is a FunBind.
 -- Also return:
@@ -171,7 +182,11 @@
           ( noAnn
           , noExtField
           , HsUnrestrictedArrow (EpUniTok d1 NormalSyntax)
+#if MIN_VERSION_ghc(9,11,0)
+          , L wildCardAnn $ HsWildCardTy NoEpTok
+#else
           , L wildCardAnn $ HsWildCardTy noExtField
+#endif 
           )
 #elif MIN_VERSION_ghc(9,4,0)
         wildCardAnn = SrcSpanAnn (EpAnn genAnchor1 (AnnListItem []) emptyComments) generatedSrcSpan
diff --git a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/Diagnostic.hs b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/Diagnostic.hs
--- a/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/Diagnostic.hs
+++ b/plugins/hls-refactor-plugin/src/Development/IDE/Plugin/Plugins/Diagnostic.hs
@@ -21,6 +21,9 @@
     Nothing                                                -> Nothing
 
 -- | 'matchRegex' combined with 'unifySpaces'
+--
+-- >>> matchRegexUnifySpaces  "hello I'm a cow" "he(ll)o"
+-- Just ["ll"]
 matchRegexUnifySpaces :: T.Text -> T.Text -> Maybe [T.Text]
 matchRegexUnifySpaces message = matchRegex (unifySpaces message)
 
diff --git a/plugins/hls-refactor-plugin/test/Main.hs b/plugins/hls-refactor-plugin/test/Main.hs
--- a/plugins/hls-refactor-plugin/test/Main.hs
+++ b/plugins/hls-refactor-plugin/test/Main.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP                   #-}
 {-# LANGUAGE AllowAmbiguousTypes   #-}
 {-# LANGUAGE DataKinds             #-}
 {-# LANGUAGE DuplicateRecordFields #-}
@@ -46,6 +47,7 @@
 import           Test.Hls
 
 import qualified Development.IDE.GHC.ExactPrint
+import           Development.IDE.Plugin.CodeAction        (NotInScope (..))
 import qualified Development.IDE.Plugin.CodeAction        as Refactor
 import qualified Test.AddArgument
 
@@ -68,6 +70,7 @@
   , codeActionTests
   , codeActionHelperFunctionTests
   , completionTests
+  , extractNotInScopeNameTests
   ]
 
 initializeTests :: TestTree
@@ -300,6 +303,8 @@
   , suggestImportClassMethodTests
   , suggestImportTests
   , suggestAddRecordFieldImportTests
+  , suggestAddCoerceMissingConstructorImportTests
+  , suggestAddGenericMissingConstructorImportTests
   , suggestHideShadowTests
   , fixConstructorImportTests
   , fixModuleImportTypoTests
@@ -316,6 +321,7 @@
   , addImplicitParamsConstraintTests
   , removeExportTests
   , Test.AddArgument.tests
+  , suggestAddRecordFieldUpdateImportTests
   ]
 
 insertImportTests :: TestTree
@@ -1849,8 +1855,14 @@
 suggestAddRecordFieldImportTests :: TestTree
 suggestAddRecordFieldImportTests = testGroup "suggest imports of record fields when using OverloadedRecordDot"
   [ testGroup "The field is suggested when an instance resolution failure occurs"
-    [ ignoreForGhcVersions [GHC94, GHC96] "Extension not present <9.2, and the assist is derived from the help message in >=9.4" theTest
+    ([ ignoreForGhcVersions [GHC94, GHC96] "Extension not present <9.2, and the assist is derived from the help message in >=9.4" theTest
     ]
+    ++ [
+        theTestIndirect qualifiedGhcRecords polymorphicType
+        |
+        qualifiedGhcRecords <- [False, True]
+        , polymorphicType <- [False, True]
+        ])
   ]
   where
     theTest = testSessionWithExtraFiles "hover" def $ \dir -> do
@@ -1871,7 +1883,145 @@
       contentAfterAction <- documentContents doc
       liftIO $ after @=? contentAfterAction
 
+    theTestIndirect qualifiedGhcRecords polymorphicType = testGroup
+      ((if qualifiedGhcRecords then "qualified-" else "unqualified-")
+      <> ("HasField " :: String)
+      <>
+      (if polymorphicType then "polymorphic-" else "monomorphic-")
+      <> "type ")
+      . (\x -> [x]) $ testSessionWithExtraFiles "hover" def $ \dir -> do
+      -- Hopefully enable project indexing?
+      configureCheckProject True
 
+      let
+          before = T.unlines ["{-# LANGUAGE OverloadedRecordDot #-}", "module A where", if qualifiedGhcRecords then "" else "import GHC.Records", "import C (bar)", "spam = bar.foo"]
+          after = T.unlines ["{-# LANGUAGE OverloadedRecordDot #-}", "module A where", if qualifiedGhcRecords then "" else "import GHC.Records", "import C (bar)", "import B (Foo(..))", "spam = bar.foo"]
+          cradle = "cradle: {direct: {arguments: [-hide-all-packages, -package, base, -package, text, -package-env, -, A, B, C]}}"
+      liftIO $ writeFileUTF8 (dir </> "hie.yaml") cradle
+      liftIO $ writeFileUTF8 (dir </> "B.hs") $ unlines ["module B where", if polymorphicType then "data Foo x = Foo { foo :: x }" else "data Foo = Foo { foo :: Int }"]
+      liftIO $ writeFileUTF8 (dir </> "C.hs") $ unlines ["module C where", "import B", "bar = Foo 10" ]
+      doc <- createDoc "Test.hs" "haskell" before
+      waitForProgressDone
+      _ <- waitForDiagnostics
+      let defLine = 4
+          range = Range (Position defLine 0) (Position defLine maxBound)
+      actions <- getCodeActions doc range
+      action <- pickActionWithTitle "import B (Foo(..))" actions
+      executeCodeAction action
+      contentAfterAction <- documentContents doc
+      liftIO $ after @=? contentAfterAction
+
+suggestAddRecordFieldUpdateImportTests :: TestTree
+suggestAddRecordFieldUpdateImportTests = testGroup "suggest imports of record fields in update"
+  [ testGroup "implicit import of type" [theTest ] ]
+  where
+    theTest = testSessionWithExtraFiles "hover" def $ \dir -> do
+      configureCheckProject True
+
+      let
+          before = T.unlines ["module C where", "import B", "biz = bar { foo = 100 }"]
+          after = T.unlines ["module C where", "import B", "import A (Foo(..))", "biz = bar { foo = 100 }"]
+          cradle = "cradle: {direct: {arguments: [-hide-all-packages, -package, base, -package, text, -package-env, -, A, B, C]}}"
+      liftIO $ writeFileUTF8 (dir </> "hie.yaml") cradle
+      liftIO $ writeFileUTF8 (dir </> "A.hs") $ unlines ["module A where", "data Foo = Foo { foo :: Int }"]
+      liftIO $ writeFileUTF8 (dir </> "B.hs") $ unlines ["module B where", "import A", "bar = Foo 10" ]
+      doc <- createDoc "Test.hs" "haskell" before
+      waitForProgressDone
+      diags <- waitForDiagnostics
+      liftIO $ print diags
+      let defLine = 2
+          range = Range (Position defLine 0) (Position defLine maxBound)
+      actions <- getCodeActions doc range
+      liftIO $ print actions
+      action <- pickActionWithTitle "import A (Foo(..))" actions
+      executeCodeAction action
+      contentAfterAction <- documentContents doc
+      liftIO $ after @=? contentAfterAction
+
+extractNotInScopeNameTests :: TestTree
+extractNotInScopeNameTests =
+  testGroup "extractNotInScopeName" [
+      testGroup "record field" [
+            testCase ">=ghc 910" $ Refactor.extractNotInScopeName "Not in scope: ‘foo’"  @=? Just (NotInScopeThing "foo"),
+            testCase "<ghc 910" $ Refactor.extractNotInScopeName "Not in scope: record field ‘foo’"  @=? Just (NotInScopeThing "foo")
+            ],
+      testGroup "HasField" [
+        testGroup "unqualified" [
+          testGroup "nice ticks" [
+            testCase "Simple type" $ Refactor.extractNotInScopeName "No instance for ‘HasField \"baz\" Cheval Bool’"  @=? Just (NotInScopeThing "Cheval"),
+            testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘HasField \"bar\" (Hibou Int) a0’"  @=? Just (NotInScopeThing "Hibou"),
+            testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘HasField \"foo\" (Tortue Int) Int’"  @=? Just (NotInScopeThing "Tortue")
+            ],
+          testGroup "parenthesis" [
+            testCase "Simple type" $ Refactor.extractNotInScopeName "No instance for ‘HasField \"blup\" Calamar Bool’"  @=? Just (NotInScopeThing "Calamar"),
+            testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘HasField \"biz\" (Ornithorink Int) a0’"  @=? Just (NotInScopeThing "Ornithorink"),
+            testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘HasField \"blork\" (Salamandre Int) Int’"  @=? Just (NotInScopeThing "Salamandre")
+            ]
+          ],
+        testGroup "qualified" [
+          testGroup "nice ticks" [
+            testCase "Simple type" $ Refactor.extractNotInScopeName "No instance for ‘GHC.HasField \"baz\" Cheval Bool’"  @=? Just (NotInScopeThing "Cheval"),
+            testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘Record.HasField \"bar\" (Hibou Int) a0’"  @=? Just (NotInScopeThing "Hibou"),
+            testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘Youpi.HasField \"foo\" (Tortue Int) Int’"  @=? Just (NotInScopeThing "Tortue")
+            ],
+          testGroup "parenthesis" [
+            testCase "Simple type" $ Refactor.extractNotInScopeName "No instance for ‘GHC.Tortue.HasField \"blup\" Calamar Bool’"  @=? Just (NotInScopeThing "Calamar"),
+            testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘Youpi.Salamandre.HasField \"biz\" (Ornithorink Int) a0’"  @=? Just (NotInScopeThing "Ornithorink"),
+            testCase "Parametric type" $ Refactor.extractNotInScopeName "No instance for ‘Foo.Bar.HasField \"blork\" (Salamandre Int) Int’"  @=? Just (NotInScopeThing "Salamandre")
+            ]
+          ]
+        ]
+    ]
+suggestAddCoerceMissingConstructorImportTests :: TestTree
+suggestAddCoerceMissingConstructorImportTests = testGroup "suggest imports of newtype constructor when using coerce"
+  [ testGroup "The newtype constructor is suggested when a matching representation error"
+    [ theTest
+    ]
+  ]
+  where
+    theTest = testSessionWithExtraFiles "hover" def $ \dir -> do
+      configureCheckProject False
+      let before = T.unlines ["module A where", "import Data.Coerce (coerce)", "import Data.Semigroup (Sum)", "bar = coerce (10 :: Int) :: Sum Int"]
+          after = T.unlines ["module A where", "import Data.Coerce (coerce)", "import Data.Semigroup (Sum)", "import Data.Semigroup (Sum(..))", "bar = coerce (10 :: Int) :: Sum Int"]
+          cradle = "cradle: {direct: {arguments: [-hide-all-packages, -package, base, -package, text, -package-env, -, A]}}"
+      liftIO $ writeFileUTF8 (dir </> "hie.yaml") cradle
+      doc <- createDoc "Test.hs" "haskell" before
+      waitForProgressDone
+      _ <- waitForDiagnostics
+      let defLine = 3
+          range = Range (Position defLine 0) (Position defLine maxBound)
+      actions <- getCodeActions doc range
+      action <- pickActionWithTitle "import Data.Semigroup (Sum(..))" actions
+      executeCodeAction action
+      contentAfterAction <- documentContents doc
+      liftIO $ after @=? contentAfterAction
+
+suggestAddGenericMissingConstructorImportTests :: TestTree
+suggestAddGenericMissingConstructorImportTests = testGroup "suggest imports of type constructors when using generic deriving"
+  [ testGroup "The type constructors are suggested when not in scope"
+    [ theTest
+    ]
+  ]
+  where
+    theTest = testSessionWithExtraFiles "hover" def $ \dir -> do
+      configureCheckProject False
+      let
+          before = T.unlines ["module A where", "import GHC.Generics", "import Data.Semigroup (Sum)", "deriving instance Generic (Sum Int)"]
+          after = T.unlines ["module A where", "import GHC.Generics", "import Data.Semigroup (Sum)", "import Data.Semigroup (Sum(..))", "deriving instance Generic (Sum Int)"]
+          cradle = "cradle: {direct: {arguments: [-hide-all-packages, -package, base, -package, text, -package-env, -, A]}}"
+      liftIO $ writeFileUTF8 (dir </> "hie.yaml") cradle
+      doc <- createDoc "Test.hs" "haskell" before
+      waitForProgressDone
+      _ <- waitForDiagnostics
+      let defLine = 3
+          range = Range (Position defLine 0) (Position defLine maxBound)
+      actions <- getCodeActions doc range
+      action <- pickActionWithTitle "import Data.Semigroup (Sum(..))" actions
+      executeCodeAction action
+      contentAfterAction <- documentContents doc
+      liftIO $ after @=? contentAfterAction
+
+
 suggestImportDisambiguationTests :: TestTree
 suggestImportDisambiguationTests = testGroup "suggest import disambiguation actions"
   [ testGroup "Hiding strategy works"
@@ -2538,14 +2688,14 @@
           [ (DiagnosticSeverity_Warning, (6, 8), "Defaulting the following constraint", Nothing)
           , (DiagnosticSeverity_Warning, (6, 16), "Defaulting the following constraint", Nothing)
           ])
-      "Add type annotation ‘String’ to ‘\"debug\"’"
+      ("Add type annotation ‘" <> stringLit <> "’ to ‘\"debug\"’")
       [ "{-# OPTIONS_GHC -Wtype-defaults #-}"
       , "{-# LANGUAGE OverloadedStrings #-}"
       , "module A (f) where"
       , ""
       , "import Debug.Trace"
       , ""
-      , "f = seq (\"debug\" :: String) traceShow \"debug\""
+      , "f = seq (\"debug\" :: "<> stringLit <> ") traceShow \"debug\""
       ]
   , testSession "add default type to satisfy two constraints" $
     testFor
@@ -2560,14 +2710,14 @@
       (if ghcVersion >= GHC94
         then [ (DiagnosticSeverity_Warning, (6, 6), "Defaulting the type variable", Nothing) ]
         else [ (DiagnosticSeverity_Warning, (6, 6), "Defaulting the following constraint", Nothing) ])
-      "Add type annotation ‘String’ to ‘\"debug\"’"
+      ("Add type annotation ‘" <> stringLit <> "’ to ‘\"debug\"’")
       [ "{-# OPTIONS_GHC -Wtype-defaults #-}"
       , "{-# LANGUAGE OverloadedStrings #-}"
       , "module A (f) where"
       , ""
       , "import Debug.Trace"
       , ""
-      , "f a = traceShow (\"debug\" :: String) a"
+      , "f a = traceShow (\"debug\" :: " <> stringLit <> ") a"
       ]
   , testSession "add default type to satisfy two constraints with duplicate literals" $
     testFor
@@ -2582,17 +2732,18 @@
       (if ghcVersion >= GHC94
         then [ (DiagnosticSeverity_Warning, (6, 54), "Defaulting the type variable", Nothing) ]
         else [ (DiagnosticSeverity_Warning, (6, 54), "Defaulting the following constraint", Nothing) ])
-      "Add type annotation ‘String’ to ‘\"debug\"’"
+      ("Add type annotation ‘"<> stringLit <>"’ to ‘\"debug\"’")
       [ "{-# OPTIONS_GHC -Wtype-defaults #-}"
       , "{-# LANGUAGE OverloadedStrings #-}"
       , "module A (f) where"
       , ""
       , "import Debug.Trace"
       , ""
-      , "f = seq (\"debug\" :: [Char]) (seq (\"debug\" :: [Char]) (traceShow (\"debug\" :: String)))"
+      , "f = seq (\"debug\" :: [Char]) (seq (\"debug\" :: [Char]) (traceShow (\"debug\" :: "<> stringLit <> ")))"
       ]
   ]
   where
+    stringLit = if ghcVersion >= GHC912 then "[Char]" else "String"
     testFor sourceLines diag expectedTitle expectedLines = do
       docId <- createDoc "A.hs" "haskell" $ T.unlines sourceLines
       expectDiagnostics [ ("A.hs", diag) ]
@@ -3208,6 +3359,10 @@
     executeCodeAction chosenAction
     modifiedCode <- documentContents doc
     liftIO $ expectedCode @=? modifiedCode
+  issue806 = if ghcVersion >= GHC912 then
+                  "hello = print"           >:: "hello :: GHC.Types.ZonkAny 0 -> IO ()" -- GHC now returns ZonkAny 0 instead of Any. https://gitlab.haskell.org/ghc/ghc/-/issues/25895
+                else
+                  "hello = print"           >:: "hello :: GHC.Types.Any -> IO ()" -- Documents current behavior outlined in #806
   in
   testGroup "add signature"
     [ "abc = True"              >:: "abc :: Bool"
@@ -3216,7 +3371,7 @@
     , "(!!!) a b = a > b"       >:: "(!!!) :: Ord a => a -> a -> Bool"
     , "a >>>> b = a + b"        >:: "(>>>>) :: Num a => a -> a -> a"
     , "a `haha` b = a b"        >:: "haha :: (t1 -> t2) -> t1 -> t2"
-    , "hello = print"           >:: "hello :: GHC.Types.Any -> IO ()" -- Documents current behavior outlined in #806
+    , issue806
     , "pattern Some a = Just a" >:: "pattern Some :: a -> Maybe a"
     , "pattern Some a <- Just a" >:: "pattern Some :: a -> Maybe a"
     , "pattern Some a <- Just a\n  where Some a = Just a" >:: "pattern Some :: a -> Maybe a"
@@ -3893,8 +4048,7 @@
 -- Which we need to do on macOS since the $TMPDIR can be in @/private/var@ or
 -- @/var@
 withTempDir :: (FilePath -> IO a) -> IO a
-withTempDir f = System.IO.Extra.withTempDir $ \dir ->
-  canonicalizePath dir >>= f
+withTempDir f = System.IO.Extra.withTempDir $ (canonicalizePath >=> f)
 
 brokenForGHC94 :: String -> TestTree -> TestTree
 brokenForGHC94 = knownBrokenForGhcVersions [GHC94]
diff --git a/plugins/hls-refactor-plugin/test/Test/AddArgument.hs b/plugins/hls-refactor-plugin/test/Test/AddArgument.hs
--- a/plugins/hls-refactor-plugin/test/Test/AddArgument.hs
+++ b/plugins/hls-refactor-plugin/test/Test/AddArgument.hs
@@ -35,7 +35,7 @@
       mkGoldenAddArgTest "AddArgFromLet" (r 2 0 2 50),
       mkGoldenAddArgTest "AddArgFromWhere" (r 3 0 3 50),
       -- TODO can we make this work for GHC 9.10?
-      knownBrokenForGhcVersions [GHC910] "In GHC 9.10 end-of-line comment annotation is in different place" $
+      knownBrokenForGhcVersions [GHC910, GHC912] "In GHC 9.10 and 9.12 end-of-line comment annotation is in different place" $
           mkGoldenAddArgTest "AddArgFromWhereComments" (r 3 0 3 50),
       mkGoldenAddArgTest "AddArgWithTypeSynSig" (r 2 0 2 50),
       mkGoldenAddArgTest "AddArgWithTypeSynSigContravariant" (r 2 0 2 50),
diff --git a/plugins/hls-stylish-haskell-plugin/src/Ide/Plugin/StylishHaskell.hs b/plugins/hls-stylish-haskell-plugin/src/Ide/Plugin/StylishHaskell.hs
--- a/plugins/hls-stylish-haskell-plugin/src/Ide/Plugin/StylishHaskell.hs
+++ b/plugins/hls-stylish-haskell-plugin/src/Ide/Plugin/StylishHaskell.hs
@@ -79,10 +79,15 @@
 -- If no such file has been found, return default config.
 loadConfigFrom :: FilePath -> IO Config
 loadConfigFrom file = do
+#if MIN_VERSION_stylish_haskell(0,15,0)
+  let configSearchStrategy = SearchFromDirectory (takeDirectory file)
+  config <- loadConfig (makeVerbose False) configSearchStrategy
+#else
   currDir <- getCurrentDirectory
   setCurrentDirectory (takeDirectory file)
   config <- loadConfig (makeVerbose False) Nothing
   setCurrentDirectory currDir
+#endif
   pure config
 
 -- | Run stylish-haskell on the given text with the given configuration.
diff --git a/test/testdata/hieBiosError/hie.yaml b/test/testdata/hieBiosError/hie.yaml
new file mode 100644
--- /dev/null
+++ b/test/testdata/hieBiosError/hie.yaml
diff --git a/test/testdata/hieBiosMainIs/dist-newstyle/cache/plan.json b/test/testdata/hieBiosMainIs/dist-newstyle/cache/plan.json
deleted file mode 100644
--- a/test/testdata/hieBiosMainIs/dist-newstyle/cache/plan.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"cabal-version":"3.12.1.0","cabal-lib-version":"3.12.1.0","compiler-id":"ghc-9.12.2","os":"linux","arch":"x86_64","install-plan":[{"type":"pre-existing","id":"base-4.21.0.0-b7a5","pkg-name":"base","pkg-version":"4.21.0.0","depends":["ghc-internal-9.1202.0-7700","ghc-prim-0.13.0-00de"]},{"type":"pre-existing","id":"ghc-bignum-1.3-4dbb","pkg-name":"ghc-bignum","pkg-version":"1.3","depends":["ghc-prim-0.13.0-00de"]},{"type":"pre-existing","id":"ghc-internal-9.1202.0-7700","pkg-name":"ghc-internal","pkg-version":"9.1202.0","depends":["ghc-bignum-1.3-4dbb","ghc-prim-0.13.0-00de","rts-1.0.2"]},{"type":"pre-existing","id":"ghc-prim-0.13.0-00de","pkg-name":"ghc-prim","pkg-version":"0.13.0","depends":["rts-1.0.2"]},{"type":"configured","id":"hieBiosMainIs-0.1.0.0-inplace-hieBiosMainIs","pkg-name":"hieBiosMainIs","pkg-version":"0.1.0.0","flags":{},"style":"local","pkg-src":{"type":"local","path":"/home/hugin/Documents/haskell/hls/test/testdata/hieBiosMainIs/."},"dist-dir":"/home/hugin/Documents/haskell/hls/test/testdata/hieBiosMainIs/dist-newstyle/build/x86_64-linux/ghc-9.12.2/hieBiosMainIs-0.1.0.0/x/hieBiosMainIs","build-info":"/home/hugin/Documents/haskell/hls/test/testdata/hieBiosMainIs/dist-newstyle/build/x86_64-linux/ghc-9.12.2/hieBiosMainIs-0.1.0.0/x/hieBiosMainIs/build-info.json","depends":["base-4.21.0.0-b7a5"],"exe-depends":[],"component-name":"exe:hieBiosMainIs","bin-file":"/home/hugin/Documents/haskell/hls/test/testdata/hieBiosMainIs/dist-newstyle/build/x86_64-linux/ghc-9.12.2/hieBiosMainIs-0.1.0.0/x/hieBiosMainIs/build/hieBiosMainIs/hieBiosMainIs"},{"type":"pre-existing","id":"rts-1.0.2","pkg-name":"rts","pkg-version":"1.0.2","depends":[]}]}
diff --git a/test/testdata/missingModuleTest/missingModule/dist-newstyle/cache/plan.json b/test/testdata/missingModuleTest/missingModule/dist-newstyle/cache/plan.json
deleted file mode 100644
--- a/test/testdata/missingModuleTest/missingModule/dist-newstyle/cache/plan.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"cabal-version":"3.12.1.0","cabal-lib-version":"3.12.1.0","compiler-id":"ghc-9.12.2","os":"linux","arch":"x86_64","install-plan":[{"type":"pre-existing","id":"base-4.21.0.0-b7a5","pkg-name":"base","pkg-version":"4.21.0.0","depends":["ghc-internal-9.1202.0-7700","ghc-prim-0.13.0-00de"]},{"type":"pre-existing","id":"ghc-bignum-1.3-4dbb","pkg-name":"ghc-bignum","pkg-version":"1.3","depends":["ghc-prim-0.13.0-00de"]},{"type":"pre-existing","id":"ghc-internal-9.1202.0-7700","pkg-name":"ghc-internal","pkg-version":"9.1202.0","depends":["ghc-bignum-1.3-4dbb","ghc-prim-0.13.0-00de","rts-1.0.2"]},{"type":"pre-existing","id":"ghc-prim-0.13.0-00de","pkg-name":"ghc-prim","pkg-version":"0.13.0","depends":["rts-1.0.2"]},{"type":"configured","id":"missingModule-0.1.0.0-inplace","pkg-name":"missingModule","pkg-version":"0.1.0.0","flags":{},"style":"local","pkg-src":{"type":"local","path":"/home/hugin/Documents/haskell/hls/test/testdata/missingModuleTest/missingModule/."},"dist-dir":"/home/hugin/Documents/haskell/hls/test/testdata/missingModuleTest/missingModule/dist-newstyle/build/x86_64-linux/ghc-9.12.2/missingModule-0.1.0.0","build-info":"/home/hugin/Documents/haskell/hls/test/testdata/missingModuleTest/missingModule/dist-newstyle/build/x86_64-linux/ghc-9.12.2/missingModule-0.1.0.0/build-info.json","depends":["base-4.21.0.0-b7a5"],"exe-depends":[],"component-name":"lib"},{"type":"pre-existing","id":"rts-1.0.2","pkg-name":"rts","pkg-version":"1.0.2","depends":[]}]}
diff --git a/test/testdata/missingModuleTest/noPrefixMatch/dist-newstyle/cache/plan.json b/test/testdata/missingModuleTest/noPrefixMatch/dist-newstyle/cache/plan.json
new file mode 100644
--- /dev/null
+++ b/test/testdata/missingModuleTest/noPrefixMatch/dist-newstyle/cache/plan.json
@@ -0,0 +1,1 @@
+{"cabal-version":"3.10.1.0","cabal-lib-version":"3.10.1.0","compiler-id":"ghc-9.6.3","os":"linux","arch":"x86_64","install-plan":[{"type":"pre-existing","id":"base-4.18.1.0","pkg-name":"base","pkg-version":"4.18.1.0","depends":["ghc-bignum-1.3","ghc-prim-0.10.0","rts-1.0.2"]},{"type":"pre-existing","id":"ghc-bignum-1.3","pkg-name":"ghc-bignum","pkg-version":"1.3","depends":["ghc-prim-0.10.0"]},{"type":"pre-existing","id":"ghc-prim-0.10.0","pkg-name":"ghc-prim","pkg-version":"0.10.0","depends":["rts-1.0.2"]},{"type":"configured","id":"noPrefixMatch-0.1.0.0-inplace-testExe","pkg-name":"noPrefixMatch","pkg-version":"0.1.0.0","flags":{},"style":"local","pkg-src":{"type":"local","path":"/home/zubin/haskell-language-server-dist/test/testdata/missingModuleTest/noPrefixMatch/."},"dist-dir":"/home/zubin/haskell-language-server-dist/test/testdata/missingModuleTest/noPrefixMatch/dist-newstyle/build/x86_64-linux/ghc-9.6.3/noPrefixMatch-0.1.0.0/x/testExe","build-info":"/home/zubin/haskell-language-server-dist/test/testdata/missingModuleTest/noPrefixMatch/dist-newstyle/build/x86_64-linux/ghc-9.6.3/noPrefixMatch-0.1.0.0/x/testExe/build-info.json","depends":["base-4.18.1.0"],"exe-depends":[],"component-name":"exe:testExe","bin-file":"/home/zubin/haskell-language-server-dist/test/testdata/missingModuleTest/noPrefixMatch/dist-newstyle/build/x86_64-linux/ghc-9.6.3/noPrefixMatch-0.1.0.0/x/testExe/build/testExe/testExe"},{"type":"pre-existing","id":"rts-1.0.2","pkg-name":"rts","pkg-version":"1.0.2","depends":[]}]}
diff --git a/test/testdata/schema/ghc910/default-config.golden.json b/test/testdata/schema/ghc910/default-config.golden.json
new file mode 100644
--- /dev/null
+++ b/test/testdata/schema/ghc910/default-config.golden.json
@@ -0,0 +1,151 @@
+{
+    "cabalFormattingProvider": "cabal-gild",
+    "checkParents": "CheckOnSave",
+    "checkProject": true,
+    "formattingProvider": "ormolu",
+    "maxCompletions": 40,
+    "plugin": {
+        "alternateNumberFormat": {
+            "globalOn": true
+        },
+        "cabal": {
+            "codeActionsOn": true,
+            "completionOn": true,
+            "diagnosticsOn": true,
+            "hoverOn": true,
+            "symbolsOn": true
+        },
+        "cabal-fmt": {
+            "config": {
+                "path": "cabal-fmt"
+            }
+        },
+        "cabal-gild": {
+            "config": {
+                "path": "cabal-gild"
+            }
+        },
+        "cabalHaskellIntegration": {
+            "globalOn": true
+        },
+        "callHierarchy": {
+            "globalOn": true
+        },
+        "changeTypeSignature": {
+            "globalOn": true
+        },
+        "class": {
+            "codeActionsOn": true,
+            "codeLensOn": true
+        },
+        "eval": {
+            "codeActionsOn": true,
+            "codeLensOn": true,
+            "config": {
+                "diff": true,
+                "exception": false
+            }
+        },
+        "explicit-fields": {
+            "codeActionsOn": true,
+            "inlayHintsOn": true
+        },
+        "explicit-fixity": {
+            "globalOn": true
+        },
+        "fourmolu": {
+            "config": {
+                "external": false,
+                "path": "fourmolu"
+            }
+        },
+        "gadt": {
+            "globalOn": true
+        },
+        "ghcide-code-actions-bindings": {
+            "globalOn": true
+        },
+        "ghcide-code-actions-fill-holes": {
+            "globalOn": true
+        },
+        "ghcide-code-actions-imports-exports": {
+            "globalOn": true
+        },
+        "ghcide-code-actions-type-signatures": {
+            "globalOn": true
+        },
+        "ghcide-completions": {
+            "config": {
+                "autoExtendOn": true,
+                "snippetsOn": true
+            },
+            "globalOn": true
+        },
+        "ghcide-hover-and-symbols": {
+            "hoverOn": true,
+            "symbolsOn": true
+        },
+        "ghcide-type-lenses": {
+            "config": {
+                "mode": "always"
+            },
+            "globalOn": true
+        },
+        "importLens": {
+            "codeActionsOn": true,
+            "codeLensOn": true,
+            "inlayHintsOn": true
+        },
+        "moduleName": {
+            "globalOn": true
+        },
+        "ormolu": {
+            "config": {
+                "external": false
+            }
+        },
+        "overloaded-record-dot": {
+            "globalOn": true
+        },
+        "pragmas-completion": {
+            "globalOn": true
+        },
+        "pragmas-disable": {
+            "globalOn": true
+        },
+        "pragmas-suggest": {
+            "globalOn": true
+        },
+        "qualifyImportedNames": {
+            "globalOn": true
+        },
+        "rename": {
+            "config": {
+                "crossModule": false
+            },
+            "globalOn": true
+        },
+        "semanticTokens": {
+            "config": {
+                "classMethodToken": "method",
+                "classToken": "class",
+                "dataConstructorToken": "enumMember",
+                "functionToken": "function",
+                "moduleToken": "namespace",
+                "operatorToken": "operator",
+                "patternSynonymToken": "macro",
+                "recordFieldToken": "property",
+                "typeConstructorToken": "enum",
+                "typeFamilyToken": "interface",
+                "typeSynonymToken": "type",
+                "typeVariableToken": "typeParameter",
+                "variableToken": "variable"
+            },
+            "globalOn": false
+        },
+        "stan": {
+            "globalOn": false
+        }
+    },
+    "sessionLoading": "singleComponent"
+}
diff --git a/test/testdata/schema/ghc910/vscode-extension-schema.golden.json b/test/testdata/schema/ghc910/vscode-extension-schema.golden.json
new file mode 100644
--- /dev/null
+++ b/test/testdata/schema/ghc910/vscode-extension-schema.golden.json
@@ -0,0 +1,1028 @@
+{
+    "haskell.plugin.alternateNumberFormat.globalOn": {
+        "default": true,
+        "description": "Enables alternateNumberFormat plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.cabal-fmt.config.path": {
+        "default": "cabal-fmt",
+        "markdownDescription": "Set path to 'cabal-fmt' executable",
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.cabal-gild.config.path": {
+        "default": "cabal-gild",
+        "markdownDescription": "Set path to 'cabal-gild' executable",
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.cabal.codeActionsOn": {
+        "default": true,
+        "description": "Enables cabal code actions",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.cabal.completionOn": {
+        "default": true,
+        "description": "Enables cabal completions",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.cabal.diagnosticsOn": {
+        "default": true,
+        "description": "Enables cabal diagnostics",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.cabal.hoverOn": {
+        "default": true,
+        "description": "Enables cabal hover",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.cabal.symbolsOn": {
+        "default": true,
+        "description": "Enables cabal symbols",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.cabalHaskellIntegration.globalOn": {
+        "default": true,
+        "description": "Enables cabalHaskellIntegration plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.callHierarchy.globalOn": {
+        "default": true,
+        "description": "Enables callHierarchy plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.changeTypeSignature.globalOn": {
+        "default": true,
+        "description": "Enables changeTypeSignature plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.class.codeActionsOn": {
+        "default": true,
+        "description": "Enables class code actions",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.class.codeLensOn": {
+        "default": true,
+        "description": "Enables class code lenses",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.eval.codeActionsOn": {
+        "default": true,
+        "description": "Enables eval code actions",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.eval.codeLensOn": {
+        "default": true,
+        "description": "Enables eval code lenses",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.eval.config.diff": {
+        "default": true,
+        "markdownDescription": "Enable the diff output (WAS/NOW) of eval lenses",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.eval.config.exception": {
+        "default": false,
+        "markdownDescription": "Enable marking exceptions with `*** Exception:` similarly to doctest and GHCi.",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.explicit-fields.codeActionsOn": {
+        "default": true,
+        "description": "Enables explicit-fields code actions",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.explicit-fields.inlayHintsOn": {
+        "default": true,
+        "description": "Enables explicit-fields inlay hints",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.explicit-fixity.globalOn": {
+        "default": true,
+        "description": "Enables explicit-fixity plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.fourmolu.config.external": {
+        "default": false,
+        "markdownDescription": "Call out to an external \"fourmolu\" executable, rather than using the bundled library.",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.fourmolu.config.path": {
+        "default": "fourmolu",
+        "markdownDescription": "Set path to executable (for \"external\" mode).",
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.gadt.globalOn": {
+        "default": true,
+        "description": "Enables gadt plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.ghcide-code-actions-bindings.globalOn": {
+        "default": true,
+        "description": "Enables ghcide-code-actions-bindings plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.ghcide-code-actions-fill-holes.globalOn": {
+        "default": true,
+        "description": "Enables ghcide-code-actions-fill-holes plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.ghcide-code-actions-imports-exports.globalOn": {
+        "default": true,
+        "description": "Enables ghcide-code-actions-imports-exports plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.ghcide-code-actions-type-signatures.globalOn": {
+        "default": true,
+        "description": "Enables ghcide-code-actions-type-signatures plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.ghcide-completions.config.autoExtendOn": {
+        "default": true,
+        "markdownDescription": "Extends the import list automatically when completing a out-of-scope identifier",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.ghcide-completions.config.snippetsOn": {
+        "default": true,
+        "markdownDescription": "Inserts snippets when using code completions",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.ghcide-completions.globalOn": {
+        "default": true,
+        "description": "Enables ghcide-completions plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.ghcide-hover-and-symbols.hoverOn": {
+        "default": true,
+        "description": "Enables ghcide-hover-and-symbols hover",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.ghcide-hover-and-symbols.symbolsOn": {
+        "default": true,
+        "description": "Enables ghcide-hover-and-symbols symbols",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.ghcide-type-lenses.config.mode": {
+        "default": "always",
+        "description": "Control how type lenses are shown",
+        "enum": [
+            "always",
+            "exported",
+            "diagnostics"
+        ],
+        "enumDescriptions": [
+            "Always displays type lenses of global bindings",
+            "Only display type lenses of exported global bindings",
+            "Follows error messages produced by GHC about missing signatures"
+        ],
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.ghcide-type-lenses.globalOn": {
+        "default": true,
+        "description": "Enables ghcide-type-lenses plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.importLens.codeActionsOn": {
+        "default": true,
+        "description": "Enables importLens code actions",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.importLens.codeLensOn": {
+        "default": true,
+        "description": "Enables importLens code lenses",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.importLens.inlayHintsOn": {
+        "default": true,
+        "description": "Enables importLens inlay hints",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.moduleName.globalOn": {
+        "default": true,
+        "description": "Enables moduleName plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.ormolu.config.external": {
+        "default": false,
+        "markdownDescription": "Call out to an external \"ormolu\" executable, rather than using the bundled library",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.overloaded-record-dot.globalOn": {
+        "default": true,
+        "description": "Enables overloaded-record-dot plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.pragmas-completion.globalOn": {
+        "default": true,
+        "description": "Enables pragmas-completion plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.pragmas-disable.globalOn": {
+        "default": true,
+        "description": "Enables pragmas-disable plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.pragmas-suggest.globalOn": {
+        "default": true,
+        "description": "Enables pragmas-suggest plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.qualifyImportedNames.globalOn": {
+        "default": true,
+        "description": "Enables qualifyImportedNames plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.rename.config.crossModule": {
+        "default": false,
+        "markdownDescription": "Enable experimental cross-module renaming",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.rename.globalOn": {
+        "default": true,
+        "description": "Enables rename plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.semanticTokens.config.classMethodToken": {
+        "default": "method",
+        "description": "LSP semantic token type to use for typeclass methods",
+        "enum": [
+            "namespace",
+            "type",
+            "class",
+            "enum",
+            "interface",
+            "struct",
+            "typeParameter",
+            "parameter",
+            "variable",
+            "property",
+            "enumMember",
+            "event",
+            "function",
+            "method",
+            "macro",
+            "keyword",
+            "modifier",
+            "comment",
+            "string",
+            "number",
+            "regexp",
+            "operator",
+            "decorator"
+        ],
+        "enumDescriptions": [
+            "LSP Semantic Token Type: namespace",
+            "LSP Semantic Token Type: type",
+            "LSP Semantic Token Type: class",
+            "LSP Semantic Token Type: enum",
+            "LSP Semantic Token Type: interface",
+            "LSP Semantic Token Type: struct",
+            "LSP Semantic Token Type: typeParameter",
+            "LSP Semantic Token Type: parameter",
+            "LSP Semantic Token Type: variable",
+            "LSP Semantic Token Type: property",
+            "LSP Semantic Token Type: enumMember",
+            "LSP Semantic Token Type: event",
+            "LSP Semantic Token Type: function",
+            "LSP Semantic Token Type: method",
+            "LSP Semantic Token Type: macro",
+            "LSP Semantic Token Type: keyword",
+            "LSP Semantic Token Type: modifier",
+            "LSP Semantic Token Type: comment",
+            "LSP Semantic Token Type: string",
+            "LSP Semantic Token Type: number",
+            "LSP Semantic Token Type: regexp",
+            "LSP Semantic Token Type: operator",
+            "LSP Semantic Token Type: decorator"
+        ],
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.semanticTokens.config.classToken": {
+        "default": "class",
+        "description": "LSP semantic token type to use for typeclasses",
+        "enum": [
+            "namespace",
+            "type",
+            "class",
+            "enum",
+            "interface",
+            "struct",
+            "typeParameter",
+            "parameter",
+            "variable",
+            "property",
+            "enumMember",
+            "event",
+            "function",
+            "method",
+            "macro",
+            "keyword",
+            "modifier",
+            "comment",
+            "string",
+            "number",
+            "regexp",
+            "operator",
+            "decorator"
+        ],
+        "enumDescriptions": [
+            "LSP Semantic Token Type: namespace",
+            "LSP Semantic Token Type: type",
+            "LSP Semantic Token Type: class",
+            "LSP Semantic Token Type: enum",
+            "LSP Semantic Token Type: interface",
+            "LSP Semantic Token Type: struct",
+            "LSP Semantic Token Type: typeParameter",
+            "LSP Semantic Token Type: parameter",
+            "LSP Semantic Token Type: variable",
+            "LSP Semantic Token Type: property",
+            "LSP Semantic Token Type: enumMember",
+            "LSP Semantic Token Type: event",
+            "LSP Semantic Token Type: function",
+            "LSP Semantic Token Type: method",
+            "LSP Semantic Token Type: macro",
+            "LSP Semantic Token Type: keyword",
+            "LSP Semantic Token Type: modifier",
+            "LSP Semantic Token Type: comment",
+            "LSP Semantic Token Type: string",
+            "LSP Semantic Token Type: number",
+            "LSP Semantic Token Type: regexp",
+            "LSP Semantic Token Type: operator",
+            "LSP Semantic Token Type: decorator"
+        ],
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.semanticTokens.config.dataConstructorToken": {
+        "default": "enumMember",
+        "description": "LSP semantic token type to use for data constructors",
+        "enum": [
+            "namespace",
+            "type",
+            "class",
+            "enum",
+            "interface",
+            "struct",
+            "typeParameter",
+            "parameter",
+            "variable",
+            "property",
+            "enumMember",
+            "event",
+            "function",
+            "method",
+            "macro",
+            "keyword",
+            "modifier",
+            "comment",
+            "string",
+            "number",
+            "regexp",
+            "operator",
+            "decorator"
+        ],
+        "enumDescriptions": [
+            "LSP Semantic Token Type: namespace",
+            "LSP Semantic Token Type: type",
+            "LSP Semantic Token Type: class",
+            "LSP Semantic Token Type: enum",
+            "LSP Semantic Token Type: interface",
+            "LSP Semantic Token Type: struct",
+            "LSP Semantic Token Type: typeParameter",
+            "LSP Semantic Token Type: parameter",
+            "LSP Semantic Token Type: variable",
+            "LSP Semantic Token Type: property",
+            "LSP Semantic Token Type: enumMember",
+            "LSP Semantic Token Type: event",
+            "LSP Semantic Token Type: function",
+            "LSP Semantic Token Type: method",
+            "LSP Semantic Token Type: macro",
+            "LSP Semantic Token Type: keyword",
+            "LSP Semantic Token Type: modifier",
+            "LSP Semantic Token Type: comment",
+            "LSP Semantic Token Type: string",
+            "LSP Semantic Token Type: number",
+            "LSP Semantic Token Type: regexp",
+            "LSP Semantic Token Type: operator",
+            "LSP Semantic Token Type: decorator"
+        ],
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.semanticTokens.config.functionToken": {
+        "default": "function",
+        "description": "LSP semantic token type to use for functions",
+        "enum": [
+            "namespace",
+            "type",
+            "class",
+            "enum",
+            "interface",
+            "struct",
+            "typeParameter",
+            "parameter",
+            "variable",
+            "property",
+            "enumMember",
+            "event",
+            "function",
+            "method",
+            "macro",
+            "keyword",
+            "modifier",
+            "comment",
+            "string",
+            "number",
+            "regexp",
+            "operator",
+            "decorator"
+        ],
+        "enumDescriptions": [
+            "LSP Semantic Token Type: namespace",
+            "LSP Semantic Token Type: type",
+            "LSP Semantic Token Type: class",
+            "LSP Semantic Token Type: enum",
+            "LSP Semantic Token Type: interface",
+            "LSP Semantic Token Type: struct",
+            "LSP Semantic Token Type: typeParameter",
+            "LSP Semantic Token Type: parameter",
+            "LSP Semantic Token Type: variable",
+            "LSP Semantic Token Type: property",
+            "LSP Semantic Token Type: enumMember",
+            "LSP Semantic Token Type: event",
+            "LSP Semantic Token Type: function",
+            "LSP Semantic Token Type: method",
+            "LSP Semantic Token Type: macro",
+            "LSP Semantic Token Type: keyword",
+            "LSP Semantic Token Type: modifier",
+            "LSP Semantic Token Type: comment",
+            "LSP Semantic Token Type: string",
+            "LSP Semantic Token Type: number",
+            "LSP Semantic Token Type: regexp",
+            "LSP Semantic Token Type: operator",
+            "LSP Semantic Token Type: decorator"
+        ],
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.semanticTokens.config.moduleToken": {
+        "default": "namespace",
+        "description": "LSP semantic token type to use for modules",
+        "enum": [
+            "namespace",
+            "type",
+            "class",
+            "enum",
+            "interface",
+            "struct",
+            "typeParameter",
+            "parameter",
+            "variable",
+            "property",
+            "enumMember",
+            "event",
+            "function",
+            "method",
+            "macro",
+            "keyword",
+            "modifier",
+            "comment",
+            "string",
+            "number",
+            "regexp",
+            "operator",
+            "decorator"
+        ],
+        "enumDescriptions": [
+            "LSP Semantic Token Type: namespace",
+            "LSP Semantic Token Type: type",
+            "LSP Semantic Token Type: class",
+            "LSP Semantic Token Type: enum",
+            "LSP Semantic Token Type: interface",
+            "LSP Semantic Token Type: struct",
+            "LSP Semantic Token Type: typeParameter",
+            "LSP Semantic Token Type: parameter",
+            "LSP Semantic Token Type: variable",
+            "LSP Semantic Token Type: property",
+            "LSP Semantic Token Type: enumMember",
+            "LSP Semantic Token Type: event",
+            "LSP Semantic Token Type: function",
+            "LSP Semantic Token Type: method",
+            "LSP Semantic Token Type: macro",
+            "LSP Semantic Token Type: keyword",
+            "LSP Semantic Token Type: modifier",
+            "LSP Semantic Token Type: comment",
+            "LSP Semantic Token Type: string",
+            "LSP Semantic Token Type: number",
+            "LSP Semantic Token Type: regexp",
+            "LSP Semantic Token Type: operator",
+            "LSP Semantic Token Type: decorator"
+        ],
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.semanticTokens.config.operatorToken": {
+        "default": "operator",
+        "description": "LSP semantic token type to use for operators",
+        "enum": [
+            "namespace",
+            "type",
+            "class",
+            "enum",
+            "interface",
+            "struct",
+            "typeParameter",
+            "parameter",
+            "variable",
+            "property",
+            "enumMember",
+            "event",
+            "function",
+            "method",
+            "macro",
+            "keyword",
+            "modifier",
+            "comment",
+            "string",
+            "number",
+            "regexp",
+            "operator",
+            "decorator"
+        ],
+        "enumDescriptions": [
+            "LSP Semantic Token Type: namespace",
+            "LSP Semantic Token Type: type",
+            "LSP Semantic Token Type: class",
+            "LSP Semantic Token Type: enum",
+            "LSP Semantic Token Type: interface",
+            "LSP Semantic Token Type: struct",
+            "LSP Semantic Token Type: typeParameter",
+            "LSP Semantic Token Type: parameter",
+            "LSP Semantic Token Type: variable",
+            "LSP Semantic Token Type: property",
+            "LSP Semantic Token Type: enumMember",
+            "LSP Semantic Token Type: event",
+            "LSP Semantic Token Type: function",
+            "LSP Semantic Token Type: method",
+            "LSP Semantic Token Type: macro",
+            "LSP Semantic Token Type: keyword",
+            "LSP Semantic Token Type: modifier",
+            "LSP Semantic Token Type: comment",
+            "LSP Semantic Token Type: string",
+            "LSP Semantic Token Type: number",
+            "LSP Semantic Token Type: regexp",
+            "LSP Semantic Token Type: operator",
+            "LSP Semantic Token Type: decorator"
+        ],
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.semanticTokens.config.patternSynonymToken": {
+        "default": "macro",
+        "description": "LSP semantic token type to use for pattern synonyms",
+        "enum": [
+            "namespace",
+            "type",
+            "class",
+            "enum",
+            "interface",
+            "struct",
+            "typeParameter",
+            "parameter",
+            "variable",
+            "property",
+            "enumMember",
+            "event",
+            "function",
+            "method",
+            "macro",
+            "keyword",
+            "modifier",
+            "comment",
+            "string",
+            "number",
+            "regexp",
+            "operator",
+            "decorator"
+        ],
+        "enumDescriptions": [
+            "LSP Semantic Token Type: namespace",
+            "LSP Semantic Token Type: type",
+            "LSP Semantic Token Type: class",
+            "LSP Semantic Token Type: enum",
+            "LSP Semantic Token Type: interface",
+            "LSP Semantic Token Type: struct",
+            "LSP Semantic Token Type: typeParameter",
+            "LSP Semantic Token Type: parameter",
+            "LSP Semantic Token Type: variable",
+            "LSP Semantic Token Type: property",
+            "LSP Semantic Token Type: enumMember",
+            "LSP Semantic Token Type: event",
+            "LSP Semantic Token Type: function",
+            "LSP Semantic Token Type: method",
+            "LSP Semantic Token Type: macro",
+            "LSP Semantic Token Type: keyword",
+            "LSP Semantic Token Type: modifier",
+            "LSP Semantic Token Type: comment",
+            "LSP Semantic Token Type: string",
+            "LSP Semantic Token Type: number",
+            "LSP Semantic Token Type: regexp",
+            "LSP Semantic Token Type: operator",
+            "LSP Semantic Token Type: decorator"
+        ],
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.semanticTokens.config.recordFieldToken": {
+        "default": "property",
+        "description": "LSP semantic token type to use for record fields",
+        "enum": [
+            "namespace",
+            "type",
+            "class",
+            "enum",
+            "interface",
+            "struct",
+            "typeParameter",
+            "parameter",
+            "variable",
+            "property",
+            "enumMember",
+            "event",
+            "function",
+            "method",
+            "macro",
+            "keyword",
+            "modifier",
+            "comment",
+            "string",
+            "number",
+            "regexp",
+            "operator",
+            "decorator"
+        ],
+        "enumDescriptions": [
+            "LSP Semantic Token Type: namespace",
+            "LSP Semantic Token Type: type",
+            "LSP Semantic Token Type: class",
+            "LSP Semantic Token Type: enum",
+            "LSP Semantic Token Type: interface",
+            "LSP Semantic Token Type: struct",
+            "LSP Semantic Token Type: typeParameter",
+            "LSP Semantic Token Type: parameter",
+            "LSP Semantic Token Type: variable",
+            "LSP Semantic Token Type: property",
+            "LSP Semantic Token Type: enumMember",
+            "LSP Semantic Token Type: event",
+            "LSP Semantic Token Type: function",
+            "LSP Semantic Token Type: method",
+            "LSP Semantic Token Type: macro",
+            "LSP Semantic Token Type: keyword",
+            "LSP Semantic Token Type: modifier",
+            "LSP Semantic Token Type: comment",
+            "LSP Semantic Token Type: string",
+            "LSP Semantic Token Type: number",
+            "LSP Semantic Token Type: regexp",
+            "LSP Semantic Token Type: operator",
+            "LSP Semantic Token Type: decorator"
+        ],
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.semanticTokens.config.typeConstructorToken": {
+        "default": "enum",
+        "description": "LSP semantic token type to use for type constructors",
+        "enum": [
+            "namespace",
+            "type",
+            "class",
+            "enum",
+            "interface",
+            "struct",
+            "typeParameter",
+            "parameter",
+            "variable",
+            "property",
+            "enumMember",
+            "event",
+            "function",
+            "method",
+            "macro",
+            "keyword",
+            "modifier",
+            "comment",
+            "string",
+            "number",
+            "regexp",
+            "operator",
+            "decorator"
+        ],
+        "enumDescriptions": [
+            "LSP Semantic Token Type: namespace",
+            "LSP Semantic Token Type: type",
+            "LSP Semantic Token Type: class",
+            "LSP Semantic Token Type: enum",
+            "LSP Semantic Token Type: interface",
+            "LSP Semantic Token Type: struct",
+            "LSP Semantic Token Type: typeParameter",
+            "LSP Semantic Token Type: parameter",
+            "LSP Semantic Token Type: variable",
+            "LSP Semantic Token Type: property",
+            "LSP Semantic Token Type: enumMember",
+            "LSP Semantic Token Type: event",
+            "LSP Semantic Token Type: function",
+            "LSP Semantic Token Type: method",
+            "LSP Semantic Token Type: macro",
+            "LSP Semantic Token Type: keyword",
+            "LSP Semantic Token Type: modifier",
+            "LSP Semantic Token Type: comment",
+            "LSP Semantic Token Type: string",
+            "LSP Semantic Token Type: number",
+            "LSP Semantic Token Type: regexp",
+            "LSP Semantic Token Type: operator",
+            "LSP Semantic Token Type: decorator"
+        ],
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.semanticTokens.config.typeFamilyToken": {
+        "default": "interface",
+        "description": "LSP semantic token type to use for type families",
+        "enum": [
+            "namespace",
+            "type",
+            "class",
+            "enum",
+            "interface",
+            "struct",
+            "typeParameter",
+            "parameter",
+            "variable",
+            "property",
+            "enumMember",
+            "event",
+            "function",
+            "method",
+            "macro",
+            "keyword",
+            "modifier",
+            "comment",
+            "string",
+            "number",
+            "regexp",
+            "operator",
+            "decorator"
+        ],
+        "enumDescriptions": [
+            "LSP Semantic Token Type: namespace",
+            "LSP Semantic Token Type: type",
+            "LSP Semantic Token Type: class",
+            "LSP Semantic Token Type: enum",
+            "LSP Semantic Token Type: interface",
+            "LSP Semantic Token Type: struct",
+            "LSP Semantic Token Type: typeParameter",
+            "LSP Semantic Token Type: parameter",
+            "LSP Semantic Token Type: variable",
+            "LSP Semantic Token Type: property",
+            "LSP Semantic Token Type: enumMember",
+            "LSP Semantic Token Type: event",
+            "LSP Semantic Token Type: function",
+            "LSP Semantic Token Type: method",
+            "LSP Semantic Token Type: macro",
+            "LSP Semantic Token Type: keyword",
+            "LSP Semantic Token Type: modifier",
+            "LSP Semantic Token Type: comment",
+            "LSP Semantic Token Type: string",
+            "LSP Semantic Token Type: number",
+            "LSP Semantic Token Type: regexp",
+            "LSP Semantic Token Type: operator",
+            "LSP Semantic Token Type: decorator"
+        ],
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.semanticTokens.config.typeSynonymToken": {
+        "default": "type",
+        "description": "LSP semantic token type to use for type synonyms",
+        "enum": [
+            "namespace",
+            "type",
+            "class",
+            "enum",
+            "interface",
+            "struct",
+            "typeParameter",
+            "parameter",
+            "variable",
+            "property",
+            "enumMember",
+            "event",
+            "function",
+            "method",
+            "macro",
+            "keyword",
+            "modifier",
+            "comment",
+            "string",
+            "number",
+            "regexp",
+            "operator",
+            "decorator"
+        ],
+        "enumDescriptions": [
+            "LSP Semantic Token Type: namespace",
+            "LSP Semantic Token Type: type",
+            "LSP Semantic Token Type: class",
+            "LSP Semantic Token Type: enum",
+            "LSP Semantic Token Type: interface",
+            "LSP Semantic Token Type: struct",
+            "LSP Semantic Token Type: typeParameter",
+            "LSP Semantic Token Type: parameter",
+            "LSP Semantic Token Type: variable",
+            "LSP Semantic Token Type: property",
+            "LSP Semantic Token Type: enumMember",
+            "LSP Semantic Token Type: event",
+            "LSP Semantic Token Type: function",
+            "LSP Semantic Token Type: method",
+            "LSP Semantic Token Type: macro",
+            "LSP Semantic Token Type: keyword",
+            "LSP Semantic Token Type: modifier",
+            "LSP Semantic Token Type: comment",
+            "LSP Semantic Token Type: string",
+            "LSP Semantic Token Type: number",
+            "LSP Semantic Token Type: regexp",
+            "LSP Semantic Token Type: operator",
+            "LSP Semantic Token Type: decorator"
+        ],
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.semanticTokens.config.typeVariableToken": {
+        "default": "typeParameter",
+        "description": "LSP semantic token type to use for type variables",
+        "enum": [
+            "namespace",
+            "type",
+            "class",
+            "enum",
+            "interface",
+            "struct",
+            "typeParameter",
+            "parameter",
+            "variable",
+            "property",
+            "enumMember",
+            "event",
+            "function",
+            "method",
+            "macro",
+            "keyword",
+            "modifier",
+            "comment",
+            "string",
+            "number",
+            "regexp",
+            "operator",
+            "decorator"
+        ],
+        "enumDescriptions": [
+            "LSP Semantic Token Type: namespace",
+            "LSP Semantic Token Type: type",
+            "LSP Semantic Token Type: class",
+            "LSP Semantic Token Type: enum",
+            "LSP Semantic Token Type: interface",
+            "LSP Semantic Token Type: struct",
+            "LSP Semantic Token Type: typeParameter",
+            "LSP Semantic Token Type: parameter",
+            "LSP Semantic Token Type: variable",
+            "LSP Semantic Token Type: property",
+            "LSP Semantic Token Type: enumMember",
+            "LSP Semantic Token Type: event",
+            "LSP Semantic Token Type: function",
+            "LSP Semantic Token Type: method",
+            "LSP Semantic Token Type: macro",
+            "LSP Semantic Token Type: keyword",
+            "LSP Semantic Token Type: modifier",
+            "LSP Semantic Token Type: comment",
+            "LSP Semantic Token Type: string",
+            "LSP Semantic Token Type: number",
+            "LSP Semantic Token Type: regexp",
+            "LSP Semantic Token Type: operator",
+            "LSP Semantic Token Type: decorator"
+        ],
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.semanticTokens.config.variableToken": {
+        "default": "variable",
+        "description": "LSP semantic token type to use for variables",
+        "enum": [
+            "namespace",
+            "type",
+            "class",
+            "enum",
+            "interface",
+            "struct",
+            "typeParameter",
+            "parameter",
+            "variable",
+            "property",
+            "enumMember",
+            "event",
+            "function",
+            "method",
+            "macro",
+            "keyword",
+            "modifier",
+            "comment",
+            "string",
+            "number",
+            "regexp",
+            "operator",
+            "decorator"
+        ],
+        "enumDescriptions": [
+            "LSP Semantic Token Type: namespace",
+            "LSP Semantic Token Type: type",
+            "LSP Semantic Token Type: class",
+            "LSP Semantic Token Type: enum",
+            "LSP Semantic Token Type: interface",
+            "LSP Semantic Token Type: struct",
+            "LSP Semantic Token Type: typeParameter",
+            "LSP Semantic Token Type: parameter",
+            "LSP Semantic Token Type: variable",
+            "LSP Semantic Token Type: property",
+            "LSP Semantic Token Type: enumMember",
+            "LSP Semantic Token Type: event",
+            "LSP Semantic Token Type: function",
+            "LSP Semantic Token Type: method",
+            "LSP Semantic Token Type: macro",
+            "LSP Semantic Token Type: keyword",
+            "LSP Semantic Token Type: modifier",
+            "LSP Semantic Token Type: comment",
+            "LSP Semantic Token Type: string",
+            "LSP Semantic Token Type: number",
+            "LSP Semantic Token Type: regexp",
+            "LSP Semantic Token Type: operator",
+            "LSP Semantic Token Type: decorator"
+        ],
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.semanticTokens.globalOn": {
+        "default": false,
+        "description": "Enables semanticTokens plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.stan.globalOn": {
+        "default": false,
+        "description": "Enables stan plugin",
+        "scope": "resource",
+        "type": "boolean"
+    }
+}
diff --git a/test/testdata/schema/ghc912/default-config.golden.json b/test/testdata/schema/ghc912/default-config.golden.json
--- a/test/testdata/schema/ghc912/default-config.golden.json
+++ b/test/testdata/schema/ghc912/default-config.golden.json
@@ -20,6 +20,11 @@
                 "path": "cabal-fmt"
             }
         },
+        "cabal-gild": {
+            "config": {
+                "path": "cabal-gild"
+            }
+        },
         "cabalHaskellIntegration": {
             "globalOn": true
         },
@@ -34,11 +39,12 @@
             "codeLensOn": true
         },
         "eval": {
+            "codeActionsOn": true,
+            "codeLensOn": true,
             "config": {
                 "diff": true,
                 "exception": false
-            },
-            "globalOn": true
+            }
         },
         "explicit-fields": {
             "codeActionsOn": true,
@@ -47,6 +53,27 @@
         "explicit-fixity": {
             "globalOn": true
         },
+        "fourmolu": {
+            "config": {
+                "external": false,
+                "path": "fourmolu"
+            }
+        },
+        "gadt": {
+            "globalOn": true
+        },
+        "ghcide-code-actions-bindings": {
+            "globalOn": true
+        },
+        "ghcide-code-actions-fill-holes": {
+            "globalOn": true
+        },
+        "ghcide-code-actions-imports-exports": {
+            "globalOn": true
+        },
+        "ghcide-code-actions-type-signatures": {
+            "globalOn": true
+        },
         "ghcide-completions": {
             "config": {
                 "autoExtendOn": true,
@@ -64,6 +91,13 @@
             },
             "globalOn": true
         },
+        "hlint": {
+            "codeActionsOn": true,
+            "config": {
+                "flags": []
+            },
+            "diagnosticsOn": true
+        },
         "importLens": {
             "codeActionsOn": true,
             "codeLensOn": true,
@@ -72,6 +106,11 @@
         "moduleName": {
             "globalOn": true
         },
+        "ormolu": {
+            "config": {
+                "external": false
+            }
+        },
         "overloaded-record-dot": {
             "globalOn": true
         },
@@ -85,6 +124,12 @@
             "globalOn": true
         },
         "qualifyImportedNames": {
+            "globalOn": true
+        },
+        "rename": {
+            "config": {
+                "crossModule": false
+            },
             "globalOn": true
         },
         "semanticTokens": {
diff --git a/test/testdata/schema/ghc912/vscode-extension-schema.golden.json b/test/testdata/schema/ghc912/vscode-extension-schema.golden.json
--- a/test/testdata/schema/ghc912/vscode-extension-schema.golden.json
+++ b/test/testdata/schema/ghc912/vscode-extension-schema.golden.json
@@ -11,6 +11,12 @@
         "scope": "resource",
         "type": "string"
     },
+    "haskell.plugin.cabal-gild.config.path": {
+        "default": "cabal-gild",
+        "markdownDescription": "Set path to 'cabal-gild' executable",
+        "scope": "resource",
+        "type": "string"
+    },
     "haskell.plugin.cabal.codeActionsOn": {
         "default": true,
         "description": "Enables cabal code actions",
@@ -71,6 +77,18 @@
         "scope": "resource",
         "type": "boolean"
     },
+    "haskell.plugin.eval.codeActionsOn": {
+        "default": true,
+        "description": "Enables eval code actions",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.eval.codeLensOn": {
+        "default": true,
+        "description": "Enables eval code lenses",
+        "scope": "resource",
+        "type": "boolean"
+    },
     "haskell.plugin.eval.config.diff": {
         "default": true,
         "markdownDescription": "Enable the diff output (WAS/NOW) of eval lenses",
@@ -83,12 +101,6 @@
         "scope": "resource",
         "type": "boolean"
     },
-    "haskell.plugin.eval.globalOn": {
-        "default": true,
-        "description": "Enables eval plugin",
-        "scope": "resource",
-        "type": "boolean"
-    },
     "haskell.plugin.explicit-fields.codeActionsOn": {
         "default": true,
         "description": "Enables explicit-fields code actions",
@@ -107,6 +119,48 @@
         "scope": "resource",
         "type": "boolean"
     },
+    "haskell.plugin.fourmolu.config.external": {
+        "default": false,
+        "markdownDescription": "Call out to an external \"fourmolu\" executable, rather than using the bundled library.",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.fourmolu.config.path": {
+        "default": "fourmolu",
+        "markdownDescription": "Set path to executable (for \"external\" mode).",
+        "scope": "resource",
+        "type": "string"
+    },
+    "haskell.plugin.gadt.globalOn": {
+        "default": true,
+        "description": "Enables gadt plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.ghcide-code-actions-bindings.globalOn": {
+        "default": true,
+        "description": "Enables ghcide-code-actions-bindings plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.ghcide-code-actions-fill-holes.globalOn": {
+        "default": true,
+        "description": "Enables ghcide-code-actions-fill-holes plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.ghcide-code-actions-imports-exports.globalOn": {
+        "default": true,
+        "description": "Enables ghcide-code-actions-imports-exports plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.ghcide-code-actions-type-signatures.globalOn": {
+        "default": true,
+        "description": "Enables ghcide-code-actions-type-signatures plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
     "haskell.plugin.ghcide-completions.config.autoExtendOn": {
         "default": true,
         "markdownDescription": "Extends the import list automatically when completing a out-of-scope identifier",
@@ -159,6 +213,24 @@
         "scope": "resource",
         "type": "boolean"
     },
+    "haskell.plugin.hlint.codeActionsOn": {
+        "default": true,
+        "description": "Enables hlint code actions",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.hlint.config.flags": {
+        "default": [],
+        "markdownDescription": "Flags used by hlint",
+        "scope": "resource",
+        "type": "array"
+    },
+    "haskell.plugin.hlint.diagnosticsOn": {
+        "default": true,
+        "description": "Enables hlint diagnostics",
+        "scope": "resource",
+        "type": "boolean"
+    },
     "haskell.plugin.importLens.codeActionsOn": {
         "default": true,
         "description": "Enables importLens code actions",
@@ -183,6 +255,12 @@
         "scope": "resource",
         "type": "boolean"
     },
+    "haskell.plugin.ormolu.config.external": {
+        "default": false,
+        "markdownDescription": "Call out to an external \"ormolu\" executable, rather than using the bundled library",
+        "scope": "resource",
+        "type": "boolean"
+    },
     "haskell.plugin.overloaded-record-dot.globalOn": {
         "default": true,
         "description": "Enables overloaded-record-dot plugin",
@@ -210,6 +288,18 @@
     "haskell.plugin.qualifyImportedNames.globalOn": {
         "default": true,
         "description": "Enables qualifyImportedNames plugin",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.rename.config.crossModule": {
+        "default": false,
+        "markdownDescription": "Enable experimental cross-module renaming",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.rename.globalOn": {
+        "default": true,
+        "description": "Enables rename plugin",
         "scope": "resource",
         "type": "boolean"
     },
diff --git a/test/testdata/schema/ghc94/default-config.golden.json b/test/testdata/schema/ghc94/default-config.golden.json
--- a/test/testdata/schema/ghc94/default-config.golden.json
+++ b/test/testdata/schema/ghc94/default-config.golden.json
@@ -39,11 +39,12 @@
             "codeLensOn": true
         },
         "eval": {
+            "codeActionsOn": true,
+            "codeLensOn": true,
             "config": {
                 "diff": true,
                 "exception": false
-            },
-            "globalOn": true
+            }
         },
         "explicit-fields": {
             "codeActionsOn": true,
diff --git a/test/testdata/schema/ghc94/vscode-extension-schema.golden.json b/test/testdata/schema/ghc94/vscode-extension-schema.golden.json
--- a/test/testdata/schema/ghc94/vscode-extension-schema.golden.json
+++ b/test/testdata/schema/ghc94/vscode-extension-schema.golden.json
@@ -77,6 +77,18 @@
         "scope": "resource",
         "type": "boolean"
     },
+    "haskell.plugin.eval.codeActionsOn": {
+        "default": true,
+        "description": "Enables eval code actions",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.eval.codeLensOn": {
+        "default": true,
+        "description": "Enables eval code lenses",
+        "scope": "resource",
+        "type": "boolean"
+    },
     "haskell.plugin.eval.config.diff": {
         "default": true,
         "markdownDescription": "Enable the diff output (WAS/NOW) of eval lenses",
@@ -86,12 +98,6 @@
     "haskell.plugin.eval.config.exception": {
         "default": false,
         "markdownDescription": "Enable marking exceptions with `*** Exception:` similarly to doctest and GHCi.",
-        "scope": "resource",
-        "type": "boolean"
-    },
-    "haskell.plugin.eval.globalOn": {
-        "default": true,
-        "description": "Enables eval plugin",
         "scope": "resource",
         "type": "boolean"
     },
diff --git a/test/testdata/schema/ghc96/default-config.golden.json b/test/testdata/schema/ghc96/default-config.golden.json
--- a/test/testdata/schema/ghc96/default-config.golden.json
+++ b/test/testdata/schema/ghc96/default-config.golden.json
@@ -39,11 +39,12 @@
             "codeLensOn": true
         },
         "eval": {
+            "codeActionsOn": true,
+            "codeLensOn": true,
             "config": {
                 "diff": true,
                 "exception": false
-            },
-            "globalOn": true
+            }
         },
         "explicit-fields": {
             "codeActionsOn": true,
diff --git a/test/testdata/schema/ghc96/vscode-extension-schema.golden.json b/test/testdata/schema/ghc96/vscode-extension-schema.golden.json
--- a/test/testdata/schema/ghc96/vscode-extension-schema.golden.json
+++ b/test/testdata/schema/ghc96/vscode-extension-schema.golden.json
@@ -77,6 +77,18 @@
         "scope": "resource",
         "type": "boolean"
     },
+    "haskell.plugin.eval.codeActionsOn": {
+        "default": true,
+        "description": "Enables eval code actions",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.eval.codeLensOn": {
+        "default": true,
+        "description": "Enables eval code lenses",
+        "scope": "resource",
+        "type": "boolean"
+    },
     "haskell.plugin.eval.config.diff": {
         "default": true,
         "markdownDescription": "Enable the diff output (WAS/NOW) of eval lenses",
@@ -86,12 +98,6 @@
     "haskell.plugin.eval.config.exception": {
         "default": false,
         "markdownDescription": "Enable marking exceptions with `*** Exception:` similarly to doctest and GHCi.",
-        "scope": "resource",
-        "type": "boolean"
-    },
-    "haskell.plugin.eval.globalOn": {
-        "default": true,
-        "description": "Enables eval plugin",
         "scope": "resource",
         "type": "boolean"
     },
diff --git a/test/testdata/schema/ghc98/default-config.golden.json b/test/testdata/schema/ghc98/default-config.golden.json
--- a/test/testdata/schema/ghc98/default-config.golden.json
+++ b/test/testdata/schema/ghc98/default-config.golden.json
@@ -39,11 +39,12 @@
             "codeLensOn": true
         },
         "eval": {
+            "codeActionsOn": true,
+            "codeLensOn": true,
             "config": {
                 "diff": true,
                 "exception": false
-            },
-            "globalOn": true
+            }
         },
         "explicit-fields": {
             "codeActionsOn": true,
diff --git a/test/testdata/schema/ghc98/vscode-extension-schema.golden.json b/test/testdata/schema/ghc98/vscode-extension-schema.golden.json
--- a/test/testdata/schema/ghc98/vscode-extension-schema.golden.json
+++ b/test/testdata/schema/ghc98/vscode-extension-schema.golden.json
@@ -77,6 +77,18 @@
         "scope": "resource",
         "type": "boolean"
     },
+    "haskell.plugin.eval.codeActionsOn": {
+        "default": true,
+        "description": "Enables eval code actions",
+        "scope": "resource",
+        "type": "boolean"
+    },
+    "haskell.plugin.eval.codeLensOn": {
+        "default": true,
+        "description": "Enables eval code lenses",
+        "scope": "resource",
+        "type": "boolean"
+    },
     "haskell.plugin.eval.config.diff": {
         "default": true,
         "markdownDescription": "Enable the diff output (WAS/NOW) of eval lenses",
@@ -86,12 +98,6 @@
     "haskell.plugin.eval.config.exception": {
         "default": false,
         "markdownDescription": "Enable marking exceptions with `*** Exception:` similarly to doctest and GHCi.",
-        "scope": "resource",
-        "type": "boolean"
-    },
-    "haskell.plugin.eval.globalOn": {
-        "default": true,
-        "description": "Enables eval plugin",
         "scope": "resource",
         "type": "boolean"
     },
diff --git a/test/testdata/wErrorTest/dist-newstyle/cache/plan.json b/test/testdata/wErrorTest/dist-newstyle/cache/plan.json
new file mode 100644
--- /dev/null
+++ b/test/testdata/wErrorTest/dist-newstyle/cache/plan.json
@@ -0,0 +1,1 @@
+{"cabal-version":"3.8.1.0","cabal-lib-version":"3.8.1.0","compiler-id":"ghc-9.2.4","os":"linux","arch":"x86_64","install-plan":[{"type":"pre-existing","id":"base-4.16.3.0","pkg-name":"base","pkg-version":"4.16.3.0","depends":["ghc-bignum-1.2","ghc-prim-0.8.0","rts"]},{"type":"pre-existing","id":"ghc-bignum-1.2","pkg-name":"ghc-bignum","pkg-version":"1.2","depends":["ghc-prim-0.8.0"]},{"type":"pre-existing","id":"ghc-prim-0.8.0","pkg-name":"ghc-prim","pkg-version":"0.8.0","depends":["rts"]},{"type":"pre-existing","id":"rts","pkg-name":"rts","pkg-version":"1.0.2","depends":[]},{"type":"configured","id":"test-0.1.0.0-inplace","pkg-name":"test","pkg-version":"0.1.0.0","flags":{},"style":"local","pkg-src":{"type":"local","path":"/home/zubin/haskell-language-server-dist/test/testdata/wErrorTest/."},"dist-dir":"/home/zubin/haskell-language-server-dist/test/testdata/wErrorTest/dist-newstyle/build/x86_64-linux/ghc-9.2.4/test-0.1.0.0","build-info":"/home/zubin/haskell-language-server-dist/test/testdata/wErrorTest/dist-newstyle/build/x86_64-linux/ghc-9.2.4/test-0.1.0.0/build-info.json","depends":["base-4.16.3.0"],"exe-depends":[],"component-name":"lib"}]}
