From f53faf87340f900efa5b4d0649e313a16b0f2e76 Mon Sep 17 00:00:00 2001 From: Jacek Generowicz Date: Fri, 13 Sep 2019 01:08:57 +0200 Subject: [PATCH] Add code action for GHC's suggestions for not-found module --- src/Development/IDE/LSP/CodeAction.hs | 10 ++++++++++ test/exe/Main.hs | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/Development/IDE/LSP/CodeAction.hs b/src/Development/IDE/LSP/CodeAction.hs index 3430deb9..e9d58f20 100644 --- a/src/Development/IDE/LSP/CodeAction.hs +++ b/src/Development/IDE/LSP/CodeAction.hs @@ -20,6 +20,7 @@ import Language.Haskell.LSP.Messages import qualified Data.Rope.UTF16 as Rope import Data.Char import Data.Maybe +import Data.List import qualified Data.Text as T -- | Generate code actions. @@ -97,6 +98,15 @@ suggestAction contents Diagnostic{_range=_range@Range{..},..} | exts@(_:_) <- filter (`Set.member` ghcExtensions) $ T.split (not . isAlpha) $ T.replace "-X" "" _message = [("Add " <> x <> " extension", [TextEdit (Range (Position 0 0) (Position 0 0)) $ "{-# LANGUAGE " <> x <> " #-}\n"]) | x <- exts] +-- src/Development/IDE/Core/Compile.hs:58:1: error: +-- Could not find module ‘Data.Cha’ +-- Perhaps you meant Data.Char (from base-4.12.0.0) + | "Could not find module" `T.isInfixOf` _message + , "Perhaps you meant" `T.isInfixOf` _message + = map proposeModule $ nub $ findSuggestedModules _message where + findSuggestedModules = (map (head . T.words) . drop 2 . T.lines) + proposeModule mod = ("replace with " <> mod, [TextEdit _range mod]) + suggestAction _ _ = [] mkRenameEdit :: Maybe T.Text -> Range -> T.Text -> TextEdit diff --git a/test/exe/Main.hs b/test/exe/Main.hs index 2376dad3..041ee5b2 100644 --- a/test/exe/Main.hs +++ b/test/exe/Main.hs @@ -213,6 +213,7 @@ codeActionTests = testGroup "code actions" [ renameActionTests , typeWildCardActionTests , removeImportTests + , importRenameActionTests ] renameActionTests :: TestTree @@ -413,6 +414,27 @@ removeImportTests = testGroup "remove import actions" liftIO $ expectedContentAfterAction @=? contentAfterAction ] +importRenameActionTests :: TestTree +importRenameActionTests = testGroup "import rename actions" + [ testSession "Data.Mape -> Data.Map" $ check "Map" + , testSession "Data.Mape -> Data.Maybe" $ check "Maybe" ] where + check modname = do + let content = T.unlines + [ "module Testing where" + , "import Data.Mape" + ] + doc <- openDoc' "Testing.hs" "haskell" content + _ <- waitForDiagnostics + actionsOrCommands <- getCodeActions doc (Range (Position 2 8) (Position 2 16)) + let [changeToMap] = [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, ("Data." <> modname) `T.isInfixOf` actionTitle ] + executeCodeAction changeToMap + contentAfterAction <- documentContents doc + let expectedContentAfterAction = T.unlines + [ "module Testing where" + , "import Data." <> modname + ] + liftIO $ expectedContentAfterAction @=? contentAfterAction + ---------------------------------------------------------------------- -- Utils