@@ -3,28 +3,42 @@ module Test.Hls.Util
33 (
44 codeActionSupportCaps
55 , dummyLspFuncs
6+ , expectCodeAction
7+ , expectDiagnostic
68 , flushStackEnvironment
9+ , fromAction
10+ , fromCommand
711 , getHspecFormattedConfig
812 , ghcVersion , GhcVersion (.. )
913 , hlsCommand
1014 , hlsCommandExamplePlugin
1115 , hlsCommandVomit
16+ , inspectCodeAction
17+ , inspectCommand
18+ , inspectDiagnostic
1219 , logConfig
1320 , logFilePath
1421 , noLogConfig
1522 , setupBuildToolFiles
23+ , waitForDiagnosticsFrom
24+ , waitForDiagnosticsFromSource
1625 , withFileLogging
1726 , withCurrentDirectoryInTmp
1827 )
1928where
2029
2130import Control.Monad
31+ import Control.Applicative.Combinators (skipManyTill )
32+ import Control.Lens ((^.) )
2233import Data.Default
2334import Data.List (intercalate )
35+ import Data.List.Extra (find )
2436import Data.Maybe
37+ import qualified Data.Text as T
2538import Language.Haskell.LSP.Core
2639import Language.Haskell.LSP.Types
2740import qualified Language.Haskell.LSP.Test as T
41+ import qualified Language.Haskell.LSP.Types.Lens as L
2842import qualified Language.Haskell.LSP.Types.Capabilities as C
2943import System.Directory
3044import System.Environment
@@ -35,7 +49,7 @@ import System.IO.Unsafe
3549import Test.Hspec.Runner
3650import Test.Hspec.Core.Formatters
3751import Text.Blaze.Renderer.String (renderMarkup )
38- import Text.Blaze.Internal
52+ import Text.Blaze.Internal hiding ( null )
3953
4054
4155noLogConfig :: T. SessionConfig
@@ -282,3 +296,56 @@ copyDir src dst = do
282296 then createDirectory dstFp >> copyDir srcFp dstFp
283297 else copyFile srcFp dstFp
284298 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