@@ -3,28 +3,42 @@ module Test.Hls.Util
3
3
(
4
4
codeActionSupportCaps
5
5
, dummyLspFuncs
6
+ , expectCodeAction
7
+ , expectDiagnostic
6
8
, flushStackEnvironment
9
+ , fromAction
10
+ , fromCommand
7
11
, getHspecFormattedConfig
8
12
, ghcVersion , GhcVersion (.. )
9
13
, hlsCommand
10
14
, hlsCommandExamplePlugin
11
15
, hlsCommandVomit
16
+ , inspectCodeAction
17
+ , inspectCommand
18
+ , inspectDiagnostic
12
19
, logConfig
13
20
, logFilePath
14
21
, noLogConfig
15
22
, setupBuildToolFiles
23
+ , waitForDiagnosticsFrom
24
+ , waitForDiagnosticsFromSource
16
25
, withFileLogging
17
26
, withCurrentDirectoryInTmp
18
27
)
19
28
where
20
29
21
30
import Control.Monad
31
+ import Control.Applicative.Combinators (skipManyTill )
32
+ import Control.Lens ((^.) )
22
33
import Data.Default
23
34
import Data.List (intercalate )
35
+ import Data.List.Extra (find )
24
36
import Data.Maybe
37
+ import qualified Data.Text as T
25
38
import Language.Haskell.LSP.Core
26
39
import Language.Haskell.LSP.Types
27
40
import qualified Language.Haskell.LSP.Test as T
41
+ import qualified Language.Haskell.LSP.Types.Lens as L
28
42
import qualified Language.Haskell.LSP.Types.Capabilities as C
29
43
import System.Directory
30
44
import System.Environment
@@ -35,7 +49,7 @@ import System.IO.Unsafe
35
49
import Test.Hspec.Runner
36
50
import Test.Hspec.Core.Formatters
37
51
import Text.Blaze.Renderer.String (renderMarkup )
38
- import Text.Blaze.Internal
52
+ import Text.Blaze.Internal hiding ( null )
39
53
40
54
41
55
noLogConfig :: T. SessionConfig
@@ -282,3 +296,56 @@ copyDir src dst = do
282
296
then createDirectory dstFp >> copyDir srcFp dstFp
283
297
else copyFile srcFp dstFp
284
298
where ignored = [" dist" , " dist-newstyle" , " .stack-work" ]
299
+
300
+ fromAction :: CAResult -> CodeAction
301
+ fromAction (CACodeAction action) = action
302
+ fromAction _ = error " Not a code action"
303
+
304
+ fromCommand :: CAResult -> Command
305
+ fromCommand (CACommand command) = command
306
+ fromCommand _ = error " Not a command"
307
+
308
+ onMatch :: [a ] -> (a -> Bool ) -> String -> IO a
309
+ onMatch as pred err = maybe (fail err) return (find pred as)
310
+
311
+ inspectDiagnostic :: [Diagnostic ] -> [T. Text ] -> IO Diagnostic
312
+ inspectDiagnostic diags s = onMatch diags (\ ca -> all (`T.isInfixOf` (ca ^. L. message)) s) err
313
+ where err = " expected diagnostic matching '" ++ show s ++ " ' but did not find one"
314
+
315
+ expectDiagnostic :: [Diagnostic ] -> [T. Text ] -> IO ()
316
+ expectDiagnostic diags s = void $ inspectDiagnostic diags s
317
+
318
+ inspectCodeAction :: [CAResult ] -> [T. Text ] -> IO CodeAction
319
+ inspectCodeAction cars s = fromAction <$> onMatch cars pred err
320
+ where pred (CACodeAction ca) = all (`T.isInfixOf` (ca ^. L. title)) s
321
+ pred _ = False
322
+ err = " expected code action matching '" ++ show s ++ " ' but did not find one"
323
+
324
+ expectCodeAction :: [CAResult ] -> [T. Text ] -> IO ()
325
+ expectCodeAction cars s = void $ inspectCodeAction cars s
326
+
327
+ inspectCommand :: [CAResult ] -> [T. Text ] -> IO Command
328
+ inspectCommand cars s = fromCommand <$> onMatch cars pred err
329
+ where pred (CACommand command) = all (`T.isInfixOf` (command ^. L. title)) s
330
+ pred _ = False
331
+ err = " expected code action matching '" ++ show s ++ " ' but did not find one"
332
+
333
+ waitForDiagnosticsFrom :: TextDocumentIdentifier -> T. Session [Diagnostic ]
334
+ waitForDiagnosticsFrom doc = do
335
+ diagsNot <- skipManyTill T. anyMessage T. message :: T. Session PublishDiagnosticsNotification
336
+ let (List diags) = diagsNot ^. L. params . L. diagnostics
337
+ if doc ^. L. uri /= diagsNot ^. L. params . L. uri
338
+ then waitForDiagnosticsFrom doc
339
+ else return diags
340
+
341
+ waitForDiagnosticsFromSource :: TextDocumentIdentifier -> String -> T. Session [Diagnostic ]
342
+ waitForDiagnosticsFromSource doc src = do
343
+ diagsNot <- skipManyTill T. anyMessage T. message :: T. Session PublishDiagnosticsNotification
344
+ let (List diags) = diagsNot ^. L. params . L. diagnostics
345
+ let res = filter matches diags
346
+ if doc ^. L. uri /= diagsNot ^. L. params . L. uri || null res
347
+ then waitForDiagnosticsFromSource doc src
348
+ else return res
349
+ where
350
+ matches :: Diagnostic -> Bool
351
+ matches d = d ^. L. source == Just (T. pack src)
0 commit comments