Skip to content

Commit 6c0652f

Browse files
committed
Added note on resolve
1 parent da22773 commit 6c0652f

File tree

1 file changed

+43
-5
lines changed

1 file changed

+43
-5
lines changed

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

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ instance PluginMethod Request Method_TextDocumentCodeAction where
408408
uri = msgParams ^. L.textDocument . L.uri
409409

410410
instance PluginMethod Request Method_CodeActionResolve where
411+
-- See Note [Resolve in PluginHandlers]
411412
pluginEnabled _ msgParams pluginDesc config =
412413
pluginResolverResponsible (msgParams ^. L.data_) pluginDesc
413414
&& pluginEnabledConfig plcCodeActionsOn (configForPlugin config pluginDesc)
@@ -447,6 +448,7 @@ instance PluginMethod Request Method_TextDocumentCodeLens where
447448
uri = msgParams ^. L.textDocument . L.uri
448449

449450
instance PluginMethod Request Method_CodeLensResolve where
451+
-- See Note [Resolve in PluginHandlers]
450452
pluginEnabled _ msgParams pluginDesc config =
451453
pluginResolverResponsible (msgParams ^. L.data_) pluginDesc
452454
&& pluginEnabledConfig plcCodeActionsOn (configForPlugin config pluginDesc)
@@ -469,6 +471,7 @@ instance PluginMethod Request Method_TextDocumentDocumentSymbol where
469471
uri = msgParams ^. L.textDocument . L.uri
470472

471473
instance PluginMethod Request Method_CompletionItemResolve where
474+
-- See Note [Resolve in PluginHandlers]
472475
pluginEnabled _ msgParams pluginDesc config = pluginResolverResponsible (msgParams ^. L.data_) pluginDesc
473476
&& pluginEnabledConfig plcCompletionOn (configForPlugin config pluginDesc)
474477

@@ -551,7 +554,8 @@ instance PluginRequestMethod Method_TextDocumentCodeAction where
551554
| otherwise = False
552555

553556
instance PluginRequestMethod Method_CodeActionResolve where
554-
-- Resolve methods should only have one response
557+
-- A resolve request should only have one response.
558+
-- See Note [Resolve in PluginHandlers].
555559
combineResponses _ _ _ _ (x :| _) = x
556560

557561
instance PluginRequestMethod Method_TextDocumentDefinition where
@@ -572,7 +576,8 @@ instance PluginRequestMethod Method_WorkspaceSymbol where
572576
instance PluginRequestMethod Method_TextDocumentCodeLens where
573577

574578
instance PluginRequestMethod Method_CodeLensResolve where
575-
-- A resolve request should only ever get one response
579+
-- A resolve request should only ever get one response.
580+
-- See note Note [Resolve in PluginHandlers]
576581
combineResponses _ _ _ _ (x :| _) = x
577582

578583
instance PluginRequestMethod Method_TextDocumentRename where
@@ -616,7 +621,8 @@ instance PluginRequestMethod Method_TextDocumentDocumentSymbol where
616621
in [si] <> children'
617622

618623
instance PluginRequestMethod Method_CompletionItemResolve where
619-
-- resolve methods should only have one response
624+
-- A resolve request should only have one response.
625+
-- See Note [Resolve in PluginHandlers]
620626
combineResponses _ _ _ _ (x :| _) = x
621627

622628
instance PluginRequestMethod Method_TextDocumentCompletion where
@@ -774,7 +780,8 @@ type PluginMethodHandler a m = a -> PluginId -> MessageParams m -> LspM Config (
774780

775781
type PluginNotificationMethodHandler a m = a -> VFS -> PluginId -> MessageParams m -> LspM Config ()
776782

777-
-- | Make a handler for plugins
783+
-- | Make a handler for plugins. For how resolve works with this see
784+
-- Note [Resolve in PluginHandlers]
778785
mkPluginHandler
779786
:: forall ideState m. PluginRequestMethod m
780787
=> SClientMethod m
@@ -896,7 +903,7 @@ type ResolveFunction ideState a (m :: Method ClientToServer Request) =
896903
-> LspM Config (Either ResponseError (MessageResult m))
897904

898905
-- | Make a handler for resolve methods. In here we take your provided ResolveFunction
899-
-- and turn it into a PluginHandlers
906+
-- and turn it into a PluginHandlers. See Note [Resolve in PluginHandlers]
900907
mkResolveHandler
901908
:: forall ideState a m. (FromJSON a, PluginRequestMethod m, L.HasData_ (MessageParams m) (Maybe Value))
902909
=> SClientMethod m
@@ -1084,8 +1091,39 @@ getProcessID = fromIntegral <$> P.getProcessID
10841091
installSigUsr1Handler h = void $ installHandler sigUSR1 (Catch h) Nothing
10851092
#endif
10861093

1094+
-- |Determine whether this request should be routed to the plugin. Fails closed
1095+
-- if we can't determine which plugin it should be routed to.
10871096
pluginResolverResponsible :: Maybe Value -> PluginDescriptor c -> Bool
10881097
pluginResolverResponsible (Just (fromJSON -> (Success (PluginResolveData o _ _)))) pluginDesc =
10891098
pluginId pluginDesc == o
10901099
-- We want to fail closed
10911100
pluginResolverResponsible _ _ = False
1101+
1102+
{- Note [Resolve in PluginHandlers]
1103+
Resolve methods have a few guarantees that need to be made by HLS,
1104+
specifically they need to only be called once, as neither their errors nor
1105+
their responses can be easily combined. Whereas commands, which similarly have
1106+
the same requirements have their own codepaths for execution, for resolve
1107+
methods we are relying on the standard PluginHandlers codepath.
1108+
That isn't a problem, but it does mean we need to do some things extra for
1109+
these methods.
1110+
- First of all, whenever a handler that can be resolved sets the data_ field
1111+
in their response, we need to intercept it, and wrap it in a data type
1112+
PluginResolveData that allows us to route the future resolve request to the
1113+
specific plugin which is responsible for it. (We also throw in the URI for
1114+
convenience, because everyone needs that). We do that in mkPluginHandler.
1115+
- When we get any resolve requests we check their data field for our
1116+
PluginResolveData that will allow us to route the request to the right
1117+
plugin. If we can't find out which plugin to route the request to, then we
1118+
just don't route it at all. This is done in pluginEnabled, and
1119+
pluginResolverResponsible.
1120+
- Finally we have mkResolveHandler, which takes the resolve request and
1121+
unwraps the plugins data from our PluginResolveData, parses it and passes it
1122+
it on to the registered handler.
1123+
It should be noted that there are some restrictions with this approach: First,
1124+
if a plugin does not set the data_ field, than the request will not be able
1125+
to be resolved. This is because we only wrap data_ fields that have been set
1126+
with our PluginResolvableData tag. Second, if a plugin were to register two
1127+
resolve handlers for the same method, than our assumptions that we never have
1128+
two responses break, and behavior is undefined.
1129+
-}

0 commit comments

Comments
 (0)