{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE TypeOperators #-} module Splice (tests) where import Control.Applicative.Combinators import Control.Monad import Control.Monad.IO.Class import Data.List (find) import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.IO as T import Ide.Plugin.Splice.Types import Language.LSP.Test import Language.LSP.Types import System.Directory import System.FilePath import System.Time.Extra (sleep) import Test.Hls.Util import Test.Tasty import Test.Tasty.HUnit tests :: TestTree tests = testGroup "splice" [ goldenTest "TSimpleExp.hs" Inplace 6 15 , goldenTest "TSimpleExp.hs" Inplace 6 24 , goldenTest "TTypeAppExp.hs" Inplace 7 5 , goldenTest "TErrorExp.hs" Inplace 6 15 , goldenTest "TErrorExp.hs" Inplace 6 51 , goldenTest "TQQExp.hs" Inplace 6 17 , goldenTest "TQQExp.hs" Inplace 6 25 , goldenTest "TQQExpError.hs" Inplace 6 13 , goldenTest "TQQExpError.hs" Inplace 6 22 , testGroup "Pattern Splices" [ goldenTest "TSimplePat.hs" Inplace 6 3 , goldenTest "TSimplePat.hs" Inplace 6 22 , goldenTest "TSimplePat.hs" Inplace 6 3 , goldenTest "TSimplePat.hs" Inplace 6 22 , goldenTest "TErrorPat.hs" Inplace 6 3 , goldenTest "TErrorPat.hs" Inplace 6 18 , goldenTest "TQQPat.hs" Inplace 6 3 , goldenTest "TQQPat.hs" Inplace 6 11 , goldenTest "TQQPatError.hs" Inplace 6 3 , goldenTest "TQQPatError.hs" Inplace 6 11 ] , goldenTest "TSimpleType.hs" Inplace 5 12 , goldenTest "TSimpleType.hs" Inplace 5 22 , goldenTest "TTypeTypeError.hs" Inplace 7 12 , goldenTest "TTypeTypeError.hs" Inplace 7 52 , goldenTest "TQQType.hs" Inplace 8 19 , goldenTest "TQQType.hs" Inplace 8 28 , goldenTest "TQQTypeTypeError.hs" Inplace 8 19 , goldenTest "TQQTypeTypeError.hs" Inplace 8 28 , goldenTest "TSimpleDecl.hs" Inplace 8 1 , goldenTest "TQQDecl.hs" Inplace 5 1 , goldenTestWithEdit "TTypeKindError.hs" Inplace 7 9 , goldenTestWithEdit "TDeclKindError.hs" Inplace 8 1 ] goldenTest :: FilePath -> ExpandStyle -> Int -> Int -> TestTree goldenTest input tc line col = testCase (input <> " (golden)") $ do runSession hlsCommand fullCaps spliceTestPath $ do doc <- openDoc input "haskell" _ <- waitForDiagnostics actions <- getCodeActions doc $ pointRange line col case find ((== Just (toExpandCmdTitle tc)) . codeActionTitle) actions of Just (InR CodeAction {_command = Just c}) -> do executeCommand c _resp <- skipManyTill anyMessage (message SWorkspaceApplyEdit) edited <- documentContents doc let expected_name = spliceTestPath input <.> "expected" -- Write golden tests if they don't already exist liftIO $ (doesFileExist expected_name >>=) $ flip unless $ do T.writeFile expected_name edited expected <- liftIO $ T.readFile expected_name liftIO $ edited @?= expected _ -> liftIO $ assertFailure "No CodeAction detected" goldenTestWithEdit :: FilePath -> ExpandStyle -> Int -> Int -> TestTree goldenTestWithEdit input tc line col = testCase (input <> " (golden)") $ do runSession hlsCommand fullCaps spliceTestPath $ do doc <- openDoc input "haskell" orig <- documentContents doc let lns = T.lines orig theRange = Range { _start = Position 0 0 , _end = Position (length lns + 1) 1 } liftIO $ sleep 3 alt <- liftIO $ T.readFile (spliceTestPath input <.> "error") void $ applyEdit doc $ TextEdit theRange alt changeDoc doc [TextDocumentContentChangeEvent (Just theRange) Nothing alt] void waitForDiagnostics actions <- getCodeActions doc $ pointRange line col case find ((== Just (toExpandCmdTitle tc)) . codeActionTitle) actions of Just (InR CodeAction {_command = Just c}) -> do executeCommand c _resp <- skipManyTill anyMessage (message SWorkspaceApplyEdit) edited <- documentContents doc let expected_name = spliceTestPath input <.> "expected" -- Write golden tests if they don't already exist liftIO $ (doesFileExist expected_name >>=) $ flip unless $ do T.writeFile expected_name edited expected <- liftIO $ T.readFile expected_name liftIO $ edited @?= expected _ -> liftIO $ assertFailure "No CodeAction detected" spliceTestPath :: FilePath spliceTestPath = "test/testdata/splice" pointRange :: Int -> Int -> Range pointRange (subtract 1 -> line) (subtract 1 -> col) = Range (Position line col) (Position line $ col + 1) -- | Get the title of a code action. codeActionTitle :: (Command |? CodeAction) -> Maybe Text codeActionTitle InL{} = Nothing codeActionTitle (InR(CodeAction title _ _ _ _ _ _)) = Just title