Skip to content

Commit fed7ad7

Browse files
Jana Chadtfendor
authored andcommitted
Generalise file extension handling for plugins
NotificationHandler now distinguishes between different file extensions RequestHandler distinguishes between different file extensions
1 parent addb648 commit fed7ad7

File tree

5 files changed

+209
-51
lines changed

5 files changed

+209
-51
lines changed

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

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ asGhcIdePlugin :: Recorder (WithPriority Log) -> IdePlugins IdeState -> Plugin C
5858
asGhcIdePlugin recorder (IdePlugins ls) =
5959
mkPlugin rulesPlugins HLS.pluginRules <>
6060
mkPlugin executeCommandPlugins HLS.pluginCommands <>
61-
mkPlugin extensiblePlugins HLS.pluginHandlers <>
62-
mkPlugin (extensibleNotificationPlugins recorder) HLS.pluginNotificationHandlers <>
61+
mkPlugin extensiblePlugins id <>
62+
mkPlugin (extensibleNotificationPlugins recorder) id <>
6363
mkPlugin dynFlagsPlugins HLS.pluginModifyDynflags
6464
where
6565

@@ -153,55 +153,80 @@ executeCommandHandlers ecs = requestHandler SWorkspaceExecuteCommand execCmd
153153

154154
-- ---------------------------------------------------------------------
155155

156-
extensiblePlugins :: [(PluginId, PluginHandlers IdeState)] -> Plugin Config
156+
extensiblePlugins :: [(PluginId, PluginDescriptor IdeState)] -> Plugin Config
157157
extensiblePlugins xs = mempty { P.pluginHandlers = handlers }
158158
where
159+
getPluginDescriptor pid = lookup pid xs
159160
IdeHandlers handlers' = foldMap bakePluginId xs
160-
bakePluginId :: (PluginId, PluginHandlers IdeState) -> IdeHandlers
161-
bakePluginId (pid,PluginHandlers hs) = IdeHandlers $ DMap.map
161+
bakePluginId :: (PluginId, PluginDescriptor IdeState) -> IdeHandlers
162+
bakePluginId (pid,pluginDesc) = IdeHandlers $ DMap.map
162163
(\(PluginHandler f) -> IdeHandler [(pid,f pid)])
163164
hs
165+
where
166+
PluginHandlers hs = HLS.pluginHandlers pluginDesc
164167
handlers = mconcat $ do
165168
(IdeMethod m :=> IdeHandler fs') <- DMap.assocs handlers'
166169
pure $ requestHandler m $ \ide params -> do
167170
config <- Ide.PluginUtils.getClientConfig
168-
let fs = filter (\(pid,_) -> pluginEnabled m pid config) fs'
169-
case nonEmpty fs of
170-
Nothing -> pure $ Left $ ResponseError InvalidRequest
171-
("No plugin enabled for " <> T.pack (show m) <> ", available: " <> T.pack (show $ map fst fs))
172-
Nothing
173-
Just fs -> do
174-
let msg e pid = "Exception in plugin " <> T.pack (show pid) <> "while processing " <> T.pack (show m) <> ": " <> T.pack (show e)
175-
es <- runConcurrently msg (show m) fs ide params
176-
let (errs,succs) = partitionEithers $ toList es
177-
case nonEmpty succs of
178-
Nothing -> pure $ Left $ combineErrors errs
179-
Just xs -> do
180-
caps <- LSP.getClientCapabilities
181-
pure $ Right $ combineResponses m config caps params xs
171+
let pluginInfo = map (\(pid,_) -> (pid, getPluginDescriptor pid)) fs'
172+
cleanPluginInfo <- collectPluginDescriptors pluginInfo []
173+
case cleanPluginInfo of
174+
Left err -> pure $ Left err
175+
Right pluginInfos -> do
176+
let fs = map snd $ filter (\((_, desc), _) -> pluginEnabled m params desc config) (zip pluginInfos fs')
177+
case nonEmpty fs of
178+
Nothing -> pure $ Left $ ResponseError InvalidRequest
179+
("No plugin enabled for " <> T.pack (show m) <> ", available: " <> T.pack (show $ map fst fs))
180+
Nothing
181+
Just fs -> do
182+
let msg e pid = "Exception in plugin " <> T.pack (show pid) <> "while processing " <> T.pack (show m) <> ": " <> T.pack (show e)
183+
es <- runConcurrently msg (show m) fs ide params
184+
let (errs,succs) = partitionEithers $ toList es
185+
case nonEmpty succs of
186+
Nothing -> pure $ Left $ combineErrors errs
187+
Just xs -> do
188+
caps <- LSP.getClientCapabilities
189+
pure $ Right $ combineResponses m config caps params xs
190+
191+
collectPluginDescriptors :: [(PluginId, Maybe (PluginDescriptor c))] -> [(PluginId, PluginDescriptor c)] -> LSP.LspM Config (Either ResponseError [(PluginId, PluginDescriptor c)])
192+
collectPluginDescriptors ((pid, Nothing):_) _ = pure $ Left $ ResponseError InvalidRequest
193+
("No plugindescriptor found for " <> pidT <> ", available: ")
194+
Nothing
195+
where
196+
PluginId pidT = pid
197+
collectPluginDescriptors ((pid, Just desc):xs) ys = collectPluginDescriptors xs (ys ++ [(pid, desc)])
198+
collectPluginDescriptors [] ys = pure $ Right ys
199+
182200
-- ---------------------------------------------------------------------
183201

184-
extensibleNotificationPlugins :: Recorder (WithPriority Log) -> [(PluginId, PluginNotificationHandlers IdeState)] -> Plugin Config
202+
extensibleNotificationPlugins :: Recorder (WithPriority Log) -> [(PluginId, PluginDescriptor IdeState)] -> Plugin Config
185203
extensibleNotificationPlugins recorder xs = mempty { P.pluginHandlers = handlers }
186204
where
205+
getPluginDescriptor pid = lookup pid xs
187206
IdeNotificationHandlers handlers' = foldMap bakePluginId xs
188-
bakePluginId :: (PluginId, PluginNotificationHandlers IdeState) -> IdeNotificationHandlers
189-
bakePluginId (pid,PluginNotificationHandlers hs) = IdeNotificationHandlers $ DMap.map
207+
bakePluginId :: (PluginId, PluginDescriptor IdeState) -> IdeNotificationHandlers
208+
bakePluginId (pid,pluginDesc) = IdeNotificationHandlers $ DMap.map
190209
(\(PluginNotificationHandler f) -> IdeNotificationHandler [(pid,f pid)])
191210
hs
211+
where PluginNotificationHandlers hs = HLS.pluginNotificationHandlers pluginDesc
192212
handlers = mconcat $ do
193213
(IdeNotification m :=> IdeNotificationHandler fs') <- DMap.assocs handlers'
194214
pure $ notificationHandler m $ \ide vfs params -> do
195215
config <- Ide.PluginUtils.getClientConfig
196-
let fs = filter (\(pid,_) -> plcGlobalOn $ configForPlugin config pid) fs'
197-
case nonEmpty fs of
198-
Nothing -> do
199-
logWith recorder Info LogNoEnabledPlugins
200-
pure ()
201-
Just fs -> do
202-
-- We run the notifications in order, so the core ghcide provider
203-
-- (which restarts the shake process) hopefully comes last
204-
mapM_ (\(pid,f) -> otTracedProvider pid (fromString $ show m) $ f ide vfs params) fs
216+
let pluginInfo = map (\(pid,_) -> (pid, getPluginDescriptor pid)) fs'
217+
cleanPluginInfo <- collectPluginDescriptors pluginInfo []
218+
case cleanPluginInfo of
219+
Left _ -> pure ()
220+
Right pluginInfos -> do
221+
let fs = map snd $ filter (\((_, desc), _) -> pluginEnabled2 m params desc config) (zip pluginInfos fs')
222+
case nonEmpty fs of
223+
Nothing -> do
224+
logWith recorder Info LogNoEnabledPlugins
225+
pure ()
226+
Just fs -> do
227+
-- We run the notifications in order, so the core ghcide provider
228+
-- (which restarts the shake process) hopefully comes last
229+
mapM_ (\(pid,f) -> otTracedProvider pid (fromString $ show m) $ f ide vfs params) fs
205230

206231
-- ---------------------------------------------------------------------
207232

haskell-language-server.cabal

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ flag dynamic
226226
common example-plugins
227227
hs-source-dirs: plugins/default/src
228228
other-modules: Ide.Plugin.Example,
229-
Ide.Plugin.Example2
229+
Ide.Plugin.Example2,
230+
Ide.Plugin.ExampleCabal
230231

231232
common class
232233
if flag(class)

hls-plugin-api/hls-plugin-api.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ library
4343
, Diff ^>=0.4.0
4444
, dlist
4545
, extra
46+
, filepath
4647
, ghc
4748
, hashable
4849
, hls-graph ^>= 1.7

0 commit comments

Comments
 (0)