@@ -24,7 +24,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
24
24
import Data.Aeson.Types (toJSON )
25
25
import qualified Data.Aeson.Types as A
26
26
import Data.Generics (GenericQ , everything ,
27
- mkQ , something )
27
+ extQ , mkQ , something )
28
28
import Data.List (find )
29
29
import qualified Data.Map as Map
30
30
import Data.Maybe (catMaybes , fromMaybe ,
@@ -105,25 +105,25 @@ descriptor recorder plId =
105
105
(defaultPluginDescriptor plId desc)
106
106
{ pluginHandlers = mkPluginHandler SMethod_TextDocumentCodeLens codeLensProvider
107
107
<> mkResolveHandler SMethod_CodeLensResolve codeLensResolveProvider
108
- <> mkPluginHandler SMethod_TextDocumentInlayHint whereClauseInlayHints
108
+ <> mkPluginHandler SMethod_TextDocumentInlayHint localBindingInlayHints
109
109
, pluginCommands = [PluginCommand typeLensCommandId " adds a signature" commandHandler]
110
- , pluginRules = globalBindingRules recorder *> whereBindingRules recorder
110
+ , pluginRules = globalBindingRules recorder *> localBindingRules recorder
111
111
, pluginConfigDescriptor = defaultConfigDescriptor {configCustomConfig = mkCustomConfig properties}
112
112
}
113
113
where
114
114
desc = " Provides code lenses type signatures"
115
115
116
116
properties :: Properties
117
- '[ 'PropertyKey " whereInlayHintOn " 'TBoolean,
117
+ '[ 'PropertyKey " localBindingInlayHintOn " 'TBoolean,
118
118
'PropertyKey " mode" ('TEnum Mode )]
119
119
properties = emptyProperties
120
120
& defineEnumProperty # mode " Control how type lenses are shown"
121
121
[ (Always , " Always displays type lenses of global bindings" )
122
122
, (Exported , " Only display type lenses of exported global bindings" )
123
123
, (Diagnostics , " Follows error messages produced by GHC about missing signatures" )
124
124
] Always
125
- & defineBooleanProperty # whereInlayHintOn
126
- " Display type lenses of where bindings"
125
+ & defineBooleanProperty # localBindingInlayHintOn
126
+ " Display type lenses of local bindings"
127
127
True
128
128
129
129
codeLensProvider :: PluginMethodHandler IdeState Method_TextDocumentCodeLens
@@ -376,23 +376,23 @@ pprPatSynTypeWithoutForalls p = pprPatSynType pWithoutTypeVariables
376
376
-- --------------------------------------------------------------------------------
377
377
378
378
-- | A binding expression with its id and location.
379
- data WhereBinding = WhereBinding
379
+ data LocalBinding = LocalBinding
380
380
{ bindingId :: Id
381
- -- ^ Each WhereBinding represents an id in binding expression.
381
+ -- ^ Each LocalBinding represents an id in binding expression.
382
382
, bindingLoc :: SrcSpan
383
383
-- ^ Location for an individual binding in a pattern.
384
384
-- Here we use the 'bindingLoc' and offset to render the type signature at the proper place.
385
385
, offset :: Int
386
386
-- ^ Column offset between whole binding and individual binding in a pattern.
387
387
--
388
- -- Example: For @(a, b) = (1, True)@, there will be two `WhereBinding `s:
389
- -- - `a`: WhereBinding id_a loc_a 0
390
- -- - `b`: WhereBinding id_b loc_b 4
388
+ -- Example: For @(a, b) = (1, True)@, there will be two `LocalBinding `s:
389
+ -- - `a`: LocalBinding id_a loc_a 0
390
+ -- - `b`: LocalBinding id_b loc_b 4
391
391
}
392
392
393
- -- | Existing bindings in a where clause.
394
- data WhereBindings = WhereBindings
395
- { bindings :: [WhereBinding ]
393
+ -- | Existing local bindings
394
+ data LocalBindings = LocalBindings
395
+ { bindings :: [LocalBinding ]
396
396
, existingSigNames :: [Name ]
397
397
-- ^ Names of existing signatures.
398
398
-- It is used to hide type lens for existing signatures.
@@ -409,69 +409,84 @@ data WhereBindings = WhereBindings
409
409
-- the definition of `f`(second line).
410
410
}
411
411
412
- data GetWhereBindingTypeSigs = GetWhereBindingTypeSigs
412
+ data GetLocalBindingTypeSigs = GetLocalBindingTypeSigs
413
413
deriving (Generic , Show , Eq , Ord , Hashable , NFData )
414
414
415
415
type BindingSigMap = Map. Map Id String
416
416
417
- newtype WhereBindingTypeSigsResult = WhereBindingTypeSigsResult ([WhereBindings ], BindingSigMap )
417
+ newtype LocalBindingTypeSigsResult = LocalBindingTypeSigsResult ([LocalBindings ], BindingSigMap )
418
418
419
- instance Show WhereBindingTypeSigsResult where
420
- show _ = " <GetTypeResult.where >"
419
+ instance Show LocalBindingTypeSigsResult where
420
+ show _ = " <GetTypeResult.local >"
421
421
422
- instance NFData WhereBindingTypeSigsResult where
422
+ instance NFData LocalBindingTypeSigsResult where
423
423
rnf = rwhnf
424
424
425
- type instance RuleResult GetWhereBindingTypeSigs = WhereBindingTypeSigsResult
425
+ type instance RuleResult GetLocalBindingTypeSigs = LocalBindingTypeSigsResult
426
426
427
- whereBindingRules :: Recorder (WithPriority Log ) -> Rules ()
428
- whereBindingRules recorder = do
429
- define (cmapWithPrio LogShake recorder) $ \ GetWhereBindingTypeSigs nfp -> do
427
+ localBindingRules :: Recorder (WithPriority Log ) -> Rules ()
428
+ localBindingRules recorder = do
429
+ define (cmapWithPrio LogShake recorder) $ \ GetLocalBindingTypeSigs nfp -> do
430
430
tmr <- use TypeCheck nfp
431
431
-- we need session here for tidying types
432
432
hsc <- use GhcSession nfp
433
- result <- liftIO $ whereBindingType (tmrTypechecked <$> tmr) (hscEnv <$> hsc)
433
+ result <- liftIO $ localBindingType (tmrTypechecked <$> tmr) (hscEnv <$> hsc)
434
434
pure ([] , result)
435
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
436
+ localBindingType :: Maybe TcGblEnv -> Maybe HscEnv -> IO (Maybe LocalBindingTypeSigsResult )
437
+ localBindingType (Just gblEnv) (Just hsc) = do
438
+ let locals = findLocalQ (tcg_binds gblEnv)
439
+ localBindings = mapMaybe findBindingsQ locals
440
440
bindToSig' = bindToSig hsc (tcg_rdr_env gblEnv)
441
- findSigs (WhereBindings bindings _) = fmap findSig bindings
442
- where findSig (WhereBinding bindingId _ _) = sequence (bindingId, bindToSig' bindingId)
441
+ findSigs (LocalBindings bindings _) = fmap findSig bindings
442
+ where findSig (LocalBinding bindingId _ _) = sequence (bindingId, bindToSig' bindingId)
443
443
(_, Map. fromList . fromMaybe [] -> sigMap) <-
444
444
initTcWithGbl hsc gblEnv ghostSpan $ sequence $ concatMap findSigs localBindings
445
- pure $ Just (WhereBindingTypeSigsResult (localBindings, sigMap))
446
- whereBindingType _ _ = pure Nothing
445
+ pure $ Just (LocalBindingTypeSigsResult (localBindings, sigMap))
446
+ localBindingType _ _ = pure Nothing
447
447
448
- -- | All where clauses from type checked source.
449
- findWhereQ :: GenericQ [HsLocalBinds GhcTc ]
450
- findWhereQ = everything (<>) $ mkQ [] (pure . findWhere)
448
+ -- | All local bind expression from type checked source.
449
+ findLocalQ :: GenericQ [HsLocalBinds GhcTc ]
450
+ findLocalQ = everything (<>) ( [] `mkQ` (pure . findWhere) `extQ` findLet )
451
451
where
452
452
findWhere :: GRHSs GhcTc (LHsExpr GhcTc ) -> HsLocalBinds GhcTc
453
453
findWhere = grhssLocalBinds
454
454
455
- -- | Find all bindings for **one** where clause.
456
- findBindingsQ :: GenericQ (Maybe WhereBindings )
455
+ findLet :: LHsExpr GhcTc -> [HsLocalBinds GhcTc ]
456
+ findLet = findLetExpr . unLoc
457
+
458
+ findLetExpr :: HsExpr GhcTc -> [HsLocalBinds GhcTc ]
459
+ findLetExpr (HsLet _ _ binds _ _) = [binds]
460
+ findLetExpr (HsDo _ _ (unLoc -> stmts)) = concatMap (findLetStmt . unLoc) stmts
461
+ findLetExpr _ = []
462
+
463
+ findLetStmt :: ExprStmt GhcTc -> [HsLocalBinds GhcTc ]
464
+ findLetStmt (LetStmt _ binds) = [binds]
465
+ -- TODO(jinser): why `foo <- expr` does not exist
466
+ -- findLetStmt (BindStmt _ _ expr) = findLetExpr (unLoc expr)
467
+ findLetStmt _ = []
468
+
469
+ -- | Find all bindings for **one** local bind expression.
470
+ findBindingsQ :: GenericQ (Maybe LocalBindings )
457
471
findBindingsQ = something (mkQ Nothing findBindings)
458
472
where
459
- findBindings :: NHsValBindsLR GhcTc -> Maybe WhereBindings
473
+ findBindings :: NHsValBindsLR GhcTc -> Maybe LocalBindings
460
474
findBindings (NValBinds binds sigs) =
461
- Just $ WhereBindings
475
+ Just $ LocalBindings
462
476
{ bindings = concat $ mapMaybe (something (mkQ Nothing findBindingIds) . snd ) binds
463
477
, existingSigNames = concatMap findSigIds sigs
464
478
}
465
479
466
- findBindingIds :: LHsBindLR GhcTc GhcTc -> Maybe [WhereBinding ]
480
+ findBindingIds :: LHsBindLR GhcTc GhcTc -> Maybe [LocalBinding ]
467
481
findBindingIds bind = case unLoc bind of
468
482
FunBind {.. } ->
469
- let whereBinding = WhereBinding (unLoc fun_id) (getLoc fun_id)
483
+ let localBinding = LocalBinding (unLoc fun_id) (getLoc fun_id)
470
484
(col (getLoc fun_id) - col (getLoc bind))
471
- in Just $ pure whereBinding
472
- PatBind {.. } -> Just $ (everything (<>) $ mkQ [] (fmap (uncurry wb) . maybeToList . findIdFromPat)) pat_lhs
485
+ in Just $ pure localBinding
486
+ PatBind {.. } ->
487
+ Just $ (everything (<>) $ mkQ [] (fmap (uncurry wb) . maybeToList . findIdFromPat)) pat_lhs
473
488
where
474
- wb id srcSpan = WhereBinding id srcSpan (col srcSpan - col (getLoc pat_lhs))
489
+ wb id srcSpan = LocalBinding id srcSpan (col srcSpan - col (getLoc pat_lhs))
475
490
_ -> Nothing
476
491
where
477
492
col = srcSpanStartCol . realSrcSpan
@@ -485,29 +500,28 @@ findBindingsQ = something (mkQ Nothing findBindings)
485
500
findSigIds (L _ (TypeSig _ names _)) = map unLoc names
486
501
findSigIds _ = []
487
502
488
- -- | Provide code lens for where bindings.
489
- whereClauseInlayHints :: PluginMethodHandler IdeState Method_TextDocumentInlayHint
490
- whereClauseInlayHints state plId (InlayHintParams _ (TextDocumentIdentifier uri) visibleRange) = do
491
- enabled <- liftIO $ runAction " inlayHint.config" state $ usePropertyAction # whereInlayHintOn plId properties
503
+ -- | Provide code lens for local bindings.
504
+ localBindingInlayHints :: PluginMethodHandler IdeState Method_TextDocumentInlayHint
505
+ localBindingInlayHints state plId (InlayHintParams _ (TextDocumentIdentifier uri) visibleRange) = do
506
+ enabled <- liftIO $ runAction " inlayHint.config" state $ usePropertyAction # localBindingInlayHintOn plId properties
492
507
if not enabled then pure $ InL [] else do
493
508
nfp <- getNormalizedFilePathE uri
494
- (WhereBindingTypeSigsResult (localBindings, sigMap), pm)
495
- <- runActionE " InlayHint.GetWhereBindingTypeSigs" state $ useWithStaleE GetWhereBindingTypeSigs nfp
509
+ (LocalBindingTypeSigsResult (localBindings, sigMap), pm)
510
+ <- runActionE " InlayHint.GetWhereBindingTypeSigs" state $ useWithStaleE GetLocalBindingTypeSigs nfp
496
511
let bindingToInlayHints id sig = generateWhereInlayHints (T. pack $ printName (idName id )) (maybe " _" T. pack sig)
497
512
498
513
-- | Note there may multi ids for one binding,
499
514
-- like @(a, b) = (42, True)@, there are `a` and `b`
500
515
-- in one binding.
501
516
inlayHints =
502
517
[ bindingToInlayHints bindingId bindingSig bindingRange offset
503
- | WhereBindings {.. } <- localBindings
518
+ | LocalBindings {.. } <- localBindings
504
519
, let sigSpans = getSrcSpan <$> existingSigNames
505
- , WhereBinding {.. } <- bindings
520
+ , LocalBinding {.. } <- bindings
506
521
, let bindingSpan = getSrcSpan (idName bindingId)
507
522
, let bindingSig = Map. lookup bindingId sigMap
508
523
, bindingSpan `notElem` sigSpans
509
524
, Just bindingRange <- maybeToList $ toCurrentRange pm <$> srcSpanToRange bindingLoc
510
- -- , Just bindingRange <- [srcSpanToRange bindingLoc]
511
525
-- Show inlay hints only within visible range
512
526
, isSubrangeOf bindingRange visibleRange
513
527
]
0 commit comments