@@ -10,7 +10,7 @@
1010module Main (main) where
1111
1212import Control.Applicative.Combinators
13−import Control.Exception (bracket, catch)
13+import Control.Exception (catch)
1414import qualified Control.Lens as Lens
1515import Control.Monad
1616import Control.Monad.IO.Class (liftIO)
@@ -28,14 +28,15 @@ import Development.IDE.Test
2828import Development.IDE.Test.Runfiles
2929import Development.IDE.Types.Location
3030import Development.Shake (getDirectoryFilesIO)
31−import Language.Haskell.LSP.Test
31+import qualified Language.Haskell.LSP.Test as LSPTest
32+import Language.Haskell.LSP.Test hiding (openDoc')
3233import Language.Haskell.LSP.Messages
3334import Language.Haskell.LSP.Types
3435import Language.Haskell.LSP.Types.Capabilities
3536import qualified Language.Haskell.LSP.Types.Lens as Lsp (diagnostics, params, message)
3637import Language.Haskell.LSP.VFS (applyChange)
3738import Network.URI
38−import System.Environment.Blank (getEnv, setEnv, unsetEnv)
39+import System.Environment.Blank (setEnv)
3940import System.FilePath
4041import System.IO.Extra
4142import System.Directory
@@ -49,35 +50,31 @@ import Test.Tasty.QuickCheck
4950import Data.Maybe
5051
5152main :: IO ()
52−main = do
53− -- We mess with env vars so run single-threaded.
54− setEnv "TASTY_NUM_THREADS" "1" True
55− defaultMainWithRerun $ testGroup "HIE"
56− [ testSession "open close" $ do
57− doc <- createDoc "Testing.hs" "haskell" ""
58− void (skipManyTill anyMessage message :: Session WorkDoneProgressCreateRequest)
59− void (skipManyTill anyMessage message :: Session WorkDoneProgressBeginNotification)
60− closeDoc doc
61− void (skipManyTill anyMessage message :: Session WorkDoneProgressEndNotification)
62− , initializeResponseTests
63− , completionTests
64− , cppTests
65− , diagnosticTests
66− , codeActionTests
67− , codeLensesTests
68− , outlineTests
69− , findDefinitionAndHoverTests
70− , pluginTests
71− , preprocessorTests
72− , thTests
73− , safeTests
74− , unitTests
75− , haddockTests
76− , positionMappingTests
77− , watchedFilesTests
78− , cradleTests
79− , dependentFileTest
80− ]
53+main = defaultMainWithRerun $ testGroup "HIE"
54+ [ testSession "open close" $ do
55+ doc <- openDoc' "Testing.hs" "haskell" ""
56+ void (skipManyTill anyMessage message :: Session WorkDoneProgressCreateRequest)
57+ void (skipManyTill anyMessage message :: Session WorkDoneProgressBeginNotification)
58+ closeDoc doc
59+ void (skipManyTill anyMessage message :: Session WorkDoneProgressEndNotification)
60+ , initializeResponseTests
61+ , completionTests
62+ , cppTests
63+ , diagnosticTests
64+ , codeActionTests
65+ , codeLensesTests
66+ , outlineTests
67+ , findDefinitionAndHoverTests
68+ , pluginTests
69+ , preprocessorTests
70+ , thTests
71+ , safeTests
72+ , unitTests
73+ , haddockTests
74+ , positionMappingTests
75+ , watchedFilesTests
76+ , cradleTests
77+ ]
8178
8279initializeResponseTests :: TestTree
8380initializeResponseTests = withResource acquire release tests where
@@ -152,7 +149,7 @@ diagnosticTests :: TestTree
152149diagnosticTests = testGroup "diagnostics"
153150 [ testSessionWait "fix syntax error" $ do
154151 let content = T.unlines [ "module Testing wher" ]
155− doc <- createDoc "Testing.hs" "haskell" content
152+ doc <- openDoc' "Testing.hs" "haskell" content
156153 expectDiagnostics [("Testing.hs", [(DsError, (0, 15), "parse error")])]
157154 let change = TextDocumentContentChangeEvent
158155 { _range = Just (Range (Position 0 15) (Position 0 19))
@@ -163,7 +160,7 @@ diagnosticTests = testGroup "diagnostics"
163160 expectDiagnostics [("Testing.hs", [])]
164161 , testSessionWait "introduce syntax error" $ do
165162 let content = T.unlines [ "module Testing where" ]
166− doc <- createDoc "Testing.hs" "haskell" content
163+ doc <- openDoc' "Testing.hs" "haskell" content
167164 void $ skipManyTill anyMessage (message :: Session WorkDoneProgressCreateRequest)
168165 void $ skipManyTill anyMessage (message :: Session WorkDoneProgressBeginNotification)
169166 let change = TextDocumentContentChangeEvent
@@ -181,7 +178,7 @@ diagnosticTests = testGroup "diagnostics"
181178 , "bar :: Int -> Int -> Int"
182179 , "bar a b = cd + b"
183180 ]
184− _ <- createDoc "Testing.hs" "haskell" content
181+ _ <- openDoc' "Testing.hs" "haskell" content
185182 expectDiagnostics
186183 [ ( "Testing.hs"
187184 , [ (DsError, (2, 14), "Variable not in scope: ab")
@@ -195,7 +192,7 @@ diagnosticTests = testGroup "diagnostics"
195192 , "foo :: Int -> String -> Int"
196193 , "foo a b = a + b"
197194 ]
198− _ <- createDoc "Testing.hs" "haskell" content
195+ _ <- openDoc' "Testing.hs" "haskell" content
199196 expectDiagnostics
200197 [ ( "Testing.hs"
201198 , [(DsError, (2, 14), "Couldn't match type '[Char]' with 'Int'")]
@@ -207,7 +204,7 @@ diagnosticTests = testGroup "diagnostics"
207204 , "foo :: Int -> String"
208205 , "foo a = _ a"
209206 ]
210− _ <- createDoc "Testing.hs" "haskell" content
207+ _ <- openDoc' "Testing.hs" "haskell" content
211208 expectDiagnostics
212209 [ ( "Testing.hs"
213210 , [(DsError, (2, 8), "Found hole: _ :: Int -> String")]
@@ -229,8 +226,8 @@ diagnosticTests = testGroup "diagnostics"
229226 [ ("A.hs", [(DsError, (2,4), aMessage)])
230227 , ("B.hs", [(DsError, (3,4), bMessage)])]
231228 deferralTest title binding msg = testSessionWait title $ do
232− _ <- createDoc "A.hs" "haskell" $ sourceA binding
233− _ <- createDoc "B.hs" "haskell" sourceB
229+ _ <- openDoc' "A.hs" "haskell" $ sourceA binding
230+ _ <- openDoc' "B.hs" "haskell" sourceB
234231 expectDiagnostics $ expectedDs msg
235232 in
236233 [ deferralTest "type error" "True" "Couldn't match expected type"
@@ -240,12 +237,12 @@ diagnosticTests = testGroup "diagnostics"
240237
241238 , testSessionWait "remove required module" $ do
242239 let contentA = T.unlines [ "module ModuleA where" ]
243− docA <- createDoc "ModuleA.hs" "haskell" contentA
240+ docA <- openDoc' "ModuleA.hs" "haskell" contentA
244241 let contentB = T.unlines
245242 [ "module ModuleB where"
246243 , "import ModuleA"
247244 ]
248− _ <- createDoc "ModuleB.hs" "haskell" contentB
245+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
249246 let change = TextDocumentContentChangeEvent
250247 { _range = Just (Range (Position 0 0) (Position 0 20))
251248 , _rangeLength = Nothing
@@ -258,20 +255,20 @@ diagnosticTests = testGroup "diagnostics"
258255 [ "module ModuleB where"
259256 , "import ModuleA"
260257 ]
261− _ <- createDoc "ModuleB.hs" "haskell" contentB
258+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
262259 expectDiagnostics [("ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]
263260 let contentA = T.unlines [ "module ModuleA where" ]
264− _ <- createDoc "ModuleA.hs" "haskell" contentA
261+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
265262 expectDiagnostics [("ModuleB.hs", [])]
266263 , testSessionWait "add missing module (non workspace)" $ do
267264 let contentB = T.unlines
268265 [ "module ModuleB where"
269266 , "import ModuleA"
270267 ]
271− _ <- createDoc "/tmp/ModuleB.hs" "haskell" contentB
268+ _ <- openDoc'' "/tmp/ModuleB.hs" "haskell" contentB
272269 expectDiagnostics [("/tmp/ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]
273270 let contentA = T.unlines [ "module ModuleA where" ]
274− _ <- createDoc "/tmp/ModuleA.hs" "haskell" contentA
271+ _ <- openDoc'' "/tmp/ModuleA.hs" "haskell" contentA
275272 expectDiagnostics [("/tmp/ModuleB.hs", [])]
276273 , testSessionWait "cyclic module dependency" $ do
277274 let contentA = T.unlines
@@ -282,8 +279,8 @@ diagnosticTests = testGroup "diagnostics"
282279 [ "module ModuleB where"
283280 , "import ModuleA"
284281 ]
285− _ <- createDoc "ModuleA.hs" "haskell" contentA
286− _ <- createDoc "ModuleB.hs" "haskell" contentB
282+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
283+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
287284 expectDiagnostics
288285 [ ( "ModuleA.hs"
289286 , [(DsError, (1, 7), "Cyclic module dependency between ModuleA, ModuleB")]
@@ -304,9 +301,9 @@ diagnosticTests = testGroup "diagnostics"
304301 let contentBboot = T.unlines
305302 [ "module ModuleB where"
306303 ]
307− _ <- createDoc "ModuleA.hs" "haskell" contentA
308− _ <- createDoc "ModuleB.hs" "haskell" contentB
309− _ <- createDoc "ModuleB.hs-boot" "haskell" contentBboot
304+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
305+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
306+ _ <- openDoc' "ModuleB.hs-boot" "haskell" contentBboot
310307 expectDiagnostics []
311308 , testSessionWait "correct reference used with hs-boot" $ do
312309 let contentB = T.unlines
@@ -328,10 +325,10 @@ diagnosticTests = testGroup "diagnostics"
328325 -- resolved to the hs-boot file
329326 , "y = x"
330327 ]
331− _ <- createDoc "ModuleB.hs" "haskell" contentB
332− _ <- createDoc "ModuleA.hs" "haskell" contentA
333− _ <- createDoc "ModuleA.hs-boot" "haskell" contentAboot
334− _ <- createDoc "ModuleC.hs" "haskell" contentC
328+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
329+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
330+ _ <- openDoc' "ModuleA.hs-boot" "haskell" contentAboot
331+ _ <- openDoc' "ModuleC.hs" "haskell" contentC
335332 expectDiagnostics []
336333 , testSessionWait "redundant import" $ do
337334 let contentA = T.unlines ["module ModuleA where"]
@@ -340,8 +337,8 @@ diagnosticTests = testGroup "diagnostics"
340337 , "module ModuleB where"
341338 , "import ModuleA"
342339 ]
343− _ <- createDoc "ModuleA.hs" "haskell" contentA
344− _ <- createDoc "ModuleB.hs" "haskell" contentB
340+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
341+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
345342 expectDiagnostics
346343 [ ( "ModuleB.hs"
347344 , [(DsWarning, (2, 0), "The import of 'ModuleA' is redundant")]
@@ -363,8 +360,8 @@ diagnosticTests = testGroup "diagnostics"
363360 , "wrong1 = ThisList.map"
364361 , "wrong2 = BaseList.x"
365362 ]
366− _ <- createDoc "Data/List.hs" "haskell" thisDataListContent
367− _ <- createDoc "Main.hs" "haskell" mainContent
363+ _ <- openDoc' "Data/List.hs" "haskell" thisDataListContent
364+ _ <- openDoc' "Main.hs" "haskell" mainContent
368365 expectDiagnostics
369366 [ ( "Main.hs"
370367 , [(DsError, (6, 9), "Not in scope: \8216ThisList.map\8217")
@@ -379,7 +376,7 @@ diagnosticTests = testGroup "diagnostics"
379376 , "foo :: Ord a => a -> Int"
380377 , "foo a = 1"
381378 ]
382− _ <- createDoc "Foo.hs" "haskell" fooContent
379+ _ <- openDoc' "Foo.hs" "haskell" fooContent
383380 expectDiagnostics
384381 [ ( "Foo.hs"
385382 -- The test is to make sure that warnings contain unqualified names
@@ -430,7 +427,7 @@ diagnosticTests = testGroup "diagnostics"
430427 , "foo :: Int"
431428 , "foo = 1 {-|-}"
432429 ]
433− _ <- createDoc "Foo.hs" "haskell" fooContent
430+ _ <- openDoc' "Foo.hs" "haskell" fooContent
434431 expectDiagnostics
435432 [ ( "Foo.hs"
436433 , [(DsError, (2, 8), "Parse error on input")
@@ -445,7 +442,7 @@ diagnosticTests = testGroup "diagnostics"
445442 , "value :: Maybe ()"
446443 , "value = [()]"
447444 ]
448− _ <- createDoc (T.unpack name <> ".hs") "haskell" content
445+ _ <- openDoc' (T.unpack name <> ".hs") "haskell" content
449446 notification <- skipManyTill anyMessage diagnostic
450447 let
451448 offenders =
@@ -482,25 +479,29 @@ watchedFilesTests :: TestTree
482479watchedFilesTests = testGroup "watched files"
483480 [ testSession' "workspace files" $ \sessionDir -> do
484481 liftIO $ writeFile (sessionDir </> "hie.yaml") "cradle: {direct: {arguments: [\"-isrc\"]}}"
485− _doc <- createDoc "A.hs" "haskell" "{-#LANGUAGE NoImplicitPrelude #-}\nmodule A where\nimport WatchedFilesMissingModule"
482+ _doc <- openDoc' "A.hs" "haskell" "{-#LANGUAGE NoImplicitPrelude #-}\nmodule A where\nimport WatchedFilesMissingModule"
486483 watchedFileRegs <- getWatchedFilesSubscriptionsUntil @PublishDiagnosticsNotification
487484
488− -- Expect 4 subscriptions (A does not get any because it's VFS):
485+ -- Expect 6 subscriptions (A does not get any because it's VFS):
489486 -- - /path-to-workspace/WatchedFilesMissingModule.hs
490487 -- - /path-to-workspace/WatchedFilesMissingModule.lhs
491− -- - /path-to-workspace/src/WatchedFilesMissingModule.hs
492− -- - /path-to-workspace/src/WatchedFilesMissingModule.lhs
493− liftIO $ length watchedFileRegs @?= 4
488+ -- - WatchedFilesMissingModule.hs
489+ -- - WatchedFilesMissingModule.lhs
490+ -- - src/WatchedFilesMissingModule.hs
491+ -- - src/WatchedFilesMissingModule.lhs
492+ liftIO $ length watchedFileRegs @?= 6
494493
495494 , testSession' "non workspace file" $ \sessionDir -> do
496495 liftIO $ writeFile (sessionDir </> "hie.yaml") "cradle: {direct: {arguments: [\"-i/tmp\"]}}"
497− _doc <- createDoc "A.hs" "haskell" "{-# LANGUAGE NoImplicitPrelude#-}\nmodule A where\nimport WatchedFilesMissingModule"
496+ _doc <- openDoc' "A.hs" "haskell" "{-# LANGUAGE NoImplicitPrelude#-}\nmodule A where\nimport WatchedFilesMissingModule"
498497 watchedFileRegs <- getWatchedFilesSubscriptionsUntil @PublishDiagnosticsNotification
499498
500− -- Expect 2 subscriptions (/tmp does not get any as it is out of the workspace):
499+ -- Expect 4 subscriptions (/tmp does not get any as it is out of the workspace):
501500 -- - /path-to-workspace/WatchedFilesMissingModule.hs
502501 -- - /path-to-workspace/WatchedFilesMissingModule.lhs
503− liftIO $ length watchedFileRegs @?= 2
502+ -- - WatchedFilesMissingModule.hs
503+ -- - WatchedFilesMissingModule.lhs
504+ liftIO $ length watchedFileRegs @?= 4
504505
505506 -- TODO add a test for didChangeWorkspaceFolder
506507 ]
@@ -513,7 +514,7 @@ renameActionTests = testGroup "rename actions"
513514 , "foo :: Int -> Int"
514515 , "foo argName = argNme"
515516 ]
516− doc <- createDoc "Testing.hs" "haskell" content
517+ doc <- openDoc' "Testing.hs" "haskell" content
517518 _ <- waitForDiagnostics
518519 action <- findCodeAction doc (Range (Position 2 14) (Position 2 20)) "Replace with ‘argName’"
519520 executeCodeAction action
@@ -531,7 +532,7 @@ renameActionTests = testGroup "rename actions"
531532 , "foo :: Maybe a -> [a]"
532533 , "foo = maybToList"
533534 ]
534− doc <- createDoc "Testing.hs" "haskell" content
535+ doc <- openDoc' "Testing.hs" "haskell" content
535536 _ <- waitForDiagnostics
536537 action <- findCodeAction doc (Range (Position 3 6) (Position 3 16)) "Replace with ‘maybeToList’"
537538 executeCodeAction action
@@ -549,7 +550,7 @@ renameActionTests = testGroup "rename actions"
549550 , "foo :: Char -> Char -> Char -> Char"
550551 , "foo argument1 argument2 argument3 = argumentX"
551552 ]
552− doc <- createDoc "Testing.hs" "haskell" content
553+ doc <- openDoc' "Testing.hs" "haskell" content
553554 _ <- waitForDiagnostics
554555 _ <- findCodeActions doc (Range (Position 2 36) (Position 2 45))
555556 ["Replace with ‘argument1’", "Replace with ‘argument2’", "Replace with ‘argument3’"]
@@ -561,7 +562,7 @@ renameActionTests = testGroup "rename actions"
561562 , "monus x y = max 0 (x - y)"
562563 , "foo x y = x `monnus` y"
563564 ]
564− doc <- createDoc "Testing.hs" "haskell" content
565+ doc <- openDoc' "Testing.hs" "haskell" content
565566 _ <- waitForDiagnostics
566567 actionsOrCommands <- getCodeActions doc (Range (Position 3 12) (Position 3 20))
567568 [fixTypo] <- pure [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, "monus" `T.isInfixOf` actionTitle ]
@@ -584,7 +585,7 @@ typeWildCardActionTests = testGroup "type wildcard actions"
584585 , "func :: _"
585586 , "func x = x"
586587 ]
587− doc <- createDoc "Testing.hs" "haskell" content
588+ doc <- openDoc' "Testing.hs" "haskell" content
588589 _ <- waitForDiagnostics
589590 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
590591 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
@@ -604,7 +605,7 @@ typeWildCardActionTests = testGroup "type wildcard actions"
604605 , "func :: _"
605606 , "func x y = x + y"
606607 ]
607− doc <- createDoc "Testing.hs" "haskell" content
608+ doc <- openDoc' "Testing.hs" "haskell" content
608609 _ <- waitForDiagnostics
609610 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
610611 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
@@ -627,7 +628,7 @@ typeWildCardActionTests = testGroup "type wildcard actions"
627628 , " y = x * 2"
628629 , " in y"
629630 ]
630− doc <- createDoc "Testing.hs" "haskell" content
631+ doc <- openDoc' "Testing.hs" "haskell" content
631632 _ <- waitForDiagnostics
632633 actionsOrCommands <- getCodeActions doc (Range (Position 4 1) (Position 4 10))
633634 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
@@ -652,7 +653,7 @@ removeImportTests = testGroup "remove import actions"
652653 let contentA = T.unlines
653654 [ "module ModuleA where"
654655 ]
655− _docA <- createDoc "ModuleA.hs" "haskell" contentA
656+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
656657 let contentB = T.unlines
657658 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
658659 , "module ModuleB where"
@@ -660,7 +661,7 @@ removeImportTests = testGroup "remove import actions"
660661 , "stuffB :: Integer"
661662 , "stuffB = 123"
662663 ]
663− docB <- createDoc "ModuleB.hs" "haskell" contentB
664+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
664665 _ <- waitForDiagnostics
665666 [CACodeAction action@CodeAction { _title = actionTitle }]
666667 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -678,7 +679,7 @@ removeImportTests = testGroup "remove import actions"
678679 let contentA = T.unlines
679680 [ "module ModuleA where"
680681 ]
681− _docA <- createDoc "ModuleA.hs" "haskell" contentA
682+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
682683 let contentB = T.unlines
683684 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
684685 , "module ModuleB where"
@@ -686,7 +687,7 @@ removeImportTests = testGroup "remove import actions"
686687 , "stuffB :: Integer"
687688 , "stuffB = 123"
688689 ]
689− docB <- createDoc "ModuleB.hs" "haskell" contentB
690+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
690691 _ <- waitForDiagnostics
691692 [CACodeAction action@CodeAction { _title = actionTitle }]
692693 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -708,14 +709,14 @@ removeImportTests = testGroup "remove import actions"
708709 , "stuffB = 123"
709710 , "stuffC = ()"
710711 ]
711− _docA <- createDoc "ModuleA.hs" "haskell" contentA
712+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
712713 let contentB = T.unlines
713714 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
714715 , "module ModuleB where"
715716 , "import ModuleA (stuffA, stuffB, stuffC, stuffA)"
716717 , "main = print stuffB"
717718 ]
718− docB <- createDoc "ModuleB.hs" "haskell" contentB
719+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
719720 _ <- waitForDiagnostics
720721 [CACodeAction action@CodeAction { _title = actionTitle }]
721722 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -737,14 +738,14 @@ removeImportTests = testGroup "remove import actions"
737738 , "stuffB :: Integer"
738739 , "stuffB = 123"
739740 ]
740− _docA <- createDoc "ModuleA.hs" "haskell" contentA
741+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
741742 let contentB = T.unlines
742743 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
743744 , "module ModuleB where"
744745 , "import qualified ModuleA as A ((<?>), stuffB, (!!))"
745746 , "main = print A.stuffB"
746747 ]
747− docB <- createDoc "ModuleB.hs" "haskell" contentB
748+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
748749 _ <- waitForDiagnostics
749750 [CACodeAction action@CodeAction { _title = actionTitle }]
750751 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -765,14 +766,14 @@ removeImportTests = testGroup "remove import actions"
765766 , "stuffB :: Integer"
766767 , "stuffB = 123"
767768 ]
768− _docA <- createDoc "ModuleA.hs" "haskell" contentA
769+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
769770 let contentB = T.unlines
770771 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
771772 , "module ModuleB where"
772773 , "import ModuleA (A(..), stuffB)"
773774 , "main = print stuffB"
774775 ]
775− docB <- createDoc "ModuleB.hs" "haskell" contentB
776+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
776777 _ <- waitForDiagnostics
777778 [CACodeAction action@CodeAction { _title = actionTitle }]
778779 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -792,14 +793,14 @@ removeImportTests = testGroup "remove import actions"
792793 , "data D = A | B"
793794 , "data E = F"
794795 ]
795− _docA <- createDoc "ModuleA.hs" "haskell" contentA
796+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
796797 let contentB = T.unlines
797798 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
798799 , "module ModuleB where"
799800 , "import ModuleA (D(A,B), E(F))"
800801 , "main = B"
801802 ]
802− docB <- createDoc "ModuleB.hs" "haskell" contentB
803+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
803804 _ <- waitForDiagnostics
804805 [CACodeAction action@CodeAction { _title = actionTitle }]
805806 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -940,8 +941,8 @@ extendImportTests = testGroup "extend import actions"
940941 ]
941942 where
942943 template contentA contentB range expectedAction expectedContentB = do
943− _docA <- createDoc "ModuleA.hs" "haskell" contentA
944− docB <- createDoc "ModuleB.hs" "haskell" contentB
944+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
945+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
945946 _ <- waitForDiagnostics
946947 CACodeAction action@CodeAction { _title = actionTitle } : _
947948 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -991,7 +992,7 @@ suggestImportTests = testGroup "suggest import actions"
991992 after = T.unlines $ "module A where" : ["import " <> x | x <- imps] ++ [newImp] ++ def : other
992993 cradle = "cradle: {direct: {arguments: [-hide-all-packages, -package, base, -package, text, -package-env, -]}}"
993994 liftIO $ writeFileUTF8 (dir </> "hie.yaml") cradle
994− doc <- createDoc "Test.hs" "haskell" before
995+ doc <- openDoc' "Test.hs" "haskell" before
995996 _diags <- waitForDiagnostics
996997 let defLine = length imps + 1
997998 range = Range (Position defLine 0) (Position defLine maxBound)
@@ -1051,7 +1052,7 @@ addExtensionTests = testGroup "add language extension actions"
10511052 ]
10521053 where
10531054 template initialContent range expectedAction expectedContents = do
1054− doc <- createDoc "Module.hs" "haskell" initialContent
1055+ doc <- openDoc' "Module.hs" "haskell" initialContent
10551056 _ <- waitForDiagnostics
10561057 CACodeAction action@CodeAction { _title = actionTitle } : _
10571058 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1074,7 +1075,7 @@ insertNewDefinitionTests = testGroup "insert new definition actions"
10741075 [""
10751076 ,"someOtherCode = ()"
10761077 ]
1077− docB <- createDoc "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
1078+ docB <- openDoc' "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
10781079 _ <- waitForDiagnostics
10791080 CACodeAction action@CodeAction { _title = actionTitle } : _
10801081 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1098,7 +1099,7 @@ insertNewDefinitionTests = testGroup "insert new definition actions"
10981099 [""
10991100 ,"someOtherCode = ()"
11001101 ]
1101− docB <- createDoc "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
1102+ docB <- openDoc' "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
11021103 _ <- waitForDiagnostics
11031104 CACodeAction action@CodeAction { _title = actionTitle } : _
11041105 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1137,8 +1138,8 @@ fixConstructorImportTests = testGroup "fix import actions"
11371138 ]
11381139 where
11391140 template contentA contentB range expectedAction expectedContentB = do
1140− _docA <- createDoc "ModuleA.hs" "haskell" contentA
1141− docB <- createDoc "ModuleB.hs" "haskell" contentB
1141+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
1142+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
11421143 _diags <- waitForDiagnostics
11431144 CACodeAction action@CodeAction { _title = actionTitle } : _
11441145 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1157,7 +1158,7 @@ importRenameActionTests = testGroup "import rename actions"
11571158 [ "module Testing where"
11581159 , "import Data.Mape"
11591160 ]
1160− doc <- createDoc "Testing.hs" "haskell" content
1161+ doc <- openDoc' "Testing.hs" "haskell" content
11611162 _ <- waitForDiagnostics
11621163 actionsOrCommands <- getCodeActions doc (Range (Position 2 8) (Position 2 16))
11631164 let [changeToMap] = [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, ("Data." <> modname) `T.isInfixOf` actionTitle ]
@@ -1194,7 +1195,7 @@ fillTypedHoleTests = let
11941195 newA newB newC = testSession (T.unpack actionTitle) $ do
11951196 let originalCode = sourceCode oldA oldB oldC
11961197 let expectedCode = sourceCode newA newB newC
1197− doc <- createDoc "Testing.hs" "haskell" originalCode
1198+ doc <- openDoc' "Testing.hs" "haskell" originalCode
11981199 _ <- waitForDiagnostics
11991200 actionsOrCommands <- getCodeActions doc (Range (Position 9 0) (Position 9 maxBound))
12001201 chosenAction <- liftIO $ pickActionWithTitle actionTitle actionsOrCommands
@@ -1242,7 +1243,7 @@ addSigActionTests = let
12421243 def >:: sig = testSession (T.unpack def) $ do
12431244 let originalCode = before def
12441245 let expectedCode = after' def sig
1245− doc <- createDoc "Sigs.hs" "haskell" originalCode
1246+ doc <- openDoc' "Sigs.hs" "haskell" originalCode
12461247 _ <- waitForDiagnostics
12471248 actionsOrCommands <- getCodeActions doc (Range (Position 3 1) (Position 3 maxBound))
12481249 chosenAction <- liftIO $ pickActionWithTitle ("add signature: " <> sig) actionsOrCommands
@@ -1274,7 +1275,7 @@ addSigLensesTests = let
12741275 sigSession withMissing def sig = testSession (T.unpack def) $ do
12751276 let originalCode = before withMissing def
12761277 let expectedCode = after' withMissing def sig
1277− doc <- createDoc "Sigs.hs" "haskell" originalCode
1278+ doc <- openDoc' "Sigs.hs" "haskell" originalCode
12781279 [CodeLens {_command = Just c}] <- getCodeLenses doc
12791280 executeCommand c
12801281 modifiedCode <- getDocumentEdit doc
@@ -1296,36 +1297,33 @@ addSigLensesTests = let
12961297 ]
12971298 ]
12981299
1299−checkDefs :: [Location] -> Session [Expect] -> Session ()
1300−checkDefs defs mkExpectations = traverse_ check =<< mkExpectations where
1301−
1302− check (ExpectRange expectedRange) = do
1303− assertNDefinitionsFound 1 defs
1304− assertRangeCorrect (head defs) expectedRange
1305− check (ExpectLocation expectedLocation) = do
1306− assertNDefinitionsFound 1 defs
1307− liftIO $ head defs @?= expectedLocation
1308− check ExpectNoDefinitions = do
1309− assertNDefinitionsFound 0 defs
1310− check ExpectExternFail = liftIO $ assertFailure "Expecting to fail to find in external file"
1311− check _ = pure () -- all other expectations not relevant to getDefinition
1312−
1313− assertNDefinitionsFound :: Int -> [a] -> Session ()
1314− assertNDefinitionsFound n defs = liftIO $ assertEqual "number of definitions" n (length defs)
1315−
1316− assertRangeCorrect Location{_range = foundRange} expectedRange =
1317− liftIO $ expectedRange @=? foundRange
1318−
1319−
13201300findDefinitionAndHoverTests :: TestTree
13211301findDefinitionAndHoverTests = let
13221302
1323− tst (get, check) pos targetRange title = testSessionWithExtraFiles "hover" title $ \dir -> do
1324− doc <- openTestDataDoc (dir </> sourceFilePath)
1303+ tst (get, check) pos targetRange title = testSession title $ do
1304+ doc <- openTestDataDoc sourceFilePath
13251305 found <- get doc pos
13261306 check found targetRange
13271307
1308+ checkDefs :: [Location] -> Session [Expect] -> Session ()
1309+ checkDefs defs mkExpectations = traverse_ check =<< mkExpectations where
1310+
1311+ check (ExpectRange expectedRange) = do
1312+ assertNDefinitionsFound 1 defs
1313+ assertRangeCorrect (head defs) expectedRange
1314+ check (ExpectLocation expectedLocation) = do
1315+ assertNDefinitionsFound 1 defs
1316+ liftIO $ head defs @?= expectedLocation
1317+ check ExpectNoDefinitions = do
1318+ assertNDefinitionsFound 0 defs
1319+ check ExpectExternFail = liftIO $ assertFailure "Expecting to fail to find in external file"
1320+ check _ = pure () -- all other expectations not relevant to getDefinition
13281321
1322+ assertNDefinitionsFound :: Int -> [a] -> Session ()
1323+ assertNDefinitionsFound n defs = liftIO $ assertEqual "number of definitions" n (length defs)
1324+
1325+ assertRangeCorrect Location{_range = foundRange} expectedRange =
1326+ liftIO $ expectedRange @=? foundRange
13291327
13301328 checkHover :: Maybe Hover -> Session [Expect] -> Session ()
13311329 checkHover hover expectations = traverse_ check =<< expectations where
@@ -1371,8 +1369,7 @@ findDefinitionAndHoverTests = let
13711369
13721370 mkFindTests tests = testGroup "get"
13731371 [ testGroup "definition" $ mapMaybe fst tests
1374− , testGroup "hover" $ mapMaybe snd tests
1375− , checkFileCompiles sourceFilePath ]
1372+ , testGroup "hover" $ mapMaybe snd tests ]
13761373
13771374 test runDef runHover look expect = testM runDef runHover look (return expect)
13781375
@@ -1467,14 +1464,6 @@ findDefinitionAndHoverTests = let
14671464 broken = Just . (`xfail` "known broken")
14681465 no = const Nothing -- don't run this test at all
14691466
1470−checkFileCompiles :: FilePath -> TestTree
1471−checkFileCompiles fp =
1472− testSessionWithExtraFiles "hover" ("Does " ++ fp ++ " compile") $ \dir -> do
1473− void (openTestDataDoc (dir </> fp))
1474− expectNoMoreDiagnostics 0.5
1475−
1476−
1477−
14781467pluginTests :: TestTree
14791468pluginTests = (`xfail8101` "known broken (#556)")
14801469 $ testSessionWait "plugins" $ do
@@ -1491,7 +1480,7 @@ pluginTests = (`xfail8101` "known broken (#556)")
14911480 , "foo :: Int -> Int -> Int"
14921481 , "foo a b = a + c"
14931482 ]
1494− _ <- createDoc "Testing.hs" "haskell" content
1483+ _ <- openDoc' "Testing.hs" "haskell" content
14951484 expectDiagnostics
14961485 [ ( "Testing.hs",
14971486 [(DsError, (8, 14), "Variable not in scope: c")]
@@ -1518,7 +1507,7 @@ cppTests =
15181507 run $ expectError content (2, 1)
15191508 )
15201509 , testSessionWait "cpp-ghcide" $ do
1521− _ <- createDoc "A.hs" "haskell" $ T.unlines
1510+ _ <- openDoc' "A.hs" "haskell" $ T.unlines
15221511 ["{-# LANGUAGE CPP #-}"
15231512 ,"main ="
15241513 ,"#ifdef __GHCIDE__"
@@ -1532,7 +1521,7 @@ cppTests =
15321521 where
15331522 expectError :: T.Text -> Cursor -> Session ()
15341523 expectError content cursor = do
1535− _ <- createDoc "Testing.hs" "haskell" content
1524+ _ <- openDoc' "Testing.hs" "haskell" content
15361525 expectDiagnostics
15371526 [ ( "Testing.hs",
15381527 [(DsError, cursor, "error: unterminated")]
@@ -1548,7 +1537,7 @@ preprocessorTests = testSessionWait "preprocessor" $ do
15481537 , "module Testing where"
15491538 , "y = x + z" -- plugin replaces x with y, making this have only one diagnostic
15501539 ]
1551− _ <- createDoc "Testing.hs" "haskell" content
1540+ _ <- openDoc' "Testing.hs" "haskell" content
15521541 expectDiagnostics
15531542 [ ( "Testing.hs",
15541543 [(DsError, (2, 8), "Variable not in scope: z")]
@@ -1581,8 +1570,8 @@ safeTests =
15811570 ,"safeId = trustWorthyId"
15821571 ]
15831572
1584− _ <- createDoc "A.hs" "haskell" sourceA
1585− _ <- createDoc "B.hs" "haskell" sourceB
1573+ _ <- openDoc' "A.hs" "haskell" sourceA
1574+ _ <- openDoc' "B.hs" "haskell" sourceB
15861575 expectNoMoreDiagnostics 1 ]
15871576
15881577thTests :: TestTree
@@ -1610,8 +1599,8 @@ thTests =
16101599 "b :: Integer",
16111600 "b = $(litE $ IntegerL $ a) + n"
16121601 ]
1613− _ <- createDoc "A.hs" "haskell" sourceA
1614− _ <- createDoc "B.hs" "haskell" sourceB
1602+ _ <- openDoc' "A.hs" "haskell" sourceA
1603+ _ <- openDoc' "B.hs" "haskell" sourceB
16151604 expectDiagnostics [ ( "B.hs", [(DsError, (6, 29), "Variable not in scope: n")] ) ]
16161605 , testSessionWait "newtype-closure" $ do
16171606 let sourceA =
@@ -1631,8 +1620,8 @@ thTests =
16311620 ,"import A"
16321621 ,"b :: Int"
16331622 ,"b = $( a )" ]
1634− _ <- createDoc "A.hs" "haskell" sourceA
1635− _ <- createDoc "B.hs" "haskell" sourceB
1623+ _ <- openDoc' "A.hs" "haskell" sourceA
1624+ _ <- openDoc' "B.hs" "haskell" sourceB
16361625 return ()
16371626 ]
16381627
@@ -1641,7 +1630,7 @@ completionTests
16411630 = testGroup "completion"
16421631 [ testSessionWait "variable" $ do
16431632 let source = T.unlines ["module A where", "f = hea"]
1644− docId <- createDoc "A.hs" "haskell" source
1633+ docId <- openDoc' "A.hs" "haskell" source
16451634 compls <- getCompletions docId (Position 1 7)
16461635 liftIO $ map dropDocs compls @?=
16471636 [complItem "head" (Just CiFunction) (Just "[a] -> a")]
@@ -1653,7 +1642,7 @@ completionTests
16531642 ]
16541643 , testSessionWait "constructor" $ do
16551644 let source = T.unlines ["module A where", "f = Tru"]
1656− docId <- createDoc "A.hs" "haskell" source
1645+ docId <- openDoc' "A.hs" "haskell" source
16571646 compls <- getCompletions docId (Position 1 7)
16581647 liftIO $ map dropDocs compls @?=
16591648 [ complItem "True" (Just CiConstructor) (Just "Bool")
@@ -1665,7 +1654,7 @@ completionTests
16651654 ]
16661655 , testSessionWait "type" $ do
16671656 let source = T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: ()", "f = ()"]
1668− docId <- createDoc "A.hs" "haskell" source
1657+ docId <- openDoc' "A.hs" "haskell" source
16691658 expectDiagnostics [ ("A.hs", [(DsWarning, (3,0), "not used")]) ]
16701659 changeDoc docId [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: Bo", "f = True"]]
16711660 compls <- getCompletions docId (Position 2 7)
@@ -1682,7 +1671,7 @@ completionTests
16821671 checkDocText "Bool" boolDocs [ "Defined in 'Prelude'" ]
16831672 , testSessionWait "qualified" $ do
16841673 let source = T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = ()"]
1685− docId <- createDoc "A.hs" "haskell" source
1674+ docId <- openDoc' "A.hs" "haskell" source
16861675 expectDiagnostics [ ("A.hs", [(DsWarning, (2, 0), "not used")]) ]
16871676 changeDoc docId [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = Prelude.hea"]]
16881677 compls <- getCompletions docId (Position 2 15)
@@ -1696,7 +1685,7 @@ completionTests
16961685 ]
16971686 , testSessionWait "keyword" $ do
16981687 let source = T.unlines ["module A where", "f = newty"]
1699− docId <- createDoc "A.hs" "haskell" source
1688+ docId <- openDoc' "A.hs" "haskell" source
17001689 compls <- getCompletions docId (Position 1 9)
17011690 liftIO $ compls @?= [keywordItem "newtype"]
17021691 , testSessionWait "type context" $ do
@@ -1705,7 +1694,7 @@ completionTests
17051694 , "module A () where"
17061695 , "f = f"
17071696 ]
1708− docId <- createDoc "A.hs" "haskell" source
1697+ docId <- openDoc' "A.hs" "haskell" source
17091698 expectDiagnostics [("A.hs", [(DsWarning, (2, 0), "not used")])]
17101699 changeDoc docId
17111700 [ TextDocumentContentChangeEvent Nothing Nothing $ T.unlines
@@ -1773,7 +1762,7 @@ outlineTests = testGroup
17731762 "outline"
17741763 [ testSessionWait "type class" $ do
17751764 let source = T.unlines ["module A where", "class A a where a :: a -> Bool"]
1776− docId <- createDoc "A.hs" "haskell" source
1765+ docId <- openDoc' "A.hs" "haskell" source
17771766 symbols <- getDocumentSymbols docId
17781767 liftIO $ symbols @?= Left
17791768 [ moduleSymbol
@@ -1786,7 +1775,7 @@ outlineTests = testGroup
17861775 ]
17871776 , testSessionWait "type class instance " $ do
17881777 let source = T.unlines ["class A a where", "instance A () where"]
1789− docId <- createDoc "A.hs" "haskell" source
1778+ docId <- openDoc' "A.hs" "haskell" source
17901779 symbols <- getDocumentSymbols docId
17911780 liftIO $ symbols @?= Left
17921781 [ classSymbol "A a" (R 0 0 0 15) []
@@ -1794,7 +1783,7 @@ outlineTests = testGroup
17941783 ]
17951784 , testSessionWait "type family" $ do
17961785 let source = T.unlines ["{-# language TypeFamilies #-}", "type family A"]
1797− docId <- createDoc "A.hs" "haskell" source
1786+ docId <- openDoc' "A.hs" "haskell" source
17981787 symbols <- getDocumentSymbols docId
17991788 liftIO $ symbols @?= Left [docSymbolD "A" "type family" SkClass (R 1 0 1 13)]
18001789 , testSessionWait "type family instance " $ do
@@ -1803,7 +1792,7 @@ outlineTests = testGroup
18031792 , "type family A a"
18041793 , "type instance A () = ()"
18051794 ]
1806− docId <- createDoc "A.hs" "haskell" source
1795+ docId <- openDoc' "A.hs" "haskell" source
18071796 symbols <- getDocumentSymbols docId
18081797 liftIO $ symbols @?= Left
18091798 [ docSymbolD "A a" "type family" SkClass (R 1 0 1 15)
@@ -1811,7 +1800,7 @@ outlineTests = testGroup
18111800 ]
18121801 , testSessionWait "data family" $ do
18131802 let source = T.unlines ["{-# language TypeFamilies #-}", "data family A"]
1814− docId <- createDoc "A.hs" "haskell" source
1803+ docId <- openDoc' "A.hs" "haskell" source
18151804 symbols <- getDocumentSymbols docId
18161805 liftIO $ symbols @?= Left [docSymbolD "A" "data family" SkClass (R 1 0 1 11)]
18171806 , testSessionWait "data family instance " $ do
@@ -1820,7 +1809,7 @@ outlineTests = testGroup
18201809 , "data family A a"
18211810 , "data instance A () = A ()"
18221811 ]
1823− docId <- createDoc "A.hs" "haskell" source
1812+ docId <- openDoc' "A.hs" "haskell" source
18241813 symbols <- getDocumentSymbols docId
18251814 liftIO $ symbols @?= Left
18261815 [ docSymbolD "A a" "data family" SkClass (R 1 0 1 11)
@@ -1828,36 +1817,36 @@ outlineTests = testGroup
18281817 ]
18291818 , testSessionWait "constant" $ do
18301819 let source = T.unlines ["a = ()"]
1831− docId <- createDoc "A.hs" "haskell" source
1820+ docId <- openDoc' "A.hs" "haskell" source
18321821 symbols <- getDocumentSymbols docId
18331822 liftIO $ symbols @?= Left
18341823 [docSymbol "a" SkFunction (R 0 0 0 6)]
18351824 , testSessionWait "pattern" $ do
18361825 let source = T.unlines ["Just foo = Just 21"]
1837− docId <- createDoc "A.hs" "haskell" source
1826+ docId <- openDoc' "A.hs" "haskell" source
18381827 symbols <- getDocumentSymbols docId
18391828 liftIO $ symbols @?= Left
18401829 [docSymbol "Just foo" SkFunction (R 0 0 0 18)]
18411830 , testSessionWait "pattern with type signature" $ do
18421831 let source = T.unlines ["{-# language ScopedTypeVariables #-}", "a :: () = ()"]
1843− docId <- createDoc "A.hs" "haskell" source
1832+ docId <- openDoc' "A.hs" "haskell" source
18441833 symbols <- getDocumentSymbols docId
18451834 liftIO $ symbols @?= Left
18461835 [docSymbol "a :: ()" SkFunction (R 1 0 1 12)]
18471836 , testSessionWait "function" $ do
18481837 let source = T.unlines ["a x = ()"]
1849− docId <- createDoc "A.hs" "haskell" source
1838+ docId <- openDoc' "A.hs" "haskell" source
18501839 symbols <- getDocumentSymbols docId
18511840 liftIO $ symbols @?= Left [docSymbol "a" SkFunction (R 0 0 0 8)]
18521841 , testSessionWait "type synonym" $ do
18531842 let source = T.unlines ["type A = Bool"]
1854− docId <- createDoc "A.hs" "haskell" source
1843+ docId <- openDoc' "A.hs" "haskell" source
18551844 symbols <- getDocumentSymbols docId
18561845 liftIO $ symbols @?= Left
18571846 [docSymbol' "A" SkTypeParameter (R 0 0 0 13) (R 0 5 0 6)]
18581847 , testSessionWait "datatype" $ do
18591848 let source = T.unlines ["data A = C"]
1860− docId <- createDoc "A.hs" "haskell" source
1849+ docId <- openDoc' "A.hs" "haskell" source
18611850 symbols <- getDocumentSymbols docId
18621851 liftIO $ symbols @?= Left
18631852 [ docSymbolWithChildren "A"
@@ -1865,21 +1854,9 @@ outlineTests = testGroup
18651854 (R 0 0 0 10)
18661855 [docSymbol "C" SkConstructor (R 0 9 0 10)]
18671856 ]
1868− , testSessionWait "record fields" $ do
1869− let source = T.unlines ["data A = B {", " x :: Int", " , y :: Int}"]
1870− docId <- createDoc "A.hs" "haskell" source
1871− symbols <- getDocumentSymbols docId
1872− liftIO $ symbols @=? Left
1873− [ docSymbolWithChildren "A" SkStruct (R 0 0 2 13)
1874− [ docSymbolWithChildren' "B" SkConstructor (R 0 9 2 13) (R 0 9 0 10)
1875− [ docSymbol "x" SkField (R 1 2 1 3)
1876− , docSymbol "y" SkField (R 2 4 2 5)
1877− ]
1878− ]
1879− ]
18801857 , testSessionWait "import" $ do
18811858 let source = T.unlines ["import Data.Maybe"]
1882− docId <- createDoc "A.hs" "haskell" source
1859+ docId <- openDoc' "A.hs" "haskell" source
18831860 symbols <- getDocumentSymbols docId
18841861 liftIO $ symbols @?= Left
18851862 [docSymbolWithChildren "imports"
@@ -1890,7 +1867,7 @@ outlineTests = testGroup
18901867 ]
18911868 , testSessionWait "multiple import" $ do
18921869 let source = T.unlines ["", "import Data.Maybe", "", "import Control.Exception", ""]
1893− docId <- createDoc "A.hs" "haskell" source
1870+ docId <- openDoc' "A.hs" "haskell" source
18941871 symbols <- getDocumentSymbols docId
18951872 liftIO $ symbols @?= Left
18961873 [docSymbolWithChildren "imports"
@@ -1905,7 +1882,7 @@ outlineTests = testGroup
19051882 [ "{-# language ForeignFunctionInterface #-}"
19061883 , "foreign import ccall \"a\" a :: Int"
19071884 ]
1908− docId <- createDoc "A.hs" "haskell" source
1885+ docId <- openDoc' "A.hs" "haskell" source
19091886 symbols <- getDocumentSymbols docId
19101887 liftIO $ symbols @?= Left [docSymbolD "a" "import" SkObject (R 1 0 1 33)]
19111888 , testSessionWait "foreign export" $ do
@@ -1913,7 +1890,7 @@ outlineTests = testGroup
19131890 [ "{-# language ForeignFunctionInterface #-}"
19141891 , "foreign export ccall odd :: Int -> Bool"
19151892 ]
1916− docId <- createDoc "A.hs" "haskell" source
1893+ docId <- openDoc' "A.hs" "haskell" source
19171894 symbols <- getDocumentSymbols docId
19181895 liftIO $ symbols @?= Left [docSymbolD "odd" "export" SkObject (R 1 0 1 39)]
19191896 ]
@@ -1926,8 +1903,6 @@ outlineTests = testGroup
19261903 DocumentSymbol name (Just detail) kind Nothing loc loc Nothing
19271904 docSymbolWithChildren name kind loc cc =
19281905 DocumentSymbol name Nothing kind Nothing loc loc (Just $ List cc)
1929− docSymbolWithChildren' name kind loc selectionLoc cc =
1930− DocumentSymbol name Nothing kind Nothing loc selectionLoc (Just $ List cc)
19311906 moduleSymbol name loc cc = DocumentSymbol name
19321907 Nothing
19331908 SkFile
@@ -2033,7 +2008,6 @@ cradleTests :: TestTree
20332008cradleTests = testGroup "cradle"
20342009 [testGroup "dependencies" [sessionDepsArePickedUp]
20352010 ,testGroup "loading" [loadCradleOnlyonce]
2036− ,testGroup "multi" [simpleMultiTest, simpleMultiTest2]
20372011 ]
20382012
20392013loadCradleOnlyonce :: TestTree
@@ -2048,53 +2022,17 @@ loadCradleOnlyonce = testGroup "load cradle only once"
20482022 test dir
20492023 implicit dir = test dir
20502024 test _dir = do
2051− doc <- createDoc "B.hs" "haskell" "module B where\nimport Data.Foo"
2025+ doc <- openDoc' "B.hs" "haskell" "module B where\nimport Data.Foo"
20522026 msgs <- someTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))
20532027 liftIO $ length msgs @?= 1
20542028 changeDoc doc [TextDocumentContentChangeEvent Nothing Nothing "module B where\nimport Data.Maybe"]
20552029 msgs <- manyTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))
20562030 liftIO $ length msgs @?= 0
2057− _ <- createDoc "A.hs" "haskell" "module A where\nimport LoadCradleBar"
2031+ _ <- openDoc' "A.hs" "haskell" "module A where\nimport LoadCradleBar"
20582032 msgs <- manyTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))
20592033 liftIO $ length msgs @?= 0
20602034
20612035
2062−dependentFileTest :: TestTree
2063−dependentFileTest = testGroup "addDependentFile"
2064− [testGroup "file-changed" [testSession' "test" test]
2065− ]
2066− where
2067− test dir = do
2068− -- If the file contains B then no type error
2069− -- otherwise type error
2070− liftIO $ writeFile (dir </> "dep-file.txt") "A"
2071− let fooContent = T.unlines
2072− [ "{-# LANGUAGE TemplateHaskell #-}"
2073− , "module Foo where"
2074− , "import Language.Haskell.TH.Syntax"
2075− , "foo :: Int"
2076− , "foo = 1 + $(do"
2077− , " qAddDependentFile \"dep-file.txt\""
2078− , " f <- qRunIO (readFile \"dep-file.txt\")"
2079− , " if f == \"B\" then [| 1 |] else lift f)"
2080− ]
2081− let bazContent = T.unlines ["module Baz where", "import Foo"]
2082− _ <-createDoc "Foo.hs" "haskell" fooContent
2083− doc <- createDoc "Baz.hs" "haskell" bazContent
2084− expectDiagnostics
2085− [("Foo.hs", [(DsError, (4, 6), "Couldn't match expected type")])]
2086− -- Now modify the dependent file
2087− liftIO $ writeFile (dir </> "dep-file.txt") "B"
2088− let change = TextDocumentContentChangeEvent
2089− { _range = Just (Range (Position 2 0) (Position 2 6))
2090− , _rangeLength = Nothing
2091− , _text = "f = ()"
2092− }
2093− -- Modifying Baz will now trigger Foo to be rebuilt as well
2094− changeDoc doc [change]
2095− expectDiagnostics [("Foo.hs", [])]
2096−
2097−
20982036cradleLoadedMessage :: Session FromServerMessage
20992037cradleLoadedMessage = satisfy $ \case
21002038 NotCustomServer (NotificationMessage _ (CustomServerMethod m) _) -> m == cradleLoadedMethod
@@ -2103,56 +2041,6 @@ cradleLoadedMessage = satisfy $ \case
21032041cradleLoadedMethod :: T.Text
21042042cradleLoadedMethod = "ghcide/cradle/loaded"
21052043
2106−-- Stack sets this which trips up cabal in the multi-component tests.
2107−-- However, our plugin tests rely on those env vars so we unset it locally.
2108−withoutStackEnv :: IO a -> IO a
2109−withoutStackEnv s =
2110− bracket
2111− (mapM getEnv vars >>= \prevState -> mapM_ unsetEnv vars >> pure prevState)
2112− (\prevState -> mapM_ (\(var, value) -> restore var value) (zip vars prevState))
2113− (const s)
2114− where vars =
2115− [ "GHC_PACKAGE_PATH"
2116− , "GHC_ENVIRONMENT"
2117− , "HASKELL_DIST_DIR"
2118− , "HASKELL_PACKAGE_SANDBOX"
2119− , "HASKELL_PACKAGE_SANDBOXES"
2120− ]
2121− restore var Nothing = unsetEnv var
2122− restore var (Just val) = setEnv var val True
2123−
2124−simpleMultiTest :: TestTree
2125−simpleMultiTest = testCase "simple-multi-test" $ withoutStackEnv $ runWithExtraFiles "multi" $ \dir -> do
2126− let aPath = dir </> "a/A.hs"
2127− bPath = dir </> "b/B.hs"
2128− aSource <- liftIO $ readFileUtf8 aPath
2129− (TextDocumentIdentifier adoc) <- createDoc aPath "haskell" aSource
2130− expectNoMoreDiagnostics 0.5
2131− bSource <- liftIO $ readFileUtf8 bPath
2132− bdoc <- createDoc bPath "haskell" bSource
2133− expectNoMoreDiagnostics 0.5
2134− locs <- getDefinitions bdoc (Position 2 7)
2135− let fooL = mkL adoc 2 0 2 3
2136− checkDefs locs (pure [fooL])
2137− expectNoMoreDiagnostics 0.5
2138−
2139−-- Like simpleMultiTest but open the files in the other order
2140−simpleMultiTest2 :: TestTree
2141−simpleMultiTest2 = testCase "simple-multi-test2" $ withoutStackEnv $ runWithExtraFiles "multi" $ \dir -> do
2142− let aPath = dir </> "a/A.hs"
2143− bPath = dir </> "b/B.hs"
2144− bSource <- liftIO $ readFileUtf8 bPath
2145− bdoc <- createDoc bPath "haskell" bSource
2146− expectNoMoreDiagnostics 5
2147− aSource <- liftIO $ readFileUtf8 aPath
2148− (TextDocumentIdentifier adoc) <- createDoc aPath "haskell" aSource
2149− -- Need to have some delay here or the test fails
2150− expectNoMoreDiagnostics 5
2151− locs <- getDefinitions bdoc (Position 2 7)
2152− let fooL = mkL adoc 2 0 2 3
2153− checkDefs locs (pure [fooL])
2154− expectNoMoreDiagnostics 0.5
2155−
21562044sessionDepsArePickedUp :: TestTree
21572045sessionDepsArePickedUp = testSession'
21582046 "session-deps-are-picked-up"
@@ -2162,7 +2050,7 @@ sessionDepsArePickedUp = testSession'
21622050 (dir </> "hie.yaml")
21632051 "cradle: {direct: {arguments: []}}"
21642052 -- Open without OverloadedStrings and expect an error.
2165− doc <- createDoc "Foo.hs" "haskell" fooContent
2053+ doc <- openDoc' "Foo.hs" "haskell" fooContent
21662054 expectDiagnostics
21672055 [("Foo.hs", [(DsError, (3, 6), "Couldn't match expected type")])]
21682056 -- Update hie.yaml to enable OverloadedStrings.
@@ -2197,9 +2085,6 @@ sessionDepsArePickedUp = testSession'
21972085testSession :: String -> Session () -> TestTree
21982086testSession name = testCase name . run
21992087
2200−testSessionWithExtraFiles :: FilePath -> String -> (FilePath -> Session ()) -> TestTree
2201−testSessionWithExtraFiles prefix name = testCase name . runWithExtraFiles prefix
2202−
22032088testSession' :: String -> (FilePath -> Session ()) -> TestTree
22042089testSession' name = testCase name . run'
22052090
@@ -2234,19 +2119,6 @@ mkRange a b c d = Range (Position a b) (Position c d)
22342119run :: Session a -> IO a
22352120run s = withTempDir $ \dir -> runInDir dir s
22362121
2237−runWithExtraFiles :: FilePath -> (FilePath -> Session a) -> IO a
2238−runWithExtraFiles prefix s = withTempDir $ \dir -> do
2239− copyTestDataFiles dir prefix
2240− runInDir dir (s dir)
2241−
2242−copyTestDataFiles :: FilePath -> FilePath -> IO ()
2243−copyTestDataFiles dir prefix = do
2244− -- Copy all the test data files to the temporary workspace
2245− testDataFiles <- getDirectoryFilesIO ("test/data" </> prefix) ["//*"]
2246− for_ testDataFiles $ \f -> do
2247− createDirectoryIfMissing True $ dir </> takeDirectory f
2248− copyFile ("test/data" </> prefix </> f) (dir </> f)
2249−
22502122run' :: (FilePath -> Session a) -> IO a
22512123run' s = withTempDir $ \dir -> runInDir dir (s dir)
22522124
@@ -2258,6 +2130,11 @@ runInDir dir s = do
22582130 -- since the package import test creates "Data/List.hs", which otherwise has no physical home
22592131 createDirectoryIfMissing True $ dir ++ "/Data"
22602132
2133+ -- Copy all the test data files to the temporary workspace
2134+ testDataFiles <- getDirectoryFilesIO "test/data" ["//*"]
2135+ for_ testDataFiles $ \f -> do
2136+ createDirectoryIfMissing True $ dir </> takeDirectory f
2137+ copyFile ("test/data" </> f) (dir </> f)
22612138
22622139 let cmd = unwords [ghcideExe, "--lsp", "--test", "--cwd", dir]
22632140 -- HIE calls getXgdDirectory which assumes that HOME is set.
@@ -2276,7 +2153,7 @@ runInDir dir s = do
22762153openTestDataDoc :: FilePath -> Session TextDocumentIdentifier
22772154openTestDataDoc path = do
22782155 source <- liftIO $ readFileUtf8 $ "test/data" </> path
2279− createDoc path "haskell" source
2156+ openDoc' path "haskell" source
22802157
22812158findCodeActions :: TextDocumentIdentifier -> Range -> [T.Text] -> Session [CodeAction]
22822159findCodeActions doc range expectedTitles = do
@@ -2317,6 +2194,20 @@ unitTests = do
23172194 uriToFilePath' uri @?= Just ""
23182195 ]
23192196
2197+-- | Wrapper around 'LSPTest.openDoc'' that sends file creation events
2198+openDoc' :: FilePath -> String -> T.Text -> Session TextDocumentIdentifier
2199+openDoc' fp name contents = do
2200+ res@(TextDocumentIdentifier uri) <- LSPTest.openDoc' fp name contents
2201+ -- Needed as ghcide sets up and relies on WatchedFiles but lsp-test does not track them
2202+ sendNotification WorkspaceDidChangeWatchedFiles (DidChangeWatchedFilesParams $ List [FileEvent uri FcCreated])
2203+ return res
2204+
2205+-- | Version of 'LSPTest.openDoc'' that does not send WatchedFiles events for files outside the workspace
2206+openDoc'' :: FilePath -> String -> T.Text -> Session TextDocumentIdentifier
2207+-- At the moment this is just LSPTest.openDoc' but it may change in the future
2208+-- when/if lsp-test implements WatchedFiles
2209+openDoc'' = LSPTest.openDoc'
2210+
23202211positionMappingTests :: TestTree
23212212positionMappingTests =
23222213 testGroup "position mapping"