@@ -27,8 +27,8 @@ import Data.Generics (GenericQ, everything,
2727 mkQ , something )
2828import Data.List (find )
2929import qualified Data.Map as Map
30- import Data.Maybe (catMaybes , mapMaybe ,
31- maybeToList )
30+ import Data.Maybe (catMaybes , fromMaybe ,
31+ mapMaybe , maybeToList )
3232import qualified Data.Text as T
3333import 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
306306newtype GlobalBindingTypeSigsResult = GlobalBindingTypeSigsResult [GlobalBindingTypeSig ]
307307
308308instance Show GlobalBindingTypeSigsResult where
309- show _ = " <GetTypeResult>"
309+ show _ = " <GetTypeResult.global >"
310310
311311instance NFData GlobalBindingTypeSigsResult where
312312 rnf = rwhnf
313313
314314type 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.
413449findWhereQ :: GenericQ [HsLocalBinds GhcTc ]
414450findWhereQ = 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