hie-core-0.0.1: test/src/Development/IDE/Test.hs
-- Copyright (c) 2019 The DAML Authors. All rights reserved.
-- SPDX-License-Identifier: Apache-2.0
module Development.IDE.Test
( Cursor
, cursorPosition
, requireDiagnostic
, expectDiagnostics
) where
import Control.Applicative.Combinators
import Control.Lens hiding (List)
import Control.Monad
import Control.Monad.IO.Class
import qualified Data.Map.Strict as Map
import qualified Data.Text as T
import Language.Haskell.LSP.Test hiding (message, openDoc')
import qualified Language.Haskell.LSP.Test as LspTest
import Language.Haskell.LSP.Types
import Language.Haskell.LSP.Types.Lens as Lsp
import Test.Tasty.HUnit
-- | (0-based line number, 0-based column number)
type Cursor = (Int, Int)
cursorPosition :: Cursor -> Position
cursorPosition (line, col) = Position line col
requireDiagnostic :: List Diagnostic -> (DiagnosticSeverity, Cursor, T.Text) -> Assertion
requireDiagnostic actuals expected@(severity, cursor, expectedMsg) = do
unless (any match actuals) $
assertFailure $
"Could not find " <> show expected <>
" in " <> show actuals
where
match :: Diagnostic -> Bool
match d =
Just severity == _severity d
&& cursorPosition cursor == d ^. range . start
&& standardizeQuotes (T.toLower expectedMsg) `T.isInfixOf`
standardizeQuotes (T.toLower $ d ^. message)
expectDiagnostics :: [(FilePath, [(DiagnosticSeverity, Cursor, T.Text)])] -> Session ()
expectDiagnostics expected = do
expected' <- Map.fromListWith (<>) <$> traverseOf (traverse . _1) (fmap toNormalizedUri . getDocUri) expected
go expected'
where
go m
| Map.null m = pure ()
| otherwise = do
diagsNot <- skipManyTill anyMessage LspTest.message :: Session PublishDiagnosticsNotification
let fileUri = diagsNot ^. params . uri
case Map.lookup (diagsNot ^. params . uri . to toNormalizedUri) m of
Nothing -> do
let actual = diagsNot ^. params . diagnostics
liftIO $ assertFailure $
"Got diagnostics for " <> show fileUri <>
" but only expected diagnostics for " <> show (Map.keys m) <>
" got " <> show actual
Just expected -> do
let actual = diagsNot ^. params . diagnostics
liftIO $ mapM_ (requireDiagnostic actual) expected
liftIO $ unless (length expected == length actual) $
assertFailure $
"Incorrect number of diagnostics for " <> show fileUri <>
", expected " <> show expected <>
" but got " <> show actual
go $ Map.delete (diagsNot ^. params . uri . to toNormalizedUri) m
standardizeQuotes :: T.Text -> T.Text
standardizeQuotes msg = let
repl '‘' = '\''
repl '’' = '\''
repl '`' = '\''
repl c = c
in T.map repl msg