@@ -27,8 +27,8 @@ import Data.Generics (GenericQ, everything,
27
27
mkQ , something )
28
28
import Data.List (find )
29
29
import qualified Data.Map as Map
30
- import Data.Maybe (catMaybes , mapMaybe ,
31
- maybeToList )
30
+ import Data.Maybe (catMaybes , fromMaybe ,
31
+ mapMaybe , maybeToList )
32
32
import qualified Data.Text as T
33
33
import Development.IDE (GhcSession (.. ),
34
34
HscEnvEq (hscEnv ),
@@ -107,7 +107,7 @@ descriptor recorder plId =
107
107
<> mkResolveHandler SMethod_CodeLensResolve codeLensResolveProvider
108
108
<> mkPluginHandler SMethod_TextDocumentInlayHint whereClauseInlayHints
109
109
, pluginCommands = [PluginCommand typeLensCommandId " adds a signature" commandHandler]
110
- , pluginRules = rules recorder
110
+ , pluginRules = globalBindingRules recorder *> whereBindingRules recorder
111
111
, pluginConfigDescriptor = defaultConfigDescriptor {configCustomConfig = mkCustomConfig properties}
112
112
}
113
113
where
@@ -306,15 +306,15 @@ gbSrcSpan GlobalBindingTypeSig{gbName} = getSrcSpan gbName
306
306
newtype GlobalBindingTypeSigsResult = GlobalBindingTypeSigsResult [GlobalBindingTypeSig ]
307
307
308
308
instance Show GlobalBindingTypeSigsResult where
309
- show _ = " <GetTypeResult>"
309
+ show _ = " <GetTypeResult.global >"
310
310
311
311
instance NFData GlobalBindingTypeSigsResult where
312
312
rnf = rwhnf
313
313
314
314
type instance RuleResult GetGlobalBindingTypeSigs = GlobalBindingTypeSigsResult
315
315
316
- rules :: Recorder (WithPriority Log ) -> Rules ()
317
- rules recorder = do
316
+ globalBindingRules :: Recorder (WithPriority Log ) -> Rules ()
317
+ globalBindingRules recorder = do
318
318
define (cmapWithPrio LogShake recorder) $ \ GetGlobalBindingTypeSigs nfp -> do
319
319
tmr <- use TypeCheck nfp
320
320
-- we need session here for tidying types
@@ -323,8 +323,8 @@ rules recorder = do
323
323
pure ([] , result)
324
324
325
325
-- | 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
328
328
env <-
329
329
#if MIN_VERSION_ghc(9,7,0)
330
330
liftZonkM
@@ -346,7 +346,7 @@ gblBindingType (Just hsc) (Just gblEnv) = do
346
346
let name = idName id
347
347
hasSig name $ do
348
348
-- convert from bind id to its signature
349
- sig <- bindToSig id hsc rdrEnv
349
+ sig <- bindToSig hsc rdrEnv id
350
350
pure $ GlobalBindingTypeSig name (printName name <> " :: " <> sig) (name `elemNameSet` exports)
351
351
patToSig p = do
352
352
let name = patSynName p
@@ -409,6 +409,42 @@ data WhereBindings = WhereBindings
409
409
-- the definition of `f`(second line).
410
410
}
411
411
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
+
412
448
-- | All where clauses from type checked source.
413
449
findWhereQ :: GenericQ [HsLocalBinds GhcTc ]
414
450
findWhereQ = everything (<>) $ mkQ [] (pure . findWhere)
@@ -455,42 +491,30 @@ whereClauseInlayHints state plId (InlayHintParams _ (TextDocumentIdentifier uri)
455
491
enabled <- liftIO $ runAction " inlayHint.config" state $ usePropertyAction # whereInlayHintOn plId properties
456
492
if not enabled then pure $ InL [] else do
457
493
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)
466
497
467
498
-- | Note there may multi ids for one binding,
468
499
-- like @(a, b) = (42, True)@, there are `a` and `b`
469
500
-- 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
+ ]
490
514
pure $ InL inlayHints
491
515
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 =
494
518
let edit = makeEdit range (name <> " :: " <> ty) offset
495
519
in InlayHint { _textEdits = Just [edit]
496
520
, _paddingRight = Nothing
0 commit comments