Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve action for fixing import typo #2522

Merged
merged 2 commits into from
Dec 22, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions ghcide/src/Development/IDE/Plugin/CodeAction.hs
Original file line number Diff line number Diff line change
Expand Up @@ -700,17 +700,33 @@ suggestFillTypeWildcard Diagnostic{_range=_range,..}
= [("Use type signature: ‘" <> typeSignature <> "’", TextEdit _range typeSignature)]
| otherwise = []

{- Handles two variants with different formatting

1. Could not find module ‘Data.Cha’
Perhaps you meant Data.Char (from base-4.12.0.0)

2. Could not find module ‘Data.I’
Perhaps you meant
Data.Ix (from base-4.14.3.0)
Data.Eq (from base-4.14.3.0)
Data.Int (from base-4.14.3.0)
-}
suggestModuleTypo :: Diagnostic -> [(T.Text, TextEdit)]
suggestModuleTypo Diagnostic{_range=_range,..}
-- 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 = let
findSuggestedModules = map (head . T.words) . drop 2 . T.lines
proposeModule mod = ("replace with " <> mod, TextEdit _range mod)
in map proposeModule $ nubOrd $ findSuggestedModules _message
, "Perhaps you meant" `T.isInfixOf` _message =
case T.splitOn "Perhaps you meant" _message of
jhrcek marked this conversation as resolved.
Show resolved Hide resolved
[_, stuff] ->
[ ("replace with " <> modul, TextEdit _range modul)
| modul <- mapMaybe extractModule (T.lines stuff)
]
_ -> []
| otherwise = []
where
extractModule line = case T.words line of
[modul, "(from", _] -> Just modul
_ -> Nothing


suggestFillHole :: Diagnostic -> [(T.Text, TextEdit)]
suggestFillHole Diagnostic{_range=_range,..}
Expand Down
26 changes: 26 additions & 0 deletions ghcide/test/exe/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,7 @@ codeActionTests = testGroup "code actions"
, suggestHideShadowTests
, suggestImportDisambiguationTests
, fixConstructorImportTests
, fixModuleImportTypoTests
, importRenameActionTests
, fillTypedHoleTests
, addSigActionTests
Expand Down Expand Up @@ -1804,6 +1805,31 @@ extendImportTests = testGroup "extend import actions"
contentAfterAction <- documentContents docB
liftIO $ expectedContentB @=? contentAfterAction

fixModuleImportTypoTests :: TestTree
fixModuleImportTypoTests = testGroup "fix module import typo"
[ testSession "works when single module suggested" $ do
doc <- createDoc "A.hs" "haskell" "import Data.Cha"
_ <- waitForDiagnostics
InR action@CodeAction { _title = actionTitle } : _ <- getCodeActions doc (R 0 0 0 10)
liftIO $ actionTitle @?= "replace with Data.Char"
executeCodeAction action
contentAfterAction <- documentContents doc
liftIO $ contentAfterAction @?= "import Data.Char"
, testSession "works when multiple modules suggested" $ do
doc <- createDoc "A.hs" "haskell" "import Data.I"
_ <- waitForDiagnostics
actions <- sortOn (\(InR CodeAction{_title=x}) -> x) <$> getCodeActions doc (R 0 0 0 10)
let actionTitles = [ title | InR CodeAction{_title=title} <- actions ]
liftIO $ actionTitles @?= [ "replace with Data.Eq"
, "replace with Data.Int"
, "replace with Data.Ix"
]
let InR replaceWithDataEq : _ = actions
executeCodeAction replaceWithDataEq
contentAfterAction <- documentContents doc
liftIO $ contentAfterAction @?= "import Data.Eq"
]

extendImportTestsRegEx :: TestTree
extendImportTestsRegEx = testGroup "regex parsing"
[
Expand Down