@@ -39,11 +39,14 @@ import Language.Haskell.LSP.Core (LspFuncs(..))
39
39
import Language.Haskell.LSP.Messages
40
40
41
41
runLanguageServer
42
- :: LSP. Options
43
- -> PartialHandlers
42
+ :: forall config . (Show config )
43
+ => LSP. Options
44
+ -> PartialHandlers config
45
+ -> (InitializeRequest -> Either T. Text config )
46
+ -> (DidChangeConfigurationNotification -> Either T. Text config )
44
47
-> (IO LspId -> (FromServerMessage -> IO () ) -> VFSHandle -> ClientCapabilities -> IO IdeState )
45
48
-> IO ()
46
- runLanguageServer options userHandlers getIdeState = do
49
+ runLanguageServer options userHandlers onInitialConfig onConfigChange getIdeState = do
47
50
-- Move stdout to another file descriptor and duplicate stderr
48
51
-- to stdout. This guards against stray prints from corrupting the JSON-RPC
49
52
-- message stream.
@@ -60,7 +63,7 @@ runLanguageServer options userHandlers getIdeState = do
60
63
61
64
-- Send everything over a channel, since you need to wait until after initialise before
62
65
-- LspFuncs is available
63
- clientMsgChan :: Chan Message <- newChan
66
+ clientMsgChan :: Chan ( Message config ) <- newChan
64
67
65
68
-- These barriers are signaled when the threads reading from these chans exit.
66
69
-- This should not happen but if it does, we will make sure that the whole server
@@ -79,6 +82,7 @@ runLanguageServer options userHandlers getIdeState = do
79
82
let withResponseAndRequest wrap wrapNewReq f = Just $ \ r@ RequestMessage {_id} -> do
80
83
atomically $ modifyTVar pendingRequests (Set. insert _id)
81
84
writeChan clientMsgChan $ ResponseAndRequest r wrap wrapNewReq f
85
+ let withInitialize f = Just $ \ r -> writeChan clientMsgChan $ InitialParams r (\ lsp ide x -> f lsp ide x)
82
86
let cancelRequest reqId = atomically $ do
83
87
queued <- readTVar pendingRequests
84
88
-- We want to avoid that the list of cancelled requests
@@ -95,6 +99,7 @@ runLanguageServer options userHandlers getIdeState = do
95
99
cancelled <- readTVar cancelledRequests
96
100
unless (reqId `Set.member` cancelled) retry
97
101
let PartialHandlers parts =
102
+ initializeRequestHandler <>
98
103
setHandlersIgnore <> -- least important
99
104
setHandlersDefinition <> setHandlersHover <>
100
105
setHandlersOutline <>
@@ -103,11 +108,11 @@ runLanguageServer options userHandlers getIdeState = do
103
108
cancelHandler cancelRequest
104
109
-- Cancel requests are special since they need to be handled
105
110
-- out of order to be useful. Existing handlers are run afterwards.
106
- handlers <- parts WithMessage {withResponse, withNotification, withResponseAndRequest} def
111
+ handlers <- parts WithMessage {withResponse, withNotification, withResponseAndRequest, withInitialize } def
107
112
108
113
let initializeCallbacks = LSP. InitializeCallbacks
109
- { LSP. onInitialConfiguration = Right . parseConfiguration
110
- , LSP. onConfigurationChange = const $ Left " Configuration changes not supported yet "
114
+ { LSP. onInitialConfiguration = onInitialConfig
115
+ , LSP. onConfigurationChange = onConfigChange
111
116
, LSP. onStartup = handleInit (signalBarrier clientMsgBarrier () ) clearReqId waitForCancel clientMsgChan
112
117
}
113
118
@@ -122,13 +127,11 @@ runLanguageServer options userHandlers getIdeState = do
122
127
, void $ waitBarrier clientMsgBarrier
123
128
]
124
129
where
125
- handleInit :: IO () -> (LspId -> IO () ) -> (LspId -> IO () ) -> Chan Message -> LSP. LspFuncs IdeConfiguration -> IO (Maybe err )
130
+ handleInit :: IO () -> (LspId -> IO () ) -> (LspId -> IO () ) -> Chan ( Message config ) -> LSP. LspFuncs config -> IO (Maybe err )
126
131
handleInit exitClientMsg clearReqId waitForCancel clientMsgChan lspFuncs@ LSP. LspFuncs {.. } = do
127
132
128
133
ide <- getIdeState getNextReqId sendFunc (makeLSPVFSHandle lspFuncs) clientCapabilities
129
134
130
- mapM_ (registerIdeConfiguration (shakeExtras ide)) =<< config
131
-
132
135
_ <- flip forkFinally (const exitClientMsg) $ forever $ do
133
136
msg <- readChan clientMsgChan
134
137
case msg of
@@ -152,6 +155,12 @@ runLanguageServer options userHandlers getIdeState = do
152
155
Just (rm, newReqParams) -> do
153
156
reqId <- getNextReqId
154
157
sendFunc $ wrapNewReq $ RequestMessage " 2.0" reqId rm newReqParams
158
+ InitialParams x@ RequestMessage {_id, _params} act -> do
159
+ catch (act lspFuncs ide _params) $ \ (e :: SomeException ) ->
160
+ logError (ideLogger ide) $ T. pack $
161
+ " Unexpected exception on InitializeRequest handler, please report!\n " ++
162
+ " Message: " ++ show x ++ " \n " ++
163
+ " Exception: " ++ show e
155
164
pure Nothing
156
165
157
166
checkCancelled ide clearReqId waitForCancel lspFuncs@ LSP. LspFuncs {.. } wrap act msg _id _params k =
@@ -177,17 +186,28 @@ runLanguageServer options userHandlers getIdeState = do
177
186
sendFunc $ wrap $ ResponseMessage " 2.0" (responseId _id) Nothing $
178
187
Just $ ResponseError InternalError (T. pack $ show e) Nothing
179
188
189
+ initializeRequestHandler :: PartialHandlers config
190
+ initializeRequestHandler = PartialHandlers $ \ WithMessage {.. } x -> return x{
191
+ LSP. initializeRequestHandler = withInitialize initHandler
192
+ }
193
+
194
+ initHandler
195
+ :: LSP. LspFuncs c
196
+ -> IdeState
197
+ -> InitializeParams
198
+ -> IO ()
199
+ initHandler _ ide params = registerIdeConfiguration (shakeExtras ide) (parseConfiguration params)
180
200
181
201
-- | Things that get sent to us, but we don't deal with.
182
202
-- Set them to avoid a warning in VS Code output.
183
- setHandlersIgnore :: PartialHandlers
203
+ setHandlersIgnore :: PartialHandlers config
184
204
setHandlersIgnore = PartialHandlers $ \ _ x -> return x
185
205
{LSP. initializedHandler = none
186
206
,LSP. responseHandler = none
187
207
}
188
208
where none = Just $ const $ return ()
189
209
190
- cancelHandler :: (LspId -> IO () ) -> PartialHandlers
210
+ cancelHandler :: (LspId -> IO () ) -> PartialHandlers config
191
211
cancelHandler cancelRequest = PartialHandlers $ \ _ x -> return x
192
212
{LSP. cancelNotificationHandler = Just $ \ msg@ NotificationMessage {_params = CancelParams {_id}} -> do
193
213
cancelRequest _id
@@ -197,14 +217,15 @@ cancelHandler cancelRequest = PartialHandlers $ \_ x -> return x
197
217
198
218
-- | A message that we need to deal with - the pieces are split up with existentials to gain additional type safety
199
219
-- and defer precise processing until later (allows us to keep at a higher level of abstraction slightly longer)
200
- data Message
201
- = forall m req resp . (Show m , Show req ) => Response (RequestMessage m req resp ) (ResponseMessage resp -> FromServerMessage ) (LSP. LspFuncs IdeConfiguration -> IdeState -> req -> IO (Either ResponseError resp ))
220
+ data Message c
221
+ = forall m req resp . (Show m , Show req ) => Response (RequestMessage m req resp ) (ResponseMessage resp -> FromServerMessage ) (LSP. LspFuncs c -> IdeState -> req -> IO (Either ResponseError resp ))
202
222
-- | Used for cases in which we need to send not only a response,
203
223
-- but also an additional request to the client.
204
224
-- For example, 'executeCommand' may generate an 'applyWorkspaceEdit' request.
205
- | forall m rm req resp newReqParams newReqBody . (Show m , Show rm , Show req ) => ResponseAndRequest (RequestMessage m req resp ) (ResponseMessage resp -> FromServerMessage ) (RequestMessage rm newReqParams newReqBody -> FromServerMessage ) (LSP. LspFuncs IdeConfiguration -> IdeState -> req -> IO (resp , Maybe (rm , newReqParams )))
206
- | forall m req . (Show m , Show req ) => Notification (NotificationMessage m req ) (LSP. LspFuncs IdeConfiguration -> IdeState -> req -> IO () )
207
-
225
+ | forall m rm req resp newReqParams newReqBody . (Show m , Show rm , Show req ) => ResponseAndRequest (RequestMessage m req resp ) (ResponseMessage resp -> FromServerMessage ) (RequestMessage rm newReqParams newReqBody -> FromServerMessage ) (LSP. LspFuncs c -> IdeState -> req -> IO (resp , Maybe (rm , newReqParams )))
226
+ | forall m req . (Show m , Show req ) => Notification (NotificationMessage m req ) (LSP. LspFuncs c -> IdeState -> req -> IO () )
227
+ -- | Used for the InitializeRequest only, where the response is generated by the LSP core handler.
228
+ | InitialParams InitializeRequest (LSP. LspFuncs c -> IdeState -> InitializeParams -> IO () )
208
229
209
230
modifyOptions :: LSP. Options -> LSP. Options
210
231
modifyOptions x = x{ LSP. textDocumentSync = Just $ tweakTDS origTDS
0 commit comments