diff --git a/hls-refactor-plugin.cabal b/hls-refactor-plugin.cabal
--- a/hls-refactor-plugin.cabal
+++ b/hls-refactor-plugin.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               hls-refactor-plugin
-version:            2.3.0.0
+version:            2.4.0.0
 synopsis:           Exactprint refactorings for Haskell Language Server
 description:
   Please see the README on GitHub at <https://github.com/haskell/haskell-language-server#readme>
@@ -22,6 +22,11 @@
     location: https://github.com/haskell/haskell-language-server.git
 
 library
+  -- Plugins that need exactprint have not been updated for 9.8 yet
+  if impl(ghc >= 9.8)
+    buildable: False
+  else
+    buildable: True
   exposed-modules:  Development.IDE.GHC.ExactPrint
                     Development.IDE.GHC.Compat.ExactPrint
                     Development.IDE.Plugin.CodeAction
@@ -68,8 +73,8 @@
     , ghc-boot
     , regex-tdfa
     , text-rope
-    , ghcide                == 2.3.0.0
-    , hls-plugin-api        == 2.3.0.0
+    , ghcide                == 2.4.0.0
+    , hls-plugin-api        == 2.4.0.0
     , lsp
     , text
     , transformers
@@ -93,6 +98,10 @@
   default-language: Haskell2010
 
 test-suite tests
+  if impl(ghc >= 9.8)
+    buildable: False
+  else
+    buildable: True
   type:             exitcode-stdio-1.0
   default-language: Haskell2010
   hs-source-dirs:   test
@@ -103,7 +112,7 @@
     , base
     , filepath
     , hls-refactor-plugin
-    , hls-test-utils      == 2.3.0.0
+    , hls-test-utils      == 2.4.0.0
     , lens
     , lsp-types
     , text
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -528,21 +528,43 @@
       "ModuleDeclAndImports.hs"
       "ModuleDeclAndImports.expected.hs"
       "import Data.Monoid"
+  , importQualifiedTests
   ]
 
+importQualifiedTests :: TestTree
+importQualifiedTests = testGroup "import qualified prefix suggestions"
+  [ checkImport'
+      "qualified import works with 3.8 code action kinds"
+      "ImportQualified.hs"
+      "ImportQualified.expected.hs"
+      "import qualified Control.Monad as Control"
+      ["import Control.Monad (when)"]
+  , checkImport'
+      "qualified import in postfix position works with 3.8 code action kinds"
+      "ImportPostQualified.hs"
+      "ImportPostQualified.expected.hs"
+      "import Control.Monad qualified as Control"
+      ["import qualified Control.Monad as Control", "import Control.Monad (when)"]
+  ]
+
 checkImport :: String -> FilePath -> FilePath -> T.Text -> TestTree
 checkImport testComment originalPath expectedPath action =
+  checkImport' testComment originalPath expectedPath action []
+
+checkImport' :: String -> FilePath -> FilePath -> T.Text -> [T.Text] -> TestTree
+checkImport' testComment originalPath expectedPath action excludedActions =
   testSessionWithExtraFiles "import-placement" testComment $ \dir ->
     check (dir </> originalPath) (dir </> expectedPath) action
   where
     check :: FilePath -> FilePath -> T.Text -> Session ()
     check originalPath expectedPath action = do
       oSrc <- liftIO $ readFileUtf8 originalPath
-      eSrc <- liftIO $  readFileUtf8 expectedPath
+      eSrc <- liftIO $ readFileUtf8 expectedPath
       originalDoc <- createDoc originalPath "haskell" oSrc
       _ <- waitForDiagnostics
       shouldBeDoc <- createDoc expectedPath "haskell" eSrc
       actionsOrCommands <- getAllCodeActions originalDoc
+      for_ excludedActions (\a -> liftIO $ assertNoActionWithTitle a actionsOrCommands)
       chosenAction <- liftIO $ pickActionWithTitle action actionsOrCommands
       executeCodeAction chosenAction
       originalDocAfterAction <- documentContents originalDoc
@@ -3723,6 +3745,21 @@
 pickActionWithTitle title actions = do
   assertBool ("Found no matching actions for " <> show title <> " in " <> show titles) (not $ null matches)
   return $ head matches
+  where
+    titles =
+        [ actionTitle
+        | InR CodeAction { _title = actionTitle } <- actions
+        ]
+    matches =
+        [ action
+        | InR action@CodeAction { _title = actionTitle } <- actions
+        , title == actionTitle
+        ]
+
+assertNoActionWithTitle :: T.Text -> [Command |? CodeAction] -> IO ()
+assertNoActionWithTitle title actions = do
+  assertBool ("Unexpected code action " <> show title <> " in " <> show titles) (null matches)
+  pure ()
   where
     titles =
         [ actionTitle
diff --git a/test/data/import-placement/ImportPostQualified.expected.hs b/test/data/import-placement/ImportPostQualified.expected.hs
new file mode 100644
--- /dev/null
+++ b/test/data/import-placement/ImportPostQualified.expected.hs
@@ -0,0 +1,5 @@
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# OPTIONS_GHC -Wprepositive-qualified-module #-}
+import Control.Monad qualified as Control
+main :: IO ()
+main = Control.when True $ putStrLn "hello"
diff --git a/test/data/import-placement/ImportPostQualified.hs b/test/data/import-placement/ImportPostQualified.hs
new file mode 100644
--- /dev/null
+++ b/test/data/import-placement/ImportPostQualified.hs
@@ -0,0 +1,4 @@
+{-# LANGUAGE ImportQualifiedPost #-}
+{-# OPTIONS_GHC -Wprepositive-qualified-module #-}
+main :: IO ()
+main = Control.when True $ putStrLn "hello"
diff --git a/test/data/import-placement/ImportQualified.expected.hs b/test/data/import-placement/ImportQualified.expected.hs
new file mode 100644
--- /dev/null
+++ b/test/data/import-placement/ImportQualified.expected.hs
@@ -0,0 +1,3 @@
+import qualified Control.Monad as Control
+main :: IO ()
+main = Control.when True $ putStrLn "hello"
diff --git a/test/data/import-placement/ImportQualified.hs b/test/data/import-placement/ImportQualified.hs
new file mode 100644
--- /dev/null
+++ b/test/data/import-placement/ImportQualified.hs
@@ -0,0 +1,2 @@
+main :: IO ()
+main = Control.when True $ putStrLn "hello"
