Skip to content

Commit 20e1274

Browse files
committed
refactor: rewrite where bindings sig as Rules
1 parent 96417e0 commit 20e1274

File tree

1 file changed

+63
-39
lines changed

1 file changed

+63
-39
lines changed

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

Lines changed: 63 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ import Data.Generics (GenericQ, everything,
2727
mkQ, something)
2828
import Data.List (find)
2929
import qualified Data.Map as Map
30-
import Data.Maybe (catMaybes, mapMaybe,
31-
maybeToList)
30+
import Data.Maybe (catMaybes, fromMaybe,
31+
mapMaybe, maybeToList)
3232
import qualified Data.Text as T
3333
import Development.IDE (GhcSession (..),
3434
HscEnvEq (hscEnv),
@@ -107,7 +107,7 @@ descriptor recorder plId =
107107
<> mkResolveHandler SMethod_CodeLensResolve codeLensResolveProvider
108108
<> mkPluginHandler SMethod_TextDocumentInlayHint whereClauseInlayHints
109109
, pluginCommands = [PluginCommand typeLensCommandId "adds a signature" commandHandler]
110-
, pluginRules = rules recorder
110+
, pluginRules = globalBindingRules recorder *> whereBindingRules recorder
111111
, pluginConfigDescriptor = defaultConfigDescriptor {configCustomConfig = mkCustomConfig properties}
112112
}
113113
where
@@ -306,15 +306,15 @@ gbSrcSpan GlobalBindingTypeSig{gbName} = getSrcSpan gbName
306306
newtype GlobalBindingTypeSigsResult = GlobalBindingTypeSigsResult [GlobalBindingTypeSig]
307307

308308
instance Show GlobalBindingTypeSigsResult where
309-
show _ = "<GetTypeResult>"
309+
show _ = "<GetTypeResult.global>"
310310

311311
instance NFData GlobalBindingTypeSigsResult where
312312
rnf = rwhnf
313313

314314
type instance RuleResult GetGlobalBindingTypeSigs = GlobalBindingTypeSigsResult
315315

316-
rules :: Recorder (WithPriority Log) -> Rules ()
317-
rules recorder = do
316+
globalBindingRules :: Recorder (WithPriority Log) -> Rules ()
317+
globalBindingRules recorder = do
318318
define (cmapWithPrio LogShake recorder) $ \GetGlobalBindingTypeSigs nfp -> do
319319
tmr <- use TypeCheck nfp
320320
-- we need session here for tidying types
@@ -323,8 +323,8 @@ rules recorder = do
323323
pure ([], result)
324324

325325
-- | Convert a given haskell bind to its corresponding type signature.
326-
bindToSig :: Id -> HscEnv -> GlobalRdrEnv -> IOEnv (Env TcGblEnv TcLclEnv) String
327-
bindToSig id hsc rdrEnv = do
326+
bindToSig :: HscEnv -> GlobalRdrEnv -> Id -> IOEnv (Env TcGblEnv TcLclEnv) String
327+
bindToSig hsc rdrEnv id = do
328328
env <-
329329
#if MIN_VERSION_ghc(9,7,0)
330330
liftZonkM
@@ -346,7 +346,7 @@ gblBindingType (Just hsc) (Just gblEnv) = do
346346
let name = idName id
347347
hasSig name $ do
348348
-- convert from bind id to its signature
349-
sig <- bindToSig id hsc rdrEnv
349+
sig <- bindToSig hsc rdrEnv id
350350
pure $ GlobalBindingTypeSig name (printName name <> " :: " <> sig) (name `elemNameSet` exports)
351351
patToSig p = do
352352
let name = patSynName p
@@ -409,6 +409,42 @@ data WhereBindings = WhereBindings
409409
-- the definition of `f`(second line).
410410
}
411411

412+
data GetWhereBindingTypeSigs = GetWhereBindingTypeSigs
413+
deriving (Generic, Show, Eq, Ord, Hashable, NFData)
414+
415+
type BindingSigMap = Map.Map Id String
416+
417+
newtype WhereBindingTypeSigsResult = WhereBindingTypeSigsResult ([WhereBindings], BindingSigMap)
418+
419+
instance Show WhereBindingTypeSigsResult where
420+
show _ = "<GetTypeResult.where>"
421+
422+
instance NFData WhereBindingTypeSigsResult where
423+
rnf = rwhnf
424+
425+
type instance RuleResult GetWhereBindingTypeSigs = WhereBindingTypeSigsResult
426+
427+
whereBindingRules :: Recorder (WithPriority Log) -> Rules ()
428+
whereBindingRules recorder = do
429+
define (cmapWithPrio LogShake recorder) $ \GetWhereBindingTypeSigs nfp -> do
430+
tmr <- use TypeCheck nfp
431+
-- we need session here for tidying types
432+
hsc <- use GhcSession nfp
433+
result <- liftIO $ whereBindingType (tmrTypechecked <$> tmr) (hscEnv <$> hsc)
434+
pure ([], result)
435+
436+
whereBindingType :: Maybe TcGblEnv -> Maybe HscEnv -> IO (Maybe WhereBindingTypeSigsResult)
437+
whereBindingType (Just gblEnv) (Just hsc) = do
438+
let wheres = findWhereQ (tcg_binds gblEnv)
439+
localBindings = mapMaybe findBindingsQ wheres
440+
bindToSig' = bindToSig hsc (tcg_rdr_env gblEnv)
441+
findSigs (WhereBindings bindings _) = fmap findSig bindings
442+
where findSig (WhereBinding bindingId _ _) = sequence (bindingId, bindToSig' bindingId)
443+
(_, Map.fromList . fromMaybe [] -> sigMap) <-
444+
initTcWithGbl hsc gblEnv ghostSpan $ sequence $ concatMap findSigs localBindings
445+
pure $ Just (WhereBindingTypeSigsResult (localBindings, sigMap))
446+
whereBindingType _ _ = pure Nothing
447+
412448
-- | All where clauses from type checked source.
413449
findWhereQ :: GenericQ [HsLocalBinds GhcTc]
414450
findWhereQ = everything (<>) $ mkQ [] (pure . findWhere)
@@ -455,42 +491,30 @@ whereClauseInlayHints state plId (InlayHintParams _ (TextDocumentIdentifier uri)
455491
enabled <- liftIO $ runAction "inlayHint.config" state $ usePropertyAction #whereInlayHintOn plId properties
456492
if not enabled then pure $ InL [] else do
457493
nfp <- getNormalizedFilePathE uri
458-
(tmr, _) <- runActionE "inlayHint.local.TypeCheck" state $ useWithStaleE TypeCheck nfp
459-
(hscEnv -> hsc, _) <- runActionE "InlayHint.local.GhcSession" state $ useWithStaleE GhcSession nfp
460-
let tcGblEnv = tmrTypechecked tmr
461-
rdrEnv = tcg_rdr_env tcGblEnv
462-
typeCheckedSource = tcg_binds tcGblEnv
463-
464-
wheres = findWhereQ typeCheckedSource
465-
localBindings = mapMaybe findBindingsQ wheres
494+
(WhereBindingTypeSigsResult (localBindings, sigMap), pm)
495+
<- runActionE "InlayHint.GetWhereBindingTypeSigs" state $ useWithStaleE GetWhereBindingTypeSigs nfp
496+
let bindingToInlayHints id sig = generateWhereInlayHints (T.pack $ printName (idName id)) (maybe "_" T.pack sig)
466497

467498
-- | Note there may multi ids for one binding,
468499
-- like @(a, b) = (42, True)@, there are `a` and `b`
469500
-- in one binding.
470-
bindingToInlayHints id range offset = do
471-
(_, sig) <- liftIO
472-
$ initTcWithGbl hsc tcGblEnv ghostSpan
473-
$ bindToSig id hsc rdrEnv
474-
let name = idName id
475-
pure $ generateWhereInlayHints range (T.pack $ printName name) (maybe "_" T.pack sig) offset
476-
477-
inlayHints <- sequence
478-
[ bindingToInlayHints bindingId bindingRange offset
479-
| WhereBindings{..} <- localBindings
480-
, let sigSpans = getSrcSpan <$> existingSigNames
481-
, WhereBinding{..} <- bindings
482-
, let bindingSpan = getSrcSpan (idName bindingId)
483-
, bindingSpan `notElem` sigSpans
484-
-- , Just bindingRange <- maybeToList $ toCurrentRange pm <$> srcSpanToRange bindingLoc
485-
, Just bindingRange <- [srcSpanToRange bindingLoc]
486-
-- Show inlay hints only within visible range
487-
, isSubrangeOf bindingRange visibleRange
488-
]
489-
501+
inlayHints =
502+
[ bindingToInlayHints bindingId bindingSig bindingRange offset
503+
| WhereBindings{..} <- localBindings
504+
, let sigSpans = getSrcSpan <$> existingSigNames
505+
, WhereBinding{..} <- bindings
506+
, let bindingSpan = getSrcSpan (idName bindingId)
507+
, let bindingSig = Map.lookup bindingId sigMap
508+
, bindingSpan `notElem` sigSpans
509+
, Just bindingRange <- maybeToList $ toCurrentRange pm <$> srcSpanToRange bindingLoc
510+
-- , Just bindingRange <- [srcSpanToRange bindingLoc]
511+
-- Show inlay hints only within visible range
512+
, isSubrangeOf bindingRange visibleRange
513+
]
490514
pure $ InL inlayHints
491515
where
492-
generateWhereInlayHints :: Range -> T.Text -> T.Text -> Int -> InlayHint
493-
generateWhereInlayHints range name ty offset =
516+
generateWhereInlayHints :: T.Text -> T.Text -> Range -> Int -> InlayHint
517+
generateWhereInlayHints name ty range offset =
494518
let edit = makeEdit range (name <> " :: " <> ty) offset
495519
in InlayHint { _textEdits = Just [edit]
496520
, _paddingRight = Nothing

0 commit comments

Comments
 (0)