diff --git a/ghcide/src/Development/IDE/Plugin/CodeAction.hs b/ghcide/src/Development/IDE/Plugin/CodeAction.hs index 59c49bc740..c68a6b5ab0 100644 --- a/ghcide/src/Development/IDE/Plugin/CodeAction.hs +++ b/ghcide/src/Development/IDE/Plugin/CodeAction.hs @@ -678,15 +678,21 @@ suggestFillHole :: Diagnostic -> [(T.Text, TextEdit)] suggestFillHole Diagnostic{_range=_range,..} | Just holeName <- extractHoleName _message , (holeFits, refFits) <- processHoleSuggestions (T.lines _message) - = map (proposeHoleFit holeName False) holeFits - ++ map (proposeHoleFit holeName True) refFits + = let hasInfixBackquote = checkInfixBackquote holeName _message in + map (proposeHoleFit holeName False hasInfixBackquote) holeFits + ++ map (proposeHoleFit holeName True hasInfixBackquote) refFits | otherwise = [] where extractHoleName = fmap head . flip matchRegexUnifySpaces "Found hole: ([^ ]*)" - proposeHoleFit holeName parenthise name = + checkInfixBackquote holeName message = message =~ T.concat [T.singleton '`', holeName, T.singleton '`'] :: Bool + proposeHoleFit holeName parenthise hasInfixBackquote name = ( "replace " <> holeName <> " with " <> name - , TextEdit _range $ if parenthise then parens name else name) + , TextEdit (if hasInfixBackquote then fixInfixBackquoteRange _range else _range) + (if parenthise then parens name else name) + ) parens x = "(" <> x <> ")" + fixInfixBackquoteRange (Range (Position x1 y1) (Position x2 y2)) = + Range (Position x1 (y1 + 1)) (Position x2 (y2 - 1)) processHoleSuggestions :: [T.Text] -> ([T.Text], [T.Text]) processHoleSuggestions mm = (holeSuggestions, refSuggestions) diff --git a/ghcide/test/exe/Main.hs b/ghcide/test/exe/Main.hs index e02f13c709..4bddbb7a5b 100644 --- a/ghcide/test/exe/Main.hs +++ b/ghcide/test/exe/Main.hs @@ -2386,6 +2386,22 @@ fillTypedHoleTests = let executeCodeAction chosen modifiedCode <- documentContents doc liftIO $ mkDoc "E.toException" @=? modifiedCode + , testSession "fill hole with infix backquote keeps" $ do + let mkDoc x = T.unlines + [ "module Testing where" + , "data A = A" + , "foo :: A -> A -> A" + , "foo A A = A" + , "test :: A -> A -> A" + , "test a1 a2 = a1 `" <> x <> "` a2" + ] + doc <- createDoc "Test.hs" "haskell" $ mkDoc "_" + _ <- waitForDiagnostics + actions <- getCodeActions doc (Range (Position 5 16) (Position 5 19)) + chosen <- liftIO $ pickActionWithTitle "replace _ with foo" actions + executeCodeAction chosen + modifiedCode <- documentContents doc + liftIO $ mkDoc "foo" @=? modifiedCode ] addInstanceConstraintTests :: TestTree