import Data.Aeson
import Data.Default
import qualified Data.HashMap.Strict as HM
+import Data.Maybe
import qualified Data.Text as T
+import Control.Applicative.Combinators
import Control.Concurrent
import Control.Monad.IO.Class
import Control.Monad
import Language.Haskell.LSP.Test
import Language.Haskell.LSP.Test.Replay
import Language.Haskell.LSP.Types.Capabilities
-import Language.Haskell.LSP.Types hiding (message, capabilities)
+import Language.Haskell.LSP.Types as LSP hiding (capabilities, message)
import System.Timeout
+{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
+{-# ANN module ("HLint: ignore Unnecessary hiding" :: String) #-}
+
main = hspec $ do
describe "Session" $ do
it "fails a test" $
noDiagnostics
contents <- documentContents doc
- liftIO $ contents `shouldBe` "main :: IO Int\nmain = return 42"
+ liftIO $ contents `shouldBe` "main :: IO Int\nmain = return 42\n"
describe "getDocumentEdit" $
it "automatically consumes applyedit requests" $
reqParams = ExecuteCommandParams "applyrefact:applyOne" (Just (List [args]))
sendRequest_ WorkspaceExecuteCommand reqParams
contents <- getDocumentEdit doc
- liftIO $ contents `shouldBe` "main :: IO Int\nmain = return 42"
+ liftIO $ contents `shouldBe` "main :: IO Int\nmain = return 42\n"
noDiagnostics
describe "getAllCodeActions" $
item ^. kind `shouldBe` Just CiFunction
item ^. detail `shouldBe` Just "Items -> IO ()\nMain"
+ describe "getReferences" $
+ it "works" $ runSession "hie --lsp" "test/data/renamePass" $ do
+ doc <- openDoc "Desktop/simple.hs" "haskell"
+ let pos = Position 40 3 -- interactWithUser
+ uri = doc ^. LSP.uri
+ refs <- getReferences doc pos True
+ liftIO $ refs `shouldContain` map (Location uri) [
+ mkRange 41 0 41 16
+ , mkRange 75 6 75 22
+ , mkRange 71 6 71 22
+ ]
+
+ describe "getDefinitions" $
+ it "works" $ runSession "hie --lsp" "test/data/renamePass" $ do
+ doc <- openDoc "Desktop/simple.hs" "haskell"
+ let pos = Position 49 25 -- addItem
+ defs <- getDefinitions doc pos
+ liftIO $ defs `shouldBe` [Location (doc ^. uri) (mkRange 28 0 28 7)]
+
+ describe "waitForDiagnosticsSource" $
+ it "works" $ runSession "hie --lsp" "test/data" $ do
+ openDoc "Error.hs" "haskell"
+ [diag] <- waitForDiagnosticsSource "ghcmod"
+ liftIO $ do
+ diag ^. severity `shouldBe` Just DsError
+ diag ^. source `shouldBe` Just "ghcmod"
+
+ describe "rename" $
+ it "works" $ runSession "hie --lsp" "test/data" $ do
+ doc <- openDoc "Rename.hs" "haskell"
+ rename doc (Position 1 0) "bar"
+ documentContents doc >>= liftIO . shouldBe "main = bar\nbar = return 42\n"
+
+ describe "getHover" $
+ it "works" $ runSession "hie --lsp" "test/data/renamePass" $ do
+ doc <- openDoc "Desktop/simple.hs" "haskell"
+ -- hover returns nothing until module is loaded
+ skipManyTill loggingNotification $ count 2 noDiagnostics
+ hover <- getHover doc (Position 45 9) -- putStrLn
+ liftIO $ hover `shouldSatisfy` isJust
+
+ describe "getHighlights" $
+ it "works" $ runSession "hie --lsp" "test/data/renamePass" $ do
+ doc <- openDoc "Desktop/simple.hs" "haskell"
+ skipManyTill loggingNotification $ count 2 noDiagnostics
+ highlights <- getHighlights doc (Position 27 4) -- addItem
+ liftIO $ length highlights `shouldBe` 4
+
+ describe "formatDoc" $
+ it "works" $ runSession "hie --lsp" "test/data" $ do
+ doc <- openDoc "Format.hs" "haskell"
+ oldContents <- documentContents doc
+ formatDoc doc (FormattingOptions 4 True)
+ documentContents doc >>= liftIO . (`shouldNotBe` oldContents)
+
+ describe "formatRange" $
+ it "works" $ runSession "hie --lsp" "test/data" $ do
+ doc <- openDoc "Format.hs" "haskell"
+ oldContents <- documentContents doc
+ formatRange doc (FormattingOptions 4 True) (Range (Position 1 10) (Position 2 10))
+ documentContents doc >>= liftIO . (`shouldNotBe` oldContents)
+
+ describe "closeDoc" $
+ it "works" $
+ let sesh =
+ runSession "hie --lsp" "test/data" $ do
+ doc <- openDoc "Format.hs" "haskell"
+ closeDoc doc
+ -- need to evaluate to throw
+ documentContents doc >>= liftIO . print
+ in sesh `shouldThrow` anyException
+
+mkRange sl sc el ec = Range (Position sl sc) (Position el ec)
didChangeCaps :: ClientCapabilities
didChangeCaps = def { _workspace = Just workspaceCaps }