@@ -24,7 +24,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
2424import Data.Aeson.Types (toJSON )
2525import qualified Data.Aeson.Types as A
2626import Data.Generics (GenericQ , everything ,
27- mkQ , something )
27+ extQ , mkQ , something )
2828import Data.List (find )
2929import qualified Data.Map as Map
3030import Data.Maybe (catMaybes , fromMaybe ,
@@ -105,25 +105,25 @@ descriptor recorder plId =
105105 (defaultPluginDescriptor plId desc)
106106 { pluginHandlers = mkPluginHandler SMethod_TextDocumentCodeLens codeLensProvider
107107 <> mkResolveHandler SMethod_CodeLensResolve codeLensResolveProvider
108- <> mkPluginHandler SMethod_TextDocumentInlayHint whereClauseInlayHints
108+ <> mkPluginHandler SMethod_TextDocumentInlayHint localBindingInlayHints
109109 , pluginCommands = [PluginCommand typeLensCommandId " adds a signature" commandHandler]
110- , pluginRules = globalBindingRules recorder *> whereBindingRules recorder
110+ , pluginRules = globalBindingRules recorder *> localBindingRules recorder
111111 , pluginConfigDescriptor = defaultConfigDescriptor {configCustomConfig = mkCustomConfig properties}
112112 }
113113 where
114114 desc = " Provides code lenses type signatures"
115115
116116properties :: Properties
117- '[ 'PropertyKey " whereInlayHintOn " 'TBoolean,
117+ '[ 'PropertyKey " localBindingInlayHintOn " 'TBoolean,
118118 'PropertyKey " mode" ('TEnum Mode )]
119119properties = emptyProperties
120120 & defineEnumProperty # mode " Control how type lenses are shown"
121121 [ (Always , " Always displays type lenses of global bindings" )
122122 , (Exported , " Only display type lenses of exported global bindings" )
123123 , (Diagnostics , " Follows error messages produced by GHC about missing signatures" )
124124 ] Always
125- & defineBooleanProperty # whereInlayHintOn
126- " Display type lenses of where bindings"
125+ & defineBooleanProperty # localBindingInlayHintOn
126+ " Display type lenses of local bindings"
127127 True
128128
129129codeLensProvider :: PluginMethodHandler IdeState Method_TextDocumentCodeLens
@@ -376,23 +376,23 @@ pprPatSynTypeWithoutForalls p = pprPatSynType pWithoutTypeVariables
376376-- --------------------------------------------------------------------------------
377377
378378-- | A binding expression with its id and location.
379- data WhereBinding = WhereBinding
379+ data LocalBinding = LocalBinding
380380 { bindingId :: Id
381- -- ^ Each WhereBinding represents an id in binding expression.
381+ -- ^ Each LocalBinding represents an id in binding expression.
382382 , bindingLoc :: SrcSpan
383383 -- ^ Location for an individual binding in a pattern.
384384 -- Here we use the 'bindingLoc' and offset to render the type signature at the proper place.
385385 , offset :: Int
386386 -- ^ Column offset between whole binding and individual binding in a pattern.
387387 --
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
391391 }
392392
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 ]
396396 , existingSigNames :: [Name ]
397397 -- ^ Names of existing signatures.
398398 -- It is used to hide type lens for existing signatures.
@@ -409,69 +409,84 @@ data WhereBindings = WhereBindings
409409 -- the definition of `f`(second line).
410410 }
411411
412- data GetWhereBindingTypeSigs = GetWhereBindingTypeSigs
412+ data GetLocalBindingTypeSigs = GetLocalBindingTypeSigs
413413 deriving (Generic , Show , Eq , Ord , Hashable , NFData )
414414
415415type BindingSigMap = Map. Map Id String
416416
417- newtype WhereBindingTypeSigsResult = WhereBindingTypeSigsResult ([WhereBindings ], BindingSigMap )
417+ newtype LocalBindingTypeSigsResult = LocalBindingTypeSigsResult ([LocalBindings ], BindingSigMap )
418418
419- instance Show WhereBindingTypeSigsResult where
420- show _ = " <GetTypeResult.where >"
419+ instance Show LocalBindingTypeSigsResult where
420+ show _ = " <GetTypeResult.local >"
421421
422- instance NFData WhereBindingTypeSigsResult where
422+ instance NFData LocalBindingTypeSigsResult where
423423 rnf = rwhnf
424424
425- type instance RuleResult GetWhereBindingTypeSigs = WhereBindingTypeSigsResult
425+ type instance RuleResult GetLocalBindingTypeSigs = LocalBindingTypeSigsResult
426426
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
430430 tmr <- use TypeCheck nfp
431431 -- we need session here for tidying types
432432 hsc <- use GhcSession nfp
433- result <- liftIO $ whereBindingType (tmrTypechecked <$> tmr) (hscEnv <$> hsc)
433+ result <- liftIO $ localBindingType (tmrTypechecked <$> tmr) (hscEnv <$> hsc)
434434 pure ([] , result)
435435
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
440440 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)
443443 (_, Map. fromList . fromMaybe [] -> sigMap) <-
444444 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
447447
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 )
451451 where
452452 findWhere :: GRHSs GhcTc (LHsExpr GhcTc ) -> HsLocalBinds GhcTc
453453 findWhere = grhssLocalBinds
454454
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 )
457471findBindingsQ = something (mkQ Nothing findBindings)
458472 where
459- findBindings :: NHsValBindsLR GhcTc -> Maybe WhereBindings
473+ findBindings :: NHsValBindsLR GhcTc -> Maybe LocalBindings
460474 findBindings (NValBinds binds sigs) =
461- Just $ WhereBindings
475+ Just $ LocalBindings
462476 { bindings = concat $ mapMaybe (something (mkQ Nothing findBindingIds) . snd ) binds
463477 , existingSigNames = concatMap findSigIds sigs
464478 }
465479
466- findBindingIds :: LHsBindLR GhcTc GhcTc -> Maybe [WhereBinding ]
480+ findBindingIds :: LHsBindLR GhcTc GhcTc -> Maybe [LocalBinding ]
467481 findBindingIds bind = case unLoc bind of
468482 FunBind {.. } ->
469- let whereBinding = WhereBinding (unLoc fun_id) (getLoc fun_id)
483+ let localBinding = LocalBinding (unLoc fun_id) (getLoc fun_id)
470484 (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
473488 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))
475490 _ -> Nothing
476491 where
477492 col = srcSpanStartCol . realSrcSpan
@@ -485,29 +500,28 @@ findBindingsQ = something (mkQ Nothing findBindings)
485500 findSigIds (L _ (TypeSig _ names _)) = map unLoc names
486501 findSigIds _ = []
487502
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
492507 if not enabled then pure $ InL [] else do
493508 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
496511 let bindingToInlayHints id sig = generateWhereInlayHints (T. pack $ printName (idName id )) (maybe " _" T. pack sig)
497512
498513 -- | Note there may multi ids for one binding,
499514 -- like @(a, b) = (42, True)@, there are `a` and `b`
500515 -- in one binding.
501516 inlayHints =
502517 [ bindingToInlayHints bindingId bindingSig bindingRange offset
503- | WhereBindings {.. } <- localBindings
518+ | LocalBindings {.. } <- localBindings
504519 , let sigSpans = getSrcSpan <$> existingSigNames
505- , WhereBinding {.. } <- bindings
520+ , LocalBinding {.. } <- bindings
506521 , let bindingSpan = getSrcSpan (idName bindingId)
507522 , let bindingSig = Map. lookup bindingId sigMap
508523 , bindingSpan `notElem` sigSpans
509524 , Just bindingRange <- maybeToList $ toCurrentRange pm <$> srcSpanToRange bindingLoc
510- -- , Just bindingRange <- [srcSpanToRange bindingLoc]
511525 -- Show inlay hints only within visible range
512526 , isSubrangeOf bindingRange visibleRange
513527 ]
0 commit comments