Skip to content

Commit 9f25011

Browse files
alanzpepeiborra
authored andcommitted
Provide pluginNotificationhandlers too
Like pluginHandlers, but for notifications At present the last one in the chain wins, so if one is set it overrides the one built into ghcide
1 parent 3f2ea7c commit 9f25011

File tree

3 files changed

+115
-3
lines changed

3 files changed

+115
-3
lines changed

ghcide/src/Development/IDE/LSP/Notifications.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
module Development.IDE.LSP.Notifications
1010
( setHandlersNotifications
11+
, whenUriFile
1112
) where
1213

1314
import qualified Language.LSP.Server as LSP

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

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
{-# LANGUAGE GADTs #-}
22
{-# LANGUAGE PolyKinds #-}
3+
{-# LANGUAGE KindSignatures #-}
4+
{-# LANGUAGE DataKinds #-}
5+
{-# LANGUAGE GADTs #-}
6+
{-# LANGUAGE OverloadedStrings #-}
37

48
module Development.IDE.Plugin.HLS
59
(
@@ -45,6 +49,7 @@ asGhcIdePlugin defaultConfig mp =
4549
mkPlugin rulesPlugins HLS.pluginRules <>
4650
mkPlugin executeCommandPlugins HLS.pluginCommands <>
4751
mkPlugin (extensiblePlugins defaultConfig) HLS.pluginHandlers
52+
mkPlugin extensibleNotificationPlugins HLS.pluginNotificationHandlers
4853
where
4954
ls = Map.toList (ipMap mp)
5055

@@ -154,6 +159,34 @@ extensiblePlugins defaultConfig xs = Plugin mempty handlers
154159
Just xs -> do
155160
caps <- LSP.getClientCapabilities
156161
pure $ Right $ combineResponses m config caps params xs
162+
-- ---------------------------------------------------------------------
163+
164+
extensibleNotificationPlugins :: [(PluginId, PluginNotificationHandlers IdeState)] -> Plugin Config
165+
extensibleNotificationPlugins xs = Plugin mempty handlers
166+
where
167+
IdeNotificationHandlers handlers' = foldMap bakePluginId xs
168+
bakePluginId :: (PluginId, PluginNotificationHandlers IdeState) -> IdeNotificationHandlers
169+
bakePluginId (pid,PluginNotificationHandlers hs) = IdeNotificationHandlers $ DMap.map
170+
(\(PluginNotificationHandler f) -> IdeNotificationHandler [(pid,f pid)])
171+
hs
172+
handlers = mconcat $ do
173+
(IdeNotification m :=> IdeNotificationHandler fs') <- DMap.assocs handlers'
174+
pure $ notificationHandler m $ \ide params -> do
175+
liftIO $ logInfo (ideLogger ide) "extensibleNotificationPlugins handler entered"
176+
config <- getClientConfig
177+
let fs = filter (\(pid,_) -> pluginEnabledNotification m pid config) fs'
178+
case nonEmpty fs of
179+
Nothing -> do
180+
liftIO $ logInfo (ideLogger ide) "extensibleNotificationPlugins no enabled plugins"
181+
pure ()
182+
-- We run the notifications in order, so the built-in ghcide
183+
-- processing (which restarts the shake process) comes last
184+
-- Just fs -> void $ runConcurrentlyNotification (show m) fs ide params
185+
Just fs -> do
186+
liftIO $ logInfo (ideLogger ide) $ "extensibleNotificationPlugins number of plugins:" <> T.pack (show (length fs))
187+
mapM_ (\(_pid,f) -> f ide params) fs
188+
189+
-- ---------------------------------------------------------------------
157190

158191
runConcurrently
159192
:: MonadUnliftIO m
@@ -175,12 +208,25 @@ combineErrors xs = ResponseError InternalError (T.pack (show xs)) Nothing
175208
newtype IdeHandler (m :: J.Method FromClient Request)
176209
= IdeHandler [(PluginId,IdeState -> MessageParams m -> LSP.LspM Config (NonEmpty (Either ResponseError (ResponseResult m))))]
177210

211+
-- | Combine the 'PluginHandler' for all plugins
212+
newtype IdeNotificationHandler (m :: J.Method FromClient Notification)
213+
= IdeNotificationHandler [(PluginId,(IdeState -> MessageParams m -> LSP.LspM Config (NonEmpty ())))]
214+
-- type NotificationHandler (m :: Method FromClient Notification) = MessageParams m -> IO ()`
215+
178216
-- | Combine the 'PluginHandlers' for all plugins
179-
newtype IdeHandlers = IdeHandlers (DMap IdeMethod IdeHandler)
217+
newtype IdeHandlers = IdeHandlers (DMap IdeMethod IdeHandler)
218+
newtype IdeNotificationHandlers = IdeNotificationHandlers (DMap IdeNotification IdeNotificationHandler)
180219

181220
instance Semigroup IdeHandlers where
182221
(IdeHandlers a) <> (IdeHandlers b) = IdeHandlers $ DMap.unionWithKey go a b
183222
where
184-
go _ (IdeHandler a) (IdeHandler b) = IdeHandler (a ++ b)
223+
go _ (IdeHandler a) (IdeHandler b) = IdeHandler (a <> b)
185224
instance Monoid IdeHandlers where
186225
mempty = IdeHandlers mempty
226+
227+
instance Semigroup IdeNotificationHandlers where
228+
(IdeNotificationHandlers a) <> (IdeNotificationHandlers b) = IdeNotificationHandlers $ DMap.unionWithKey go a b
229+
where
230+
go _ (IdeNotificationHandler a) (IdeNotificationHandler b) = IdeNotificationHandler (a <> b)
231+
instance Monoid IdeNotificationHandlers where
232+
mempty = IdeNotificationHandlers mempty

hls-plugin-api/src/Ide/Types.hs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ data PluginDescriptor ideState =
6262
, pluginRules :: !(Rules ())
6363
, pluginCommands :: ![PluginCommand ideState]
6464
, pluginHandlers :: PluginHandlers ideState
65+
, pluginNotificationHandlers :: PluginNotificationHandlers ideState
6566
}
6667

6768
-- | Methods that can be handled by plugins.
@@ -180,18 +181,59 @@ instance PluginMethod TextDocumentRangeFormatting where
180181
pluginEnabled _ pid conf = (PluginId $ formattingProvider conf) == pid
181182
combineResponses _ _ _ _ (x :| _) = x
182183

184+
-- ---------------------------------------------------------------------
185+
186+
-- | Notifications that can be handled by plugins.
187+
-- 'ExtraParams' captures any extra data the IDE passes to the handlers for this method
188+
class HasTracing (MessageParams m) => PluginNotification m where
189+
190+
-- | Parse the configuration to check if this plugin is enabled
191+
pluginEnabledNotification :: SMethod m -> PluginId -> Config -> Bool
192+
193+
instance PluginNotification TextDocumentDidOpen where
194+
pluginEnabledNotification _ _ _ = True
195+
196+
instance PluginNotification TextDocumentDidChange where
197+
pluginEnabledNotification _ _ _ = True
198+
199+
instance PluginNotification TextDocumentDidSave where
200+
pluginEnabledNotification _ _ _ = True
201+
202+
-- ---------------------------------------------------------------------
203+
183204
-- | Methods which have a PluginMethod instance
184205
data IdeMethod (m :: Method FromClient Request) = PluginMethod m => IdeMethod (SMethod m)
185206
instance GEq IdeMethod where
186207
geq (IdeMethod a) (IdeMethod b) = geq a b
187208
instance GCompare IdeMethod where
188209
gcompare (IdeMethod a) (IdeMethod b) = gcompare a b
189210

211+
-- | Methods which have a PluginMethod instance
212+
data IdeNotification (m :: Method FromClient Notification) = PluginNotification m => IdeNotification (SMethod m)
213+
instance GEq IdeNotification where
214+
geq (IdeNotification a) (IdeNotification b) = geq a b
215+
instance GCompare IdeNotification where
216+
gcompare (IdeNotification a) (IdeNotification b) = gcompare a b
217+
190218
-- | Combine handlers for the
191219
newtype PluginHandler a (m :: Method FromClient Request)
192220
= PluginHandler (PluginId -> a -> MessageParams m -> LspM Config (NonEmpty (Either ResponseError (ResponseResult m))))
193221

194-
newtype PluginHandlers a = PluginHandlers (DMap IdeMethod (PluginHandler a))
222+
newtype PluginNotificationHandler a (m :: Method FromClient Notification)
223+
= PluginNotificationHandler (PluginId -> a -> MessageParams m -> LspM Config (NonEmpty ()))
224+
-- newtype PluginNotificationHandler a (m :: Method FromClient Notification)
225+
-- = PluginNotificationHandler (PluginNotificationMethodHandler a m)`
226+
227+
{-
228+
From Zubin
229+
alanz_: I would say `newtype PluginNotificationHandler a (m :: Method FromClient Notification) = PluginNotificationHandler (PluginNotificationMethodHandler a m)`
230+
16:28 and `newtype PluginNotificationHandlers a = PluginNotificationHandlers (DMap SMethod (PluginNotificationHandler a))
231+
232+
-}
233+
234+
newtype PluginHandlers a = PluginHandlers (DMap IdeMethod (PluginHandler a))
235+
newtype PluginNotificationHandlers a = PluginNotificationHandlers (DMap IdeNotification (PluginNotificationHandler a))
236+
-- newtype PluginNotificationHandlers a = PluginNotificationHandlers (DMap SMethod (PluginNotificationHandler a))
195237

196238
instance Semigroup (PluginHandlers a) where
197239
(PluginHandlers a) <> (PluginHandlers b) = PluginHandlers $ DMap.unionWithKey go a b
@@ -202,8 +244,19 @@ instance Semigroup (PluginHandlers a) where
202244
instance Monoid (PluginHandlers a) where
203245
mempty = PluginHandlers mempty
204246

247+
instance Semigroup (PluginNotificationHandlers a) where
248+
(PluginNotificationHandlers a) <> (PluginNotificationHandlers b) = PluginNotificationHandlers $ DMap.unionWithKey go a b
249+
where
250+
go _ (PluginNotificationHandler f) (PluginNotificationHandler g) = PluginNotificationHandler $ \pid ide params ->
251+
f pid ide params >> g pid ide params
252+
253+
instance Monoid (PluginNotificationHandlers a) where
254+
mempty = PluginNotificationHandlers mempty
255+
205256
type PluginMethodHandler a m = a -> PluginId -> MessageParams m -> LspM Config (Either ResponseError (ResponseResult m))
206257

258+
type PluginNotificationMethodHandler a m = a -> PluginId -> MessageParams m -> LspM Config ()
259+
207260
-- | Make a handler for plugins with no extra data
208261
mkPluginHandler
209262
:: PluginMethod m
@@ -214,13 +267,25 @@ mkPluginHandler m f = PluginHandlers $ DMap.singleton (IdeMethod m) (PluginHandl
214267
where
215268
f' pid ide params = pure <$> f ide pid params
216269

270+
-- | Make a handler for plugins with no extra data
271+
mkPluginNotificationHandler
272+
:: (PluginNotification m)
273+
=> SClientMethod (m :: Method FromClient Notification)
274+
-> PluginNotificationMethodHandler ideState m
275+
-> PluginNotificationHandlers ideState
276+
mkPluginNotificationHandler m f
277+
= PluginNotificationHandlers $ DMap.singleton (IdeNotification m) (PluginNotificationHandler f')
278+
where
279+
f' pid ide params = pure <$> f ide pid params
280+
217281
defaultPluginDescriptor :: PluginId -> PluginDescriptor ideState
218282
defaultPluginDescriptor plId =
219283
PluginDescriptor
220284
plId
221285
mempty
222286
mempty
223287
mempty
288+
mempty
224289

225290
newtype CommandId = CommandId T.Text
226291
deriving (Show, Read, Eq, Ord)

0 commit comments

Comments
 (0)