Skip to content

Commit 016ccde

Browse files
authored
Update Define Function Code Action to have knowledge of comments (#2740)
* Fix defining new function code action Use `GetParsedModuleWithComments` rather than `GetParsedModule` as the default `ToCodeAction` instance. The insertion code needs knowledge of comments in order to properly insert the function definition. Also swaps out the old default `error "Not Implemented"` definition with a hole. * Revert whitespace
1 parent 0c018ac commit 016ccde

File tree

3 files changed

+76
-17
lines changed

3 files changed

+76
-17
lines changed

ghcide/src/Development/IDE/Plugin/CodeAction.hs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -711,15 +711,14 @@ newDefinitionAction IdeOptions{..} parsedModule Range{_start} name typ
711711
, _start `isInsideSrcSpan` l]
712712
, nextLineP <- Position{ _line = _line lastLineP + 1, _character = 0}
713713
= [ ("Define " <> sig
714-
, [TextEdit (Range nextLineP nextLineP) (T.unlines ["", sig, name <> " = error \"not implemented\""])]
714+
, [TextEdit (Range nextLineP nextLineP) (T.unlines ["", sig, name <> " = _"])]
715715
)]
716716
| otherwise = []
717717
where
718718
colon = if optNewColonConvention then " : " else " :: "
719719
sig = name <> colon <> T.dropWhileEnd isSpace typ
720720
ParsedModule{pm_parsed_source = L _ HsModule{hsmodDecls}} = parsedModule
721721

722-
723722
suggestFillTypeWildcard :: Diagnostic -> [(T.Text, TextEdit)]
724723
suggestFillTypeWildcard Diagnostic{_range=_range,..}
725724
-- Foo.hs:3:8: error:

ghcide/src/Development/IDE/Plugin/CodeAction/Args.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ runGhcideCodeAction state (CodeActionParams _ _ (TextDocumentIdentifier uri) _ra
6565
pure $ localExports <> pkgExports
6666
_ -> pure mempty
6767
caaIdeOptions <- onceIO $ runAction "GhcideCodeActions.getIdeOptions" state getIdeOptions
68-
caaParsedModule <- onceIO $ runRule GetParsedModule
68+
caaParsedModule <- onceIO $ runRule GetParsedModuleWithComments
6969
caaContents <-
7070
onceIO $
7171
runRule GetFileContents >>= \case

ghcide/test/exe/Main.hs

Lines changed: 74 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ import Development.IDE.Test (Cursor,
5555
flushMessages,
5656
getInterfaceFilesDir,
5757
getStoredKeys,
58+
isReferenceReady,
59+
referenceReady,
5860
standardizeQuotes,
5961
waitForAction,
6062
waitForGC,
61-
waitForTypecheck,
62-
isReferenceReady,
63-
referenceReady)
63+
waitForTypecheck)
6464
import Development.IDE.Test.Runfiles
6565
import qualified Development.IDE.Types.Diagnostics as Diagnostics
6666
import Development.IDE.Types.Location
@@ -97,6 +97,7 @@ import Test.QuickCheck
9797
import Control.Concurrent.Async
9898
import Control.Lens (to, (^.))
9999
import Control.Monad.Extra (whenJust)
100+
import Data.Function ((&))
100101
import Data.IORef
101102
import Data.IORef.Extra (atomicModifyIORef_)
102103
import Data.String (IsString (fromString))
@@ -107,6 +108,18 @@ import qualified Development.IDE.Plugin.HLS.GhcIde as Ghcide
107108
import Development.IDE.Plugin.Test (TestRequest (BlockSeconds),
108109
WaitForIdeRuleResult (..),
109110
blockCommandId)
111+
import Development.IDE.Types.Logger (Logger (Logger),
112+
LoggingColumn (DataColumn, PriorityColumn),
113+
Pretty (pretty),
114+
Priority (Debug),
115+
Recorder (Recorder, logger_),
116+
WithPriority (WithPriority, priority),
117+
cfilter,
118+
cmapWithPrio,
119+
makeDefaultStderrRecorder)
120+
import qualified FuzzySearch
121+
import GHC.Stack (emptyCallStack)
122+
import qualified HieDbRetry
110123
import Ide.PluginUtils (pluginDescToIdePlugins)
111124
import Ide.Types
112125
import qualified Language.LSP.Types as LSP
@@ -120,19 +133,14 @@ import Test.Tasty.Ingredients.Rerun
120133
import Test.Tasty.QuickCheck
121134
import Text.Printf (printf)
122135
import Text.Regex.TDFA ((=~))
123-
import qualified HieDbRetry
124-
import Development.IDE.Types.Logger (WithPriority(WithPriority, priority), Priority (Debug), cmapWithPrio, Recorder (Recorder, logger_), makeDefaultStderrRecorder, cfilter, LoggingColumn (PriorityColumn, DataColumn), Logger (Logger), Pretty (pretty))
125-
import Data.Function ((&))
126-
import GHC.Stack (emptyCallStack)
127-
import qualified FuzzySearch
128136

129-
data Log
130-
= LogGhcIde Ghcide.Log
137+
data Log
138+
= LogGhcIde Ghcide.Log
131139
| LogIDEMain IDE.Log
132140

133141
instance Pretty Log where
134142
pretty = \case
135-
LogGhcIde log -> pretty log
143+
LogGhcIde log -> pretty log
136144
LogIDEMain log -> pretty log
137145

138146
-- | Wait for the next progress begin step
@@ -2411,7 +2419,7 @@ insertNewDefinitionTests = testGroup "insert new definition actions"
24112419
liftIO $ contentAfterAction @?= T.unlines (txtB ++
24122420
[ ""
24132421
, "select :: [Bool] -> Bool"
2414-
, "select = error \"not implemented\""
2422+
, "select = _"
24152423
]
24162424
++ txtB')
24172425
, testSession "define a hole" $ do
@@ -2438,9 +2446,61 @@ insertNewDefinitionTests = testGroup "insert new definition actions"
24382446
,"foo False = False"
24392447
, ""
24402448
, "select :: [Bool] -> Bool"
2441-
, "select = error \"not implemented\""
2449+
, "select = _"
24422450
]
24432451
++ txtB')
2452+
, testSession "insert new function definition - Haddock comments" $ do
2453+
let start = ["foo :: Int -> Bool"
2454+
, "foo x = select (x + 1)"
2455+
, ""
2456+
, "-- | This is a haddock comment"
2457+
, "haddock :: Int -> Int"
2458+
, "haddock = undefined"
2459+
]
2460+
let expected = ["foo :: Int -> Bool"
2461+
, "foo x = select (x + 1)"
2462+
, ""
2463+
, "select :: Int -> Bool"
2464+
, "select = _"
2465+
, ""
2466+
, "-- | This is a haddock comment"
2467+
, "haddock :: Int -> Int"
2468+
, "haddock = undefined"]
2469+
docB <- createDoc "ModuleB.hs" "haskell" (T.unlines start)
2470+
_ <- waitForDiagnostics
2471+
InR action@CodeAction { _title = actionTitle } : _
2472+
<- sortOn (\(InR CodeAction{_title=x}) -> x) <$>
2473+
getCodeActions docB (R 1 0 0 50)
2474+
liftIO $ actionTitle @?= "Define select :: Int -> Bool"
2475+
executeCodeAction action
2476+
contentAfterAction <- documentContents docB
2477+
liftIO $ contentAfterAction @?= T.unlines expected
2478+
, testSession "insert new function definition - normal comments" $ do
2479+
let start = ["foo :: Int -> Bool"
2480+
, "foo x = select (x + 1)"
2481+
, ""
2482+
, "-- This is a normal comment"
2483+
, "normal :: Int -> Int"
2484+
, "normal = undefined"
2485+
]
2486+
let expected = ["foo :: Int -> Bool"
2487+
, "foo x = select (x + 1)"
2488+
, ""
2489+
, "select :: Int -> Bool"
2490+
, "select = _"
2491+
, ""
2492+
, "-- This is a normal comment"
2493+
, "normal :: Int -> Int"
2494+
, "normal = undefined"]
2495+
docB <- createDoc "ModuleB.hs" "haskell" (T.unlines start)
2496+
_ <- waitForDiagnostics
2497+
InR action@CodeAction { _title = actionTitle } : _
2498+
<- sortOn (\(InR CodeAction{_title=x}) -> x) <$>
2499+
getCodeActions docB (R 1 0 0 50)
2500+
liftIO $ actionTitle @?= "Define select :: Int -> Bool"
2501+
executeCodeAction action
2502+
contentAfterAction <- documentContents docB
2503+
liftIO $ contentAfterAction @?= T.unlines expected
24442504
]
24452505

24462506

@@ -5613,7 +5673,7 @@ bootTests = testGroup "boot"
56135673
hoverResponseOrReadyMessage <- skipManyTill anyMessage ((Left <$> parseHoverResponse) <|> (Right <$> parseReadyMessage))
56145674
_ <- skipManyTill anyMessage $
56155675
case hoverResponseOrReadyMessage of
5616-
Left _ -> void parseReadyMessage
5676+
Left _ -> void parseReadyMessage
56175677
Right _ -> void parseHoverResponse
56185678
closeDoc cDoc
56195679
cdoc <- createDoc cPath "haskell" cSource

0 commit comments

Comments
 (0)