@@ -59,6 +59,7 @@ import Control.Concurrent.STM ( atomically, readTVarIO, modifyTVar
59
59
import Control.Monad ( when , unless )
60
60
import Control.Monad.Except ( runExceptT , throwError )
61
61
import Control.Monad.State ( runStateT , gets , MonadIO (liftIO ), gets , modify' )
62
+ import Control.Monad.Reader
62
63
import Data.Aeson ( FromJSON , Result (.. ), fromJSON )
63
64
import Data.Aeson.Encode.Pretty ( encodePretty )
64
65
import Data.Aeson.Types ( object , Key , KeyValue ((.=) ), ToJSON )
@@ -68,23 +69,25 @@ import System.IO ( Handle )
68
69
import qualified Data.ByteString.Lazy.Char8 as BL8
69
70
import qualified Data.ByteString.Char8 as BS
70
71
import qualified Data.HashMap.Strict as H
72
+ import GHC.Stack
73
+ import Data.IORef
71
74
----------------------------------------------------------------------------
72
75
import DAP.Types
73
76
import DAP.Utils
74
77
import DAP.Internal
75
78
----------------------------------------------------------------------------
76
- logWarn :: BL8. ByteString -> Adaptor app ()
79
+ logWarn :: BL8. ByteString -> Adaptor app r ()
77
80
logWarn msg = logWithAddr WARN Nothing (withBraces msg)
78
81
----------------------------------------------------------------------------
79
- logError :: BL8. ByteString -> Adaptor app ()
82
+ logError :: BL8. ByteString -> Adaptor app r ()
80
83
logError msg = logWithAddr ERROR Nothing (withBraces msg)
81
84
----------------------------------------------------------------------------
82
- logInfo :: BL8. ByteString -> Adaptor app ()
85
+ logInfo :: BL8. ByteString -> Adaptor app r ()
83
86
logInfo msg = logWithAddr INFO Nothing (withBraces msg)
84
87
----------------------------------------------------------------------------
85
88
-- | Meant for internal consumption, used to signify a message has been
86
89
-- SENT from the server
87
- debugMessage :: BL8. ByteString -> Adaptor app ()
90
+ debugMessage :: BL8. ByteString -> Adaptor app r ()
88
91
debugMessage msg = do
89
92
shouldLog <- getDebugLogging
90
93
addr <- getAddress
@@ -93,7 +96,7 @@ debugMessage msg = do
93
96
$ logger DEBUG addr (Just SENT ) msg
94
97
----------------------------------------------------------------------------
95
98
-- | Meant for external consumption
96
- logWithAddr :: Level -> Maybe DebugStatus -> BL8. ByteString -> Adaptor app ()
99
+ logWithAddr :: Level -> Maybe DebugStatus -> BL8. ByteString -> Adaptor app r ()
97
100
logWithAddr level status msg = do
98
101
addr <- getAddress
99
102
liftIO (logger level addr status msg)
@@ -113,38 +116,42 @@ logger level addr maybeDebug msg = do
113
116
, msg
114
117
]
115
118
----------------------------------------------------------------------------
116
- getDebugLogging :: Adaptor app Bool
117
- getDebugLogging = gets (debugLogging . serverConfig)
119
+ getDebugLogging :: Adaptor app r Bool
120
+ getDebugLogging = asks (debugLogging . serverConfig)
118
121
----------------------------------------------------------------------------
119
- getServerCapabilities :: Adaptor app Capabilities
120
- getServerCapabilities = gets (serverCapabilities . serverConfig)
122
+ getServerCapabilities :: Adaptor app r Capabilities
123
+ getServerCapabilities = asks (serverCapabilities . serverConfig)
121
124
----------------------------------------------------------------------------
122
- getAddress :: Adaptor app SockAddr
123
- getAddress = gets address
125
+ getAddress :: Adaptor app r SockAddr
126
+ getAddress = asks address
124
127
----------------------------------------------------------------------------
125
- getHandle :: Adaptor app Handle
126
- getHandle = gets handle
128
+ getHandle :: Adaptor app r Handle
129
+ getHandle = asks handle
127
130
----------------------------------------------------------------------------
128
- getRequestSeqNum :: Adaptor app Seq
129
- getRequestSeqNum = gets (requestSeqNum . request)
131
+ getRequestSeqNum :: Adaptor app Request Seq
132
+ getRequestSeqNum = asks (requestSeqNum . request)
130
133
----------------------------------------------------------------------------
131
- getDebugSessionId :: Adaptor app SessionId
134
+ getDebugSessionId :: Adaptor app r SessionId
132
135
getDebugSessionId = do
133
- gets sessionId >>= \ case
136
+ var <- asks (sessionId)
137
+ res <- liftIO $ readIORef var
138
+ case res of
134
139
Nothing -> sessionNotFound
135
140
Just sessionId -> pure sessionId
136
141
where
137
142
sessionNotFound = do
138
143
let err = " No Debug Session has started"
139
144
sendError (ErrorMessage (pack err)) Nothing
140
145
----------------------------------------------------------------------------
141
- setDebugSessionId :: SessionId -> Adaptor app ()
142
- setDebugSessionId session = modify' $ \ s -> s { sessionId = Just session }
146
+ setDebugSessionId :: SessionId -> Adaptor app r ()
147
+ setDebugSessionId session = do
148
+ var <- asks sessionId
149
+ liftIO $ writeIORef var (Just session)
143
150
----------------------------------------------------------------------------
144
151
registerNewDebugSession
145
152
:: SessionId
146
153
-> app
147
- -> [(( Adaptor app () -> IO () ) -> IO () )]
154
+ -> [(Adaptor app () () -> IO () ) -> IO () ]
148
155
-- ^ Actions to run debugger (operates in a forked thread that gets killed when disconnect is set)
149
156
-- Long running operation, meant to be used as a sink for
150
157
-- the debugger to emit events and for the adaptor to forward to the editor
@@ -161,29 +168,32 @@ registerNewDebugSession
161
168
-- > withAdaptor $ sendOutputEvent defaultOutputEvent { outputEventOutput = output }
162
169
-- > ]
163
170
--
164
- -> Adaptor app ()
171
+ -> Adaptor app r ()
165
172
registerNewDebugSession k v debuggerConcurrentActions = do
166
- store <- gets appStore
167
- adaptorStateMVar <- gets adaptorStateMVar
173
+ store <- asks appStore
174
+ lcl <- ask
175
+ let lcl' = lcl { request = () }
176
+ let emptyState = AdaptorState MessageTypeEvent []
168
177
debuggerThreadState <- liftIO $
169
178
DebuggerThreadState
170
- <$> sequence [fork $ action (runAdaptorWith adaptorStateMVar ) | action <- debuggerConcurrentActions]
179
+ <$> sequence [fork $ action (runAdaptorWith lcl' emptyState " s " ) | action <- debuggerConcurrentActions]
171
180
liftIO . atomically $ modifyTVar' store (H. insert k (debuggerThreadState, v))
172
- setDebugSessionId k
173
181
logInfo $ BL8. pack $ " Registered new debug session: " <> unpack k
182
+ setDebugSessionId k
183
+
174
184
----------------------------------------------------------------------------
175
- updateDebugSession :: (app -> app ) -> Adaptor app ()
185
+ updateDebugSession :: (app -> app ) -> Adaptor app r ()
176
186
updateDebugSession updateFun = do
177
187
sessionId <- getDebugSessionId
178
- store <- gets appStore
188
+ store <- asks appStore
179
189
liftIO . atomically $ modifyTVar' store (H. adjust (fmap updateFun) sessionId)
180
190
----------------------------------------------------------------------------
181
- getDebugSession :: Adaptor a a
191
+ getDebugSession :: Adaptor a r a
182
192
getDebugSession = do
183
193
(_, _, app) <- getDebugSessionWithThreadIdAndSessionId
184
194
pure app
185
195
----------------------------------------------------------------------------
186
- getDebugSessionWithThreadIdAndSessionId :: Adaptor app (SessionId , DebuggerThreadState , app )
196
+ getDebugSessionWithThreadIdAndSessionId :: Adaptor app r (SessionId , DebuggerThreadState , app )
187
197
getDebugSessionWithThreadIdAndSessionId = do
188
198
sessionId <- getDebugSessionId
189
199
appStore <- liftIO . readTVarIO =<< getAppStore
@@ -203,7 +213,7 @@ getDebugSessionWithThreadIdAndSessionId = do
203
213
-- | Whenever a debug Session ends (cleanly or otherwise) this function
204
214
-- will remove the local debugger communication state from the global state
205
215
----------------------------------------------------------------------------
206
- destroyDebugSession :: Adaptor app ()
216
+ destroyDebugSession :: Adaptor app r ()
207
217
destroyDebugSession = do
208
218
(sessionId, DebuggerThreadState {.. }, _) <- getDebugSessionWithThreadIdAndSessionId
209
219
store <- getAppStore
@@ -212,17 +222,17 @@ destroyDebugSession = do
212
222
atomically $ modifyTVar' store (H. delete sessionId)
213
223
logInfo $ BL8. pack $ " SessionId " <> unpack sessionId <> " ended"
214
224
----------------------------------------------------------------------------
215
- getAppStore :: Adaptor app (AppStore app )
216
- getAppStore = gets appStore
225
+ getAppStore :: Adaptor app r (AppStore app )
226
+ getAppStore = asks appStore
217
227
----------------------------------------------------------------------------
218
- getCommand :: Adaptor app Command
219
- getCommand = command <$> gets request
228
+ getCommand :: Adaptor app Request Command
229
+ getCommand = command <$> asks request
220
230
----------------------------------------------------------------------------
221
231
-- | 'sendRaw' (internal use only)
222
232
-- Sends a raw JSON payload to the editor. No "seq", "type" or "command" fields are set.
223
233
-- The message is still encoded with the ProtocolMessage Header, byte count, and CRLF.
224
234
--
225
- sendRaw :: ToJSON value => value -> Adaptor app ()
235
+ sendRaw :: ToJSON value => value -> Adaptor app r ()
226
236
sendRaw value = do
227
237
handle <- getHandle
228
238
address <- getAddress
@@ -234,7 +244,7 @@ sendRaw value = do
234
244
-- i.e. "request_seq" and "command".
235
245
-- We also have to be sure to reset the message payload
236
246
----------------------------------------------------------------------------
237
- send :: Adaptor app () -> Adaptor app ()
247
+ send :: Adaptor app Request () -> Adaptor app Request ()
238
248
send action = do
239
249
() <- action
240
250
cmd <- getCommand
@@ -258,9 +268,28 @@ send action = do
258
268
259
269
-- Send payload to client from debug adaptor
260
270
writeToHandle address handle payload
271
+ resetAdaptorStatePayload
272
+
273
+ sendEvent :: Adaptor app r () -> Adaptor app r ()
274
+ sendEvent action = do
275
+ () <- action
276
+ handle <- getHandle
277
+ messageType <- gets messageType
278
+ address <- getAddress
279
+ case messageType of
280
+ MessageTypeResponse -> error " use send"
281
+ MessageTypeRequest -> error " use send"
282
+ MessageTypeEvent -> do
283
+ address <- getAddress
284
+ setField " type" messageType
261
285
262
- -- Reset payload each time a send occurs
286
+ -- Once all fields are set, fetch the payload for sending
287
+ payload <- object <$> gets payload
288
+ -- Send payload to client from debug adaptor
289
+ writeToHandle address handle payload
263
290
resetAdaptorStatePayload
291
+
292
+
264
293
----------------------------------------------------------------------------
265
294
-- | Writes payload to the given 'Handle' using the local connection lock
266
295
----------------------------------------------------------------------------
@@ -269,31 +298,31 @@ writeToHandle
269
298
=> SockAddr
270
299
-> Handle
271
300
-> event
272
- -> Adaptor app ()
301
+ -> Adaptor app r ()
273
302
writeToHandle _ handle evt = do
274
303
let msg = encodeBaseProtocolMessage evt
275
304
debugMessage (" \n " <> encodePretty evt)
276
305
withConnectionLock (BS. hPutStr handle msg)
277
306
----------------------------------------------------------------------------
278
307
-- | Resets Adaptor's payload
279
308
----------------------------------------------------------------------------
280
- resetAdaptorStatePayload :: Adaptor app ()
309
+ resetAdaptorStatePayload :: Adaptor app r ()
281
310
resetAdaptorStatePayload = modify' $ \ s -> s { payload = [] }
282
311
----------------------------------------------------------------------------
283
- sendSuccesfulResponse :: Adaptor app () -> Adaptor app ()
312
+ sendSuccesfulResponse :: Adaptor app Request () -> Adaptor app Request ()
284
313
sendSuccesfulResponse action = do
285
314
send $ do
286
315
setType MessageTypeResponse
287
316
setSuccess True
288
317
action
289
318
----------------------------------------------------------------------------
290
- sendSuccesfulEmptyResponse :: Adaptor app ()
319
+ sendSuccesfulEmptyResponse :: Adaptor app Request ()
291
320
sendSuccesfulEmptyResponse = sendSuccesfulResponse (pure () )
292
321
----------------------------------------------------------------------------
293
322
-- | Sends successful event
294
- sendSuccesfulEvent :: EventType -> Adaptor app () -> Adaptor app ()
323
+ sendSuccesfulEvent :: EventType -> Adaptor app r () -> Adaptor app r ()
295
324
sendSuccesfulEvent event action = do
296
- send $ do
325
+ sendEvent $ do
297
326
setEvent event
298
327
setType MessageTypeEvent
299
328
action
@@ -305,7 +334,7 @@ sendSuccesfulEvent event action = do
305
334
sendError
306
335
:: ErrorMessage
307
336
-> Maybe Message
308
- -> Adaptor app a
337
+ -> Adaptor app r a
309
338
sendError errorMessage maybeMessage = do
310
339
throwError (errorMessage, maybeMessage)
311
340
----------------------------------------------------------------------------
@@ -314,7 +343,7 @@ sendError errorMessage maybeMessage = do
314
343
sendErrorResponse
315
344
:: ErrorMessage
316
345
-> Maybe Message
317
- -> Adaptor app ()
346
+ -> Adaptor app Request ()
318
347
sendErrorResponse errorMessage maybeMessage = do
319
348
send $ do
320
349
setType MessageTypeResponse
@@ -324,24 +353,24 @@ sendErrorResponse errorMessage maybeMessage = do
324
353
----------------------------------------------------------------------------
325
354
setErrorMessage
326
355
:: ErrorMessage
327
- -> Adaptor app ()
356
+ -> Adaptor app r ()
328
357
setErrorMessage v = setField " message" v
329
358
----------------------------------------------------------------------------
330
359
-- | Sends successful event
331
360
setSuccess
332
361
:: Bool
333
- -> Adaptor app ()
362
+ -> Adaptor app r ()
334
363
setSuccess = setField " success"
335
364
----------------------------------------------------------------------------
336
365
setBody
337
366
:: ToJSON value
338
367
=> value
339
- -> Adaptor app ()
368
+ -> Adaptor app r ()
340
369
setBody value = setField " body" value
341
370
----------------------------------------------------------------------------
342
371
setType
343
372
:: MessageType
344
- -> Adaptor app ()
373
+ -> Adaptor app r ()
345
374
setType messageType = do
346
375
modify' $ \ adaptorState ->
347
376
adaptorState
@@ -350,14 +379,14 @@ setType messageType = do
350
379
----------------------------------------------------------------------------
351
380
setEvent
352
381
:: EventType
353
- -> Adaptor app ()
382
+ -> Adaptor app r ()
354
383
setEvent = setField " event"
355
384
----------------------------------------------------------------------------
356
385
setField
357
386
:: ToJSON value
358
387
=> Key
359
388
-> value
360
- -> Adaptor app ()
389
+ -> Adaptor app r ()
361
390
setField key value = do
362
391
currentPayload <- gets payload
363
392
modify' $ \ adaptorState ->
@@ -367,18 +396,18 @@ setField key value = do
367
396
----------------------------------------------------------------------------
368
397
withConnectionLock
369
398
:: IO ()
370
- -> Adaptor app ()
399
+ -> Adaptor app r ()
371
400
withConnectionLock action = do
372
- lock <- gets handleLock
401
+ lock <- asks handleLock
373
402
liftIO (withLock lock action)
374
403
----------------------------------------------------------------------------
375
404
-- | Attempt to parse arguments from the Request
376
405
----------------------------------------------------------------------------
377
406
getArguments
378
407
:: (Show value , FromJSON value )
379
- => Adaptor app value
408
+ => Adaptor app Request value
380
409
getArguments = do
381
- maybeArgs <- gets (args . request)
410
+ maybeArgs <- asks (args . request)
382
411
let msg = " No args found for this message"
383
412
case maybeArgs of
384
413
Nothing -> do
@@ -393,15 +422,16 @@ getArguments = do
393
422
394
423
----------------------------------------------------------------------------
395
424
-- | Evaluates Adaptor action by using and updating the state in the MVar
396
- runAdaptorWith :: MVar (AdaptorState app ) -> Adaptor app () -> IO ()
397
- runAdaptorWith adaptorStateMVar action = do
398
- modifyMVar_ adaptorStateMVar (flip runAdaptor (resetAdaptorStatePayload >> action))
425
+ runAdaptorWith :: AdaptorLocal app r -> AdaptorState -> String -> Adaptor app r () -> IO ()
426
+ runAdaptorWith lcl st s (Adaptor action) = do
427
+ runStateT (runReaderT (runExceptT action) lcl) st
428
+ return ()
399
429
400
430
----------------------------------------------------------------------------
401
431
-- | Utility for evaluating a monad transformer stack
402
- runAdaptor :: AdaptorState app -> Adaptor app () -> IO (AdaptorState app )
403
- runAdaptor adaptorState (Adaptor client) =
404
- runStateT (runExceptT client) adaptorState >>= \ case
405
- (Left (errorMessage, maybeMessage), nextState ) ->
406
- runAdaptor nextState (sendErrorResponse errorMessage maybeMessage)
407
- (Right () , nextState ) -> pure nextState
432
+ runAdaptor :: AdaptorLocal app Request -> AdaptorState -> Adaptor app Request () -> IO ()
433
+ runAdaptor lcl s (Adaptor client) =
434
+ runStateT (runReaderT ( runExceptT client) lcl) s >>= \ case
435
+ (Left (errorMessage, maybeMessage), s' ) ->
436
+ runAdaptor lcl s' (sendErrorResponse errorMessage maybeMessage)
437
+ (Right () , s' ) -> pure ()
0 commit comments