@@ -31,6 +31,7 @@ module Ide.Types
31
31
, PluginCommand (.. ), CommandId (.. ), CommandFunction , mkLspCommand, mkLspCmdId
32
32
, PluginId (.. )
33
33
, PluginHandler (.. ), mkPluginHandler
34
+ , PluginM , runPluginM, pluginGetClientCapabilities, pluginGetVirtualFile, pluginGetVersionedTextDoc, pluginSendNotification, pluginSendRequest, pluginWithIndefiniteProgress
34
35
, PluginHandlers (.. )
35
36
, PluginMethod (.. )
36
37
, PluginMethodHandler
@@ -62,6 +63,7 @@ import Control.Lens (_Just, view, (.~), (?~), (^.),
62
63
(^?) )
63
64
import Control.Monad (void )
64
65
import Control.Monad.Error.Class (MonadError (throwError ))
66
+ import Control.Monad.IO.Class (MonadIO )
65
67
import Control.Monad.Trans.Class (MonadTrans (lift ))
66
68
import Control.Monad.Trans.Except (ExceptT , runExceptT )
67
69
import Data.Aeson hiding (Null , defaultOptions )
@@ -94,7 +96,7 @@ import Ide.Plugin.Properties
94
96
import qualified Language.LSP.Protocol.Lens as L
95
97
import Language.LSP.Protocol.Message
96
98
import Language.LSP.Protocol.Types
97
- import Language.LSP.Server ( LspM , LspT , getVirtualFile )
99
+ import Language.LSP.Server
98
100
import Language.LSP.VFS
99
101
import Numeric.Natural
100
102
import OpenTelemetry.Eventlog
@@ -103,6 +105,7 @@ import Prettyprinter as PP
103
105
import System.FilePath
104
106
import System.IO.Unsafe
105
107
import Text.Regex.TDFA.Text ()
108
+ import UnliftIO (MonadUnliftIO )
106
109
-- ---------------------------------------------------------------------
107
110
108
111
data IdePlugins ideState = IdePlugins_
@@ -890,9 +893,52 @@ instance GEq IdeNotification where
890
893
instance GCompare IdeNotification where
891
894
gcompare (IdeNotification a) (IdeNotification b) = gcompare a b
892
895
896
+ -- | Restricted version of 'LspM' specific to plugins
897
+ newtype PluginM config a = PluginM { _runPluginM :: LspM config a }
898
+ deriving newtype (Applicative , Functor , Monad , MonadIO , MonadUnliftIO )
899
+
900
+ runPluginM :: PluginM config a -> LspM config a
901
+ runPluginM = _runPluginM
902
+
903
+ -- | Wrapper of 'getVirtualFile' for PluginM
904
+ --
905
+ -- TODO: To be replaced by a lookup of the Shake build graph
906
+ pluginGetVirtualFile :: NormalizedUri -> PluginM config (Maybe VirtualFile )
907
+ pluginGetVirtualFile uri = PluginM $ getVirtualFile uri
908
+
909
+ -- | Version of 'getVersionedTextDoc' for PluginM
910
+ --
911
+ -- TODO: Should use 'pluginGetVirtualFile' instead of wrapping 'getVersionedTextDoc'.
912
+ -- At the time of writing, 'pluginGetVirtualFile' of the "lsp" package is implemented with 'getVirtualFile'.
913
+ pluginGetVersionedTextDoc :: TextDocumentIdentifier -> PluginM config VersionedTextDocumentIdentifier
914
+ pluginGetVersionedTextDoc = PluginM . getVersionedTextDoc
915
+
916
+ -- | Wrapper of 'getClientCapabilities' for PluginM
917
+ pluginGetClientCapabilities :: PluginM config ClientCapabilities
918
+ pluginGetClientCapabilities = PluginM getClientCapabilities
919
+
920
+ -- | Wrapper of 'sendNotification for PluginM
921
+ --
922
+ -- TODO: Return notification in result instead of calling `sendNotification` directly
923
+ pluginSendNotification :: forall (m :: Method ServerToClient Notification ) config . SServerMethod m -> MessageParams m -> PluginM config ()
924
+ pluginSendNotification smethod params = PluginM $ sendNotification smethod params
925
+
926
+ -- | Wrapper of 'sendRequest' for PluginM
927
+ --
928
+ -- TODO: Return request in result instead of calling `sendRequest` directly
929
+ pluginSendRequest :: forall (m :: Method ServerToClient Request ) config . SServerMethod m -> MessageParams m -> (Either (TResponseError m ) (MessageResult m ) -> PluginM config () ) -> PluginM config (LspId m )
930
+ pluginSendRequest smethod params action = PluginM $ sendRequest smethod params (runPluginM . action)
931
+
932
+ -- | Wrapper of 'withIndefiniteProgress' for PluginM
933
+ pluginWithIndefiniteProgress :: T. Text -> Maybe ProgressToken -> ProgressCancellable -> ((T. Text -> PluginM config () ) -> PluginM config a ) -> PluginM config a
934
+ pluginWithIndefiniteProgress title progressToken cancellable updateAction =
935
+ PluginM $
936
+ withIndefiniteProgress title progressToken cancellable $ \ putUpdate ->
937
+ runPluginM $ updateAction (PluginM . putUpdate)
938
+
893
939
-- | Combine handlers for the
894
940
newtype PluginHandler a (m :: Method ClientToServer Request )
895
- = PluginHandler (PluginId -> a -> MessageParams m -> LspM Config (NonEmpty (Either PluginError (MessageResult m ))))
941
+ = PluginHandler (PluginId -> a -> MessageParams m -> PluginM Config (NonEmpty (Either PluginError (MessageResult m ))))
896
942
897
943
newtype PluginNotificationHandler a (m :: Method ClientToServer Notification )
898
944
= PluginNotificationHandler (PluginId -> a -> VFS -> MessageParams m -> LspM Config () )
@@ -917,7 +963,7 @@ instance Semigroup (PluginNotificationHandlers a) where
917
963
instance Monoid (PluginNotificationHandlers a ) where
918
964
mempty = PluginNotificationHandlers mempty
919
965
920
- type PluginMethodHandler a m = a -> PluginId -> MessageParams m -> ExceptT PluginError (LspM Config ) (MessageResult m )
966
+ type PluginMethodHandler a m = a -> PluginId -> MessageParams m -> ExceptT PluginError (PluginM Config ) (MessageResult m )
921
967
922
968
type PluginNotificationMethodHandler a m = a -> VFS -> PluginId -> MessageParams m -> LspM Config ()
923
969
@@ -930,7 +976,7 @@ mkPluginHandler
930
976
-> PluginHandlers ideState
931
977
mkPluginHandler m f = PluginHandlers $ DMap. singleton (IdeMethod m) (PluginHandler (f' m))
932
978
where
933
- f' :: SMethod m -> PluginId -> ideState -> MessageParams m -> LspT Config IO (NonEmpty (Either PluginError (MessageResult m )))
979
+ f' :: SMethod m -> PluginId -> ideState -> MessageParams m -> PluginM Config (NonEmpty (Either PluginError (MessageResult m )))
934
980
-- We need to have separate functions for each method that supports resolve, so far we only support CodeActions
935
981
-- CodeLens, and Completion methods.
936
982
f' SMethod_TextDocumentCodeAction pid ide params@ CodeActionParams {_textDocument= TextDocumentIdentifier {_uri}} =
@@ -1034,7 +1080,7 @@ type CommandFunction ideState a
1034
1080
= ideState
1035
1081
-> Maybe ProgressToken
1036
1082
-> a
1037
- -> ExceptT PluginError (LspM Config ) (Value |? Null )
1083
+ -> ExceptT PluginError (PluginM Config ) (Value |? Null )
1038
1084
1039
1085
-- ---------------------------------------------------------------------
1040
1086
@@ -1044,7 +1090,7 @@ type ResolveFunction ideState a (m :: Method ClientToServer Request) =
1044
1090
-> MessageParams m
1045
1091
-> Uri
1046
1092
-> a
1047
- -> ExceptT PluginError (LspM Config ) (MessageResult m )
1093
+ -> ExceptT PluginError (PluginM Config ) (MessageResult m )
1048
1094
1049
1095
-- | Make a handler for resolve methods. In here we take your provided ResolveFunction
1050
1096
-- and turn it into a PluginHandlers. See Note [Resolve in PluginHandlers]
@@ -1126,7 +1172,7 @@ type FormattingHandler a
1126
1172
-> T. Text
1127
1173
-> NormalizedFilePath
1128
1174
-> FormattingOptions
1129
- -> ExceptT PluginError (LspM Config ) ([TextEdit ] |? Null )
1175
+ -> ExceptT PluginError (PluginM Config ) ([TextEdit ] |? Null )
1130
1176
1131
1177
mkFormattingHandlers :: forall a . FormattingHandler a -> PluginHandlers a
1132
1178
mkFormattingHandlers f = mkPluginHandler SMethod_TextDocumentFormatting ( provider SMethod_TextDocumentFormatting )
@@ -1135,7 +1181,7 @@ mkFormattingHandlers f = mkPluginHandler SMethod_TextDocumentFormatting ( provid
1135
1181
provider :: forall m . FormattingMethod m => SMethod m -> PluginMethodHandler a m
1136
1182
provider m ide _pid params
1137
1183
| Just nfp <- uriToNormalizedFilePath $ toNormalizedUri uri = do
1138
- mf <- lift $ getVirtualFile $ toNormalizedUri uri
1184
+ mf <- lift $ pluginGetVirtualFile $ toNormalizedUri uri
1139
1185
case mf of
1140
1186
Just vf -> do
1141
1187
let (typ, mtoken) = case m of
0 commit comments