@@ -1,7 +1,6 @@
11-- Copyright (c) 2019 The DAML Authors. All rights reserved.
22-- SPDX-License-Identifier: Apache-2.0
33
4−{-# LANGUAGE AllowAmbiguousTypes #-}
54{-# LANGUAGE DuplicateRecordFields #-}
65{-# LANGUAGE PatternSynonyms #-}
76{-# LANGUAGE CPP #-}
@@ -10,32 +9,29 @@
109module Main (main) where
1110
1211import Control.Applicative.Combinators
13−import Control.Exception (bracket, catch)
14−import qualified Control.Lens as Lens
12+import Control.Exception (catch)
1513import Control.Monad
1614import Control.Monad.IO.Class (liftIO)
17−import Data.Aeson (FromJSON, Value)
15+import Data.Aeson (Value)
16+import Data.Char (toLower)
1817import Data.Foldable
19−import Data.List.Extra
18+import Data.List
2019import Data.Rope.UTF16 (Rope)
2120import qualified Data.Rope.UTF16 as Rope
2221import Development.IDE.Core.PositionMapping (fromCurrent, toCurrent)
2322import Development.IDE.GHC.Util
2423import qualified Data.Text as T
25−import Data.Typeable
2624import Development.IDE.Spans.Common
2725import Development.IDE.Test
2826import Development.IDE.Test.Runfiles
2927import Development.IDE.Types.Location
30−import Development.Shake (getDirectoryFilesIO)
31−import Language.Haskell.LSP.Test
28+import qualified Language.Haskell.LSP.Test as LSPTest
29+import Language.Haskell.LSP.Test hiding (openDoc')
3230import Language.Haskell.LSP.Messages
3331import Language.Haskell.LSP.Types
3432import Language.Haskell.LSP.Types.Capabilities
35−import qualified Language.Haskell.LSP.Types.Lens as Lsp (diagnostics, params, message)
3633import Language.Haskell.LSP.VFS (applyChange)
37−import Network.URI
38−import System.Environment.Blank (getEnv, setEnv, unsetEnv)
34+import System.Environment.Blank (setEnv)
3935import System.FilePath
4036import System.IO.Extra
4137import System.Directory
@@ -43,41 +39,35 @@ import Test.QuickCheck
4339import Test.QuickCheck.Instances ()
4440import Test.Tasty
4541import Test.Tasty.ExpectedFailure
46−import Test.Tasty.Ingredients.Rerun
4742import Test.Tasty.HUnit
4843import Test.Tasty.QuickCheck
4944import Data.Maybe
5045
5146main :: 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− ]
47+main = defaultMain $ testGroup "HIE"
48+ [ testSession "open close" $ do
49+ doc <- openDoc' "Testing.hs" "haskell" ""
50+ void (skipManyTill anyMessage message :: Session WorkDoneProgressCreateRequest)
51+ void (skipManyTill anyMessage message :: Session WorkDoneProgressBeginNotification)
52+ closeDoc doc
53+ void (skipManyTill anyMessage message :: Session WorkDoneProgressEndNotification)
54+ , initializeResponseTests
55+ , completionTests
56+ , cppTests
57+ , diagnosticTests
58+ , codeActionTests
59+ , codeLensesTests
60+ , outlineTests
61+ , findDefinitionAndHoverTests
62+ , pluginTests
63+ , preprocessorTests
64+ , thTests
65+ , unitTests
66+ , haddockTests
67+ , positionMappingTests
68+ , watchedFilesTests
69+ , cradleTests
70+ ]
8171
8272initializeResponseTests :: TestTree
8373initializeResponseTests = withResource acquire release tests where
@@ -112,7 +102,7 @@ initializeResponseTests = withResource acquire release tests where
112102 , chk "NO doc link" _documentLinkProvider Nothing
113103 , chk "NO color" _colorProvider (Just $ ColorOptionsStatic False)
114104 , chk "NO folding range" _foldingRangeProvider (Just $ FoldingRangeOptionsStatic False)
115− , che " execute command" _executeCommandProvider (Just $ ExecuteCommandOptions $ List ["typesignature.add"])
105+ , chk " execute command" _executeCommandProvider (Just $ ExecuteCommandOptions $ List ["typesignature.add"])
116106 , chk " workspace" _workspace (Just $ WorkspaceOptions (Just WorkspaceFolderOptions{_supported = Just True, _changeNotifications = Just ( WorkspaceFolderChangeNotificationsBool True )}))
117107 , chk "NO experimental" _experimental Nothing
118108 ] where
@@ -128,17 +118,8 @@ initializeResponseTests = withResource acquire release tests where
128118 chk title getActual expected =
129119 testCase title $ getInitializeResponse >>= \ir -> expected @=? (getActual . innerCaps) ir
130120
131− che :: TestName -> (InitializeResponseCapabilitiesInner -> Maybe ExecuteCommandOptions) -> Maybe ExecuteCommandOptions -> TestTree
132− che title getActual _expected = testCase title doTest
133− where
134− doTest = do
135− ir <- getInitializeResponse
136− let Just ExecuteCommandOptions {_commands = List [command]} = getActual $ innerCaps ir
137− True @=? T.isSuffixOf "typesignature.add" command
138−
139−
140121 innerCaps :: InitializeResponse -> InitializeResponseCapabilitiesInner
141− innerCaps (ResponseMessage _ _ (Right (InitializeResponseCapabilities c))) = c
122+ innerCaps (ResponseMessage _ _ (Just (InitializeResponseCapabilities c)) _) = c
142123 innerCaps _ = error "this test only expects inner capabilities"
143124
144125 acquire :: IO InitializeResponse
@@ -152,7 +133,7 @@ diagnosticTests :: TestTree
152133diagnosticTests = testGroup "diagnostics"
153134 [ testSessionWait "fix syntax error" $ do
154135 let content = T.unlines [ "module Testing wher" ]
155− doc <- createDoc "Testing.hs" "haskell" content
136+ doc <- openDoc' "Testing.hs" "haskell" content
156137 expectDiagnostics [("Testing.hs", [(DsError, (0, 15), "parse error")])]
157138 let change = TextDocumentContentChangeEvent
158139 { _range = Just (Range (Position 0 15) (Position 0 19))
@@ -163,7 +144,7 @@ diagnosticTests = testGroup "diagnostics"
163144 expectDiagnostics [("Testing.hs", [])]
164145 , testSessionWait "introduce syntax error" $ do
165146 let content = T.unlines [ "module Testing where" ]
166− doc <- createDoc "Testing.hs" "haskell" content
147+ doc <- openDoc' "Testing.hs" "haskell" content
167148 void $ skipManyTill anyMessage (message :: Session WorkDoneProgressCreateRequest)
168149 void $ skipManyTill anyMessage (message :: Session WorkDoneProgressBeginNotification)
169150 let change = TextDocumentContentChangeEvent
@@ -181,7 +162,7 @@ diagnosticTests = testGroup "diagnostics"
181162 , "bar :: Int -> Int -> Int"
182163 , "bar a b = cd + b"
183164 ]
184− _ <- createDoc "Testing.hs" "haskell" content
165+ _ <- openDoc' "Testing.hs" "haskell" content
185166 expectDiagnostics
186167 [ ( "Testing.hs"
187168 , [ (DsError, (2, 14), "Variable not in scope: ab")
@@ -195,7 +176,7 @@ diagnosticTests = testGroup "diagnostics"
195176 , "foo :: Int -> String -> Int"
196177 , "foo a b = a + b"
197178 ]
198− _ <- createDoc "Testing.hs" "haskell" content
179+ _ <- openDoc' "Testing.hs" "haskell" content
199180 expectDiagnostics
200181 [ ( "Testing.hs"
201182 , [(DsError, (2, 14), "Couldn't match type '[Char]' with 'Int'")]
@@ -207,7 +188,7 @@ diagnosticTests = testGroup "diagnostics"
207188 , "foo :: Int -> String"
208189 , "foo a = _ a"
209190 ]
210− _ <- createDoc "Testing.hs" "haskell" content
191+ _ <- openDoc' "Testing.hs" "haskell" content
211192 expectDiagnostics
212193 [ ( "Testing.hs"
213194 , [(DsError, (2, 8), "Found hole: _ :: Int -> String")]
@@ -229,23 +210,24 @@ diagnosticTests = testGroup "diagnostics"
229210 [ ("A.hs", [(DsError, (2,4), aMessage)])
230211 , ("B.hs", [(DsError, (3,4), bMessage)])]
231212 deferralTest title binding msg = testSessionWait title $ do
232− _ <- createDoc "A.hs" "haskell" $ sourceA binding
233− _ <- createDoc "B.hs" "haskell" sourceB
213+ _ <- openDoc' "A.hs" "haskell" $ sourceA binding
214+ _ <- openDoc' "B.hs" "haskell" sourceB
234215 expectDiagnostics $ expectedDs msg
235216 in
236217 [ deferralTest "type error" "True" "Couldn't match expected type"
237218 , deferralTest "typed hole" "_" "Found hole"
238219 , deferralTest "out of scope var" "unbound" "Variable not in scope"
220+ , deferralTest "message shows error" "True" "A.hs:3:5: error:"
239221 ]
240222
241223 , testSessionWait "remove required module" $ do
242224 let contentA = T.unlines [ "module ModuleA where" ]
243− docA <- createDoc "ModuleA.hs" "haskell" contentA
225+ docA <- openDoc' "ModuleA.hs" "haskell" contentA
244226 let contentB = T.unlines
245227 [ "module ModuleB where"
246228 , "import ModuleA"
247229 ]
248− _ <- createDoc "ModuleB.hs" "haskell" contentB
230+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
249231 let change = TextDocumentContentChangeEvent
250232 { _range = Just (Range (Position 0 0) (Position 0 20))
251233 , _rangeLength = Nothing
@@ -258,20 +240,20 @@ diagnosticTests = testGroup "diagnostics"
258240 [ "module ModuleB where"
259241 , "import ModuleA"
260242 ]
261− _ <- createDoc "ModuleB.hs" "haskell" contentB
243+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
262244 expectDiagnostics [("ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]
263245 let contentA = T.unlines [ "module ModuleA where" ]
264− _ <- createDoc "ModuleA.hs" "haskell" contentA
246+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
265247 expectDiagnostics [("ModuleB.hs", [])]
266248 , testSessionWait "add missing module (non workspace)" $ do
267249 let contentB = T.unlines
268250 [ "module ModuleB where"
269251 , "import ModuleA"
270252 ]
271− _ <- createDoc "/tmp/ModuleB.hs" "haskell" contentB
253+ _ <- openDoc'' "/tmp/ModuleB.hs" "haskell" contentB
272254 expectDiagnostics [("/tmp/ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]
273255 let contentA = T.unlines [ "module ModuleA where" ]
274− _ <- createDoc "/tmp/ModuleA.hs" "haskell" contentA
256+ _ <- openDoc'' "/tmp/ModuleA.hs" "haskell" contentA
275257 expectDiagnostics [("/tmp/ModuleB.hs", [])]
276258 , testSessionWait "cyclic module dependency" $ do
277259 let contentA = T.unlines
@@ -282,8 +264,8 @@ diagnosticTests = testGroup "diagnostics"
282264 [ "module ModuleB where"
283265 , "import ModuleA"
284266 ]
285− _ <- createDoc "ModuleA.hs" "haskell" contentA
286− _ <- createDoc "ModuleB.hs" "haskell" contentB
267+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
268+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
287269 expectDiagnostics
288270 [ ( "ModuleA.hs"
289271 , [(DsError, (1, 7), "Cyclic module dependency between ModuleA, ModuleB")]
@@ -304,9 +286,9 @@ diagnosticTests = testGroup "diagnostics"
304286 let contentBboot = T.unlines
305287 [ "module ModuleB where"
306288 ]
307− _ <- createDoc "ModuleA.hs" "haskell" contentA
308− _ <- createDoc "ModuleB.hs" "haskell" contentB
309− _ <- createDoc "ModuleB.hs-boot" "haskell" contentBboot
289+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
290+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
291+ _ <- openDoc' "ModuleB.hs-boot" "haskell" contentBboot
310292 expectDiagnostics []
311293 , testSessionWait "correct reference used with hs-boot" $ do
312294 let contentB = T.unlines
@@ -328,10 +310,10 @@ diagnosticTests = testGroup "diagnostics"
328310 -- resolved to the hs-boot file
329311 , "y = x"
330312 ]
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
313+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
314+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
315+ _ <- openDoc' "ModuleA.hs-boot" "haskell" contentAboot
316+ _ <- openDoc' "ModuleC.hs" "haskell" contentC
335317 expectDiagnostics []
336318 , testSessionWait "redundant import" $ do
337319 let contentA = T.unlines ["module ModuleA where"]
@@ -340,8 +322,8 @@ diagnosticTests = testGroup "diagnostics"
340322 , "module ModuleB where"
341323 , "import ModuleA"
342324 ]
343− _ <- createDoc "ModuleA.hs" "haskell" contentA
344− _ <- createDoc "ModuleB.hs" "haskell" contentB
325+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
326+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
345327 expectDiagnostics
346328 [ ( "ModuleB.hs"
347329 , [(DsWarning, (2, 0), "The import of 'ModuleA' is redundant")]
@@ -363,8 +345,8 @@ diagnosticTests = testGroup "diagnostics"
363345 , "wrong1 = ThisList.map"
364346 , "wrong2 = BaseList.x"
365347 ]
366− _ <- createDoc "Data/List.hs" "haskell" thisDataListContent
367− _ <- createDoc "Main.hs" "haskell" mainContent
348+ _ <- openDoc' "Data/List.hs" "haskell" thisDataListContent
349+ _ <- openDoc' "Main.hs" "haskell" mainContent
368350 expectDiagnostics
369351 [ ( "Main.hs"
370352 , [(DsError, (6, 9), "Not in scope: \8216ThisList.map\8217")
@@ -379,7 +361,7 @@ diagnosticTests = testGroup "diagnostics"
379361 , "foo :: Ord a => a -> Int"
380362 , "foo a = 1"
381363 ]
382− _ <- createDoc "Foo.hs" "haskell" fooContent
364+ _ <- openDoc' "Foo.hs" "haskell" fooContent
383365 expectDiagnostics
384366 [ ( "Foo.hs"
385367 -- The test is to make sure that warnings contain unqualified names
@@ -404,18 +386,18 @@ diagnosticTests = testGroup "diagnostics"
404386 Just pathB <- pure $ uriToFilePath uriB
405387 uriB <- pure $
406388 let (drive, suffix) = splitDrive pathB
407− in filePathToUri (joinDrive (lower drive) suffix)
389+ in filePathToUri (joinDrive (map toLower drive ) suffix)
408390 liftIO $ createDirectoryIfMissing True (takeDirectory pathB)
409391 liftIO $ writeFileUTF8 pathB $ T.unpack bContent
410392 uriA <- getDocUri "A/A.hs"
411393 Just pathA <- pure $ uriToFilePath uriA
412394 uriA <- pure $
413395 let (drive, suffix) = splitDrive pathA
414− in filePathToUri (joinDrive (lower drive) suffix)
396+ in filePathToUri (joinDrive (map toLower drive ) suffix)
415397 let itemA = TextDocumentItem uriA "haskell" 0 aContent
416398 let a = TextDocumentIdentifier uriA
417399 sendNotification TextDocumentDidOpen (DidOpenTextDocumentParams itemA)
418− diagsNot <- skipManyTill anyMessage diagnostic
400+ diagsNot <- skipManyTill anyMessage message :: Session PublishDiagnosticsNotification
419401 let PublishDiagnosticsParams fileUri diags = _params (diagsNot :: PublishDiagnosticsNotification)
420402 -- Check that if we put a lower-case drive in for A.A
421403 -- the diagnostics for A.B will also be lower-case.
@@ -424,38 +406,6 @@ diagnosticTests = testGroup "diagnostics"
424406 liftIO $ unless ("redundant" `T.isInfixOf` msg) $
425407 assertFailure ("Expected redundant import but got " <> T.unpack msg)
426408 closeDoc a
427− , testSessionWait "haddock parse error" $ do
428− let fooContent = T.unlines
429− [ "module Foo where"
430− , "foo :: Int"
431− , "foo = 1 {-|-}"
432− ]
433− _ <- createDoc "Foo.hs" "haskell" fooContent
434− expectDiagnostics
435− [ ( "Foo.hs"
436− , [(DsError, (2, 8), "Parse error on input")
437− ]
438− )
439− ]
440− , testSessionWait "strip file path" $ do
441− let
442− name = "Testing"
443− content = T.unlines
444− [ "module " <> name <> " where"
445− , "value :: Maybe ()"
446− , "value = [()]"
447− ]
448− _ <- createDoc (T.unpack name <> ".hs") "haskell" content
449− notification <- skipManyTill anyMessage diagnostic
450− let
451− offenders =
452− Lsp.params .
453− Lsp.diagnostics .
454− Lens.folded .
455− Lsp.message .
456− Lens.filtered (T.isInfixOf ("/" <> name <> ".hs:"))
457− failure msg = liftIO $ assertFailure $ "Expected file path to be stripped but got " <> T.unpack msg
458− Lens.mapMOf_ offenders failure notification
459409 ]
460410
461411codeActionTests :: TestTree
@@ -481,26 +431,26 @@ codeLensesTests = testGroup "code lenses"
481431watchedFilesTests :: TestTree
482432watchedFilesTests = testGroup "watched files"
483433 [ testSession' "workspace files" $ \sessionDir -> do
484− liftIO $ writeFile (sessionDir </> "hie.yaml") "cradle: {direct: {arguments: [\"-isrc\"]}}"
485− _doc <- createDoc "A.hs" "haskell" "{-#LANGUAGE NoImplicitPrelude #-}\nmodule A where\nimport WatchedFilesMissingModule"
486− watchedFileRegs <- getWatchedFilesSubscriptionsUntil @PublishDiagnosticsNotification
487−
488− -- Expect 4 subscriptions (A does not get any because it's VFS):
489− -- - /path-to-workspace/WatchedFilesMissingModule.hs
490− -- - /path-to-workspace/WatchedFilesMissingModule.lhs
491− -- - /path-to-workspace/src/WatchedFilesMissingModule.hs
492− -- - /path-to-workspace/src/WatchedFilesMissingModule.lhs
493− liftIO $ length watchedFileRegs @?= 4
434+ liftIO $ writeFile (sessionDir </> "hie.yaml") $ "cradle: {direct: {arguments: [\"-isrc\"]}}"
435+ _ <- openDoc' "A.hs" "haskell" "{-#LANGUAGE NoImplicitPrelude #-}\nmodule A where\nimport B"
436+ watchedFileRegs <- getWatchedFilesSubscriptionsUntilProgressEnd
437+
438+ -- Expect 6 subscriptions (A does not get any because it's VFS):
439+ -- - /path-to-workspace/B.hs
440+ -- - /path-to-workspace/B.lhs
441+ -- - B.hs
442+ -- - B.lhs
443+ -- - src/B.hs
444+ -- - src/B.lhs
445+ liftIO $ length watchedFileRegs @?= 6
494446
495447 , testSession' "non workspace file" $ \sessionDir -> do
496− liftIO $ writeFile (sessionDir </> "hie.yaml") "cradle: {direct: {arguments: [\"-i/tmp\"]}}"
497− _doc <- createDoc "A.hs" "haskell" "{-# LANGUAGE NoImplicitPrelude#-}\nmodule A where\nimport WatchedFilesMissingModule"
498− watchedFileRegs <- getWatchedFilesSubscriptionsUntil @PublishDiagnosticsNotification
448+ liftIO $ writeFile (sessionDir </> "hie.yaml") $ "cradle: {direct: {arguments: [\"-i/tmp\"]}}"
449+ _ <- openDoc' "A.hs" "haskell" "{-# LANGUAGE NoImplicitPrelude#-}\nmodule A where\nimport B"
450+ watchedFileRegs <- getWatchedFilesSubscriptionsUntilProgressEnd
499451
500− -- Expect 2 subscriptions (/tmp does not get any as it is out of the workspace):
501− -- - /path-to-workspace/WatchedFilesMissingModule.hs
502− -- - /path-to-workspace/WatchedFilesMissingModule.lhs
503− liftIO $ length watchedFileRegs @?= 2
452+ -- Expect 4 subscriptions:
453+ liftIO $ length watchedFileRegs @?= 4
504454
505455 -- TODO add a test for didChangeWorkspaceFolder
506456 ]
@@ -513,7 +463,7 @@ renameActionTests = testGroup "rename actions"
513463 , "foo :: Int -> Int"
514464 , "foo argName = argNme"
515465 ]
516− doc <- createDoc "Testing.hs" "haskell" content
466+ doc <- openDoc' "Testing.hs" "haskell" content
517467 _ <- waitForDiagnostics
518468 action <- findCodeAction doc (Range (Position 2 14) (Position 2 20)) "Replace with ‘argName’"
519469 executeCodeAction action
@@ -531,7 +481,7 @@ renameActionTests = testGroup "rename actions"
531481 , "foo :: Maybe a -> [a]"
532482 , "foo = maybToList"
533483 ]
534− doc <- createDoc "Testing.hs" "haskell" content
484+ doc <- openDoc' "Testing.hs" "haskell" content
535485 _ <- waitForDiagnostics
536486 action <- findCodeAction doc (Range (Position 3 6) (Position 3 16)) "Replace with ‘maybeToList’"
537487 executeCodeAction action
@@ -549,7 +499,7 @@ renameActionTests = testGroup "rename actions"
549499 , "foo :: Char -> Char -> Char -> Char"
550500 , "foo argument1 argument2 argument3 = argumentX"
551501 ]
552− doc <- createDoc "Testing.hs" "haskell" content
502+ doc <- openDoc' "Testing.hs" "haskell" content
553503 _ <- waitForDiagnostics
554504 _ <- findCodeActions doc (Range (Position 2 36) (Position 2 45))
555505 ["Replace with ‘argument1’", "Replace with ‘argument2’", "Replace with ‘argument3’"]
@@ -561,7 +511,7 @@ renameActionTests = testGroup "rename actions"
561511 , "monus x y = max 0 (x - y)"
562512 , "foo x y = x `monnus` y"
563513 ]
564− doc <- createDoc "Testing.hs" "haskell" content
514+ doc <- openDoc' "Testing.hs" "haskell" content
565515 _ <- waitForDiagnostics
566516 actionsOrCommands <- getCodeActions doc (Range (Position 3 12) (Position 3 20))
567517 [fixTypo] <- pure [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, "monus" `T.isInfixOf` actionTitle ]
@@ -584,7 +534,7 @@ typeWildCardActionTests = testGroup "type wildcard actions"
584534 , "func :: _"
585535 , "func x = x"
586536 ]
587− doc <- createDoc "Testing.hs" "haskell" content
537+ doc <- openDoc' "Testing.hs" "haskell" content
588538 _ <- waitForDiagnostics
589539 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
590540 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
@@ -604,7 +554,7 @@ typeWildCardActionTests = testGroup "type wildcard actions"
604554 , "func :: _"
605555 , "func x y = x + y"
606556 ]
607− doc <- createDoc "Testing.hs" "haskell" content
557+ doc <- openDoc' "Testing.hs" "haskell" content
608558 _ <- waitForDiagnostics
609559 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
610560 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
@@ -627,7 +577,7 @@ typeWildCardActionTests = testGroup "type wildcard actions"
627577 , " y = x * 2"
628578 , " in y"
629579 ]
630− doc <- createDoc "Testing.hs" "haskell" content
580+ doc <- openDoc' "Testing.hs" "haskell" content
631581 _ <- waitForDiagnostics
632582 actionsOrCommands <- getCodeActions doc (Range (Position 4 1) (Position 4 10))
633583 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
@@ -652,7 +602,7 @@ removeImportTests = testGroup "remove import actions"
652602 let contentA = T.unlines
653603 [ "module ModuleA where"
654604 ]
655− _docA <- createDoc "ModuleA.hs" "haskell" contentA
605+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
656606 let contentB = T.unlines
657607 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
658608 , "module ModuleB where"
@@ -660,7 +610,7 @@ removeImportTests = testGroup "remove import actions"
660610 , "stuffB :: Integer"
661611 , "stuffB = 123"
662612 ]
663− docB <- createDoc "ModuleB.hs" "haskell" contentB
613+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
664614 _ <- waitForDiagnostics
665615 [CACodeAction action@CodeAction { _title = actionTitle }]
666616 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -678,7 +628,7 @@ removeImportTests = testGroup "remove import actions"
678628 let contentA = T.unlines
679629 [ "module ModuleA where"
680630 ]
681− _docA <- createDoc "ModuleA.hs" "haskell" contentA
631+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
682632 let contentB = T.unlines
683633 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
684634 , "module ModuleB where"
@@ -686,7 +636,7 @@ removeImportTests = testGroup "remove import actions"
686636 , "stuffB :: Integer"
687637 , "stuffB = 123"
688638 ]
689− docB <- createDoc "ModuleB.hs" "haskell" contentB
639+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
690640 _ <- waitForDiagnostics
691641 [CACodeAction action@CodeAction { _title = actionTitle }]
692642 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -708,14 +658,14 @@ removeImportTests = testGroup "remove import actions"
708658 , "stuffB = 123"
709659 , "stuffC = ()"
710660 ]
711− _docA <- createDoc "ModuleA.hs" "haskell" contentA
661+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
712662 let contentB = T.unlines
713663 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
714664 , "module ModuleB where"
715665 , "import ModuleA (stuffA, stuffB, stuffC, stuffA)"
716666 , "main = print stuffB"
717667 ]
718− docB <- createDoc "ModuleB.hs" "haskell" contentB
668+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
719669 _ <- waitForDiagnostics
720670 [CACodeAction action@CodeAction { _title = actionTitle }]
721671 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -737,18 +687,22 @@ removeImportTests = testGroup "remove import actions"
737687 , "stuffB :: Integer"
738688 , "stuffB = 123"
739689 ]
740− _docA <- createDoc "ModuleA.hs" "haskell" contentA
690+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
741691 let contentB = T.unlines
742692 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
743693 , "module ModuleB where"
744694 , "import qualified ModuleA as A ((<?>), stuffB, (!!))"
745695 , "main = print A.stuffB"
746696 ]
747− docB <- createDoc "ModuleB.hs" "haskell" contentB
697+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
748698 _ <- waitForDiagnostics
749699 [CACodeAction action@CodeAction { _title = actionTitle }]
750700 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
701+#if MIN_GHC_API_VERSION(8,6,0)
751702 liftIO $ "Remove !!, <?> from import" @=? actionTitle
703+#else
704+ liftIO $ "Remove A.!!, A.<?> from import" @=? actionTitle
705+#endif
752706 executeCodeAction action
753707 contentAfterAction <- documentContents docB
754708 let expectedContentAfterAction = T.unlines
@@ -765,14 +719,14 @@ removeImportTests = testGroup "remove import actions"
765719 , "stuffB :: Integer"
766720 , "stuffB = 123"
767721 ]
768− _docA <- createDoc "ModuleA.hs" "haskell" contentA
722+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
769723 let contentB = T.unlines
770724 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
771725 , "module ModuleB where"
772726 , "import ModuleA (A(..), stuffB)"
773727 , "main = print stuffB"
774728 ]
775− docB <- createDoc "ModuleB.hs" "haskell" contentB
729+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
776730 _ <- waitForDiagnostics
777731 [CACodeAction action@CodeAction { _title = actionTitle }]
778732 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -792,14 +746,14 @@ removeImportTests = testGroup "remove import actions"
792746 , "data D = A | B"
793747 , "data E = F"
794748 ]
795− _docA <- createDoc "ModuleA.hs" "haskell" contentA
749+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
796750 let contentB = T.unlines
797751 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
798752 , "module ModuleB where"
799753 , "import ModuleA (D(A,B), E(F))"
800754 , "main = B"
801755 ]
802− docB <- createDoc "ModuleB.hs" "haskell" contentB
756+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
803757 _ <- waitForDiagnostics
804758 [CACodeAction action@CodeAction { _title = actionTitle }]
805759 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -940,8 +894,8 @@ extendImportTests = testGroup "extend import actions"
940894 ]
941895 where
942896 template contentA contentB range expectedAction expectedContentB = do
943− _docA <- createDoc "ModuleA.hs" "haskell" contentA
944− docB <- createDoc "ModuleB.hs" "haskell" contentB
897+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
898+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
945899 _ <- waitForDiagnostics
946900 CACodeAction action@CodeAction { _title = actionTitle } : _
947901 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -981,8 +935,6 @@ suggestImportTests = testGroup "suggest import actions"
981935 , test True [] "f :: Typeable a => a" ["f = undefined"] "import Data.Typeable (Typeable)"
982936 , test True [] "f = pack" [] "import Data.Text (pack)"
983937 , test True [] "f :: Text" ["f = undefined"] "import Data.Text (Text)"
984− , test True [] "f = [] & id" [] "import Data.Function ((&))"
985− , test True [] "f = (&) [] id" [] "import Data.Function ((&))"
986938 ]
987939 ]
988940 where
@@ -991,20 +943,19 @@ suggestImportTests = testGroup "suggest import actions"
991943 after = T.unlines $ "module A where" : ["import " <> x | x <- imps] ++ [newImp] ++ def : other
992944 cradle = "cradle: {direct: {arguments: [-hide-all-packages, -package, base, -package, text, -package-env, -]}}"
993945 liftIO $ writeFileUTF8 (dir </> "hie.yaml") cradle
994− doc <- createDoc "Test.hs" "haskell" before
946+ doc <- openDoc' "Test.hs" "haskell" before
995947 _diags <- waitForDiagnostics
996948 let defLine = length imps + 1
997949 range = Range (Position defLine 0) (Position defLine maxBound)
998950 actions <- getCodeActions doc range
999− if wanted
1000− then do
1001− action <- liftIO $ pickActionWithTitle newImp actions
1002− executeCodeAction action
1003− contentAfterAction <- documentContents doc
1004− liftIO $ after @=? contentAfterAction
1005− else
1006− liftIO $ [_title | CACodeAction CodeAction{_title} <- actions, _title == newImp ] @?= []
1007−
951+ case wanted of
952+ False ->
953+ liftIO $ [_title | CACodeAction CodeAction{_title} <- actions, _title == newImp ] @?= []
954+ True -> do
955+ action <- liftIO $ pickActionWithTitle newImp actions
956+ executeCodeAction action
957+ contentAfterAction <- documentContents doc
958+ liftIO $ after @=? contentAfterAction
1008959
1009960addExtensionTests :: TestTree
1010961addExtensionTests = testGroup "add language extension actions"
@@ -1051,7 +1002,7 @@ addExtensionTests = testGroup "add language extension actions"
10511002 ]
10521003 where
10531004 template initialContent range expectedAction expectedContents = do
1054− doc <- createDoc "Module.hs" "haskell" initialContent
1005+ doc <- openDoc' "Module.hs" "haskell" initialContent
10551006 _ <- waitForDiagnostics
10561007 CACodeAction action@CodeAction { _title = actionTitle } : _
10571008 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1074,7 +1025,7 @@ insertNewDefinitionTests = testGroup "insert new definition actions"
10741025 [""
10751026 ,"someOtherCode = ()"
10761027 ]
1077− docB <- createDoc "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
1028+ docB <- openDoc' "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
10781029 _ <- waitForDiagnostics
10791030 CACodeAction action@CodeAction { _title = actionTitle } : _
10801031 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1098,7 +1049,7 @@ insertNewDefinitionTests = testGroup "insert new definition actions"
10981049 [""
10991050 ,"someOtherCode = ()"
11001051 ]
1101− docB <- createDoc "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
1052+ docB <- openDoc' "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
11021053 _ <- waitForDiagnostics
11031054 CACodeAction action@CodeAction { _title = actionTitle } : _
11041055 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1137,8 +1088,8 @@ fixConstructorImportTests = testGroup "fix import actions"
11371088 ]
11381089 where
11391090 template contentA contentB range expectedAction expectedContentB = do
1140− _docA <- createDoc "ModuleA.hs" "haskell" contentA
1141− docB <- createDoc "ModuleB.hs" "haskell" contentB
1091+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
1092+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
11421093 _diags <- waitForDiagnostics
11431094 CACodeAction action@CodeAction { _title = actionTitle } : _
11441095 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1157,7 +1108,7 @@ importRenameActionTests = testGroup "import rename actions"
11571108 [ "module Testing where"
11581109 , "import Data.Mape"
11591110 ]
1160− doc <- createDoc "Testing.hs" "haskell" content
1111+ doc <- openDoc' "Testing.hs" "haskell" content
11611112 _ <- waitForDiagnostics
11621113 actionsOrCommands <- getCodeActions doc (Range (Position 2 8) (Position 2 16))
11631114 let [changeToMap] = [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, ("Data." <> modname) `T.isInfixOf` actionTitle ]
@@ -1194,7 +1145,7 @@ fillTypedHoleTests = let
11941145 newA newB newC = testSession (T.unpack actionTitle) $ do
11951146 let originalCode = sourceCode oldA oldB oldC
11961147 let expectedCode = sourceCode newA newB newC
1197− doc <- createDoc "Testing.hs" "haskell" originalCode
1148+ doc <- openDoc' "Testing.hs" "haskell" originalCode
11981149 _ <- waitForDiagnostics
11991150 actionsOrCommands <- getCodeActions doc (Range (Position 9 0) (Position 9 maxBound))
12001151 chosenAction <- liftIO $ pickActionWithTitle actionTitle actionsOrCommands
@@ -1242,7 +1193,7 @@ addSigActionTests = let
12421193 def >:: sig = testSession (T.unpack def) $ do
12431194 let originalCode = before def
12441195 let expectedCode = after' def sig
1245− doc <- createDoc "Sigs.hs" "haskell" originalCode
1196+ doc <- openDoc' "Sigs.hs" "haskell" originalCode
12461197 _ <- waitForDiagnostics
12471198 actionsOrCommands <- getCodeActions doc (Range (Position 3 1) (Position 3 maxBound))
12481199 chosenAction <- liftIO $ pickActionWithTitle ("add signature: " <> sig) actionsOrCommands
@@ -1274,7 +1225,7 @@ addSigLensesTests = let
12741225 sigSession withMissing def sig = testSession (T.unpack def) $ do
12751226 let originalCode = before withMissing def
12761227 let expectedCode = after' withMissing def sig
1277− doc <- createDoc "Sigs.hs" "haskell" originalCode
1228+ doc <- openDoc' "Sigs.hs" "haskell" originalCode
12781229 [CodeLens {_command = Just c}] <- getCodeLenses doc
12791230 executeCommand c
12801231 modifiedCode <- getDocumentEdit doc
@@ -1296,39 +1247,33 @@ addSigLensesTests = let
12961247 ]
12971248 ]
12981249
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−
13201250findDefinitionAndHoverTests :: TestTree
13211251findDefinitionAndHoverTests = let
13221252
1323− tst (get, check) pos targetRange title = testSessionWithExtraFiles "hover" title $ \dir -> do
1324− doc <- openTestDataDoc (dir </> sourceFilePath)
1253+ tst (get, check) pos targetRange title = testSession title $ do
1254+ doc <- openTestDataDoc sourceFilePath
13251255 found <- get doc pos
13261256 check found targetRange
13271257
1258+ checkDefs :: [Location] -> [Expect] -> Session ()
1259+ checkDefs defs expectations = traverse_ check expectations where
13281260
1261+ check (ExpectRange expectedRange) = do
1262+ assertNDefinitionsFound 1 defs
1263+ assertRangeCorrect (head defs) expectedRange
1264+ check ExpectNoDefinitions = do
1265+ assertNDefinitionsFound 0 defs
1266+ check ExpectExternFail = liftIO $ assertFailure "Expecting to fail to find in external file"
1267+ check _ = pure () -- all other expectations not relevant to getDefinition
13291268
1330− checkHover :: Maybe Hover -> Session [Expect] -> Session ()
1331− checkHover hover expectations = traverse_ check =<< expectations where
1269+ assertNDefinitionsFound :: Int -> [a] -> Session ()
1270+ assertNDefinitionsFound n defs = liftIO $ assertEqual "number of definitions" n (length defs)
1271+
1272+ assertRangeCorrect Location{_range = foundRange} expectedRange =
1273+ liftIO $ expectedRange @=? foundRange
1274+
1275+ checkHover :: Maybe Hover -> [Expect] -> Session ()
1276+ checkHover hover expectations = traverse_ check expectations where
13321277
13331278 check expected =
13341279 case hover of
@@ -1371,12 +1316,9 @@ findDefinitionAndHoverTests = let
13711316
13721317 mkFindTests tests = testGroup "get"
13731318 [ testGroup "definition" $ mapMaybe fst tests
1374− , testGroup "hover" $ mapMaybe snd tests
1375− , checkFileCompiles sourceFilePath ]
1376−
1377− test runDef runHover look expect = testM runDef runHover look (return expect)
1319+ , testGroup "hover" $ mapMaybe snd tests ]
13781320
1379− testM runDef runHover look expect title =
1321+ test runDef runHover look expect title =
13801322 ( runDef $ tst def look expect title
13811323 , runHover $ tst hover look expect title ) where
13821324 def = (getDefinitions, checkDefs)
@@ -1384,100 +1326,87 @@ findDefinitionAndHoverTests = let
13841326 --type_ = (getTypeDefinitions, checkTDefs) -- getTypeDefinitions always times out
13851327
13861328 -- search locations expectations on results
1387− fffL4 = _start fffR ; fffR = mkRange 8 4 8 7 ; fff = [ExpectRange fffR]
1388− fffL8 = Position 12 4 ;
1389− fffL14 = Position 18 7 ;
1390− aaaL14 = Position 18 20 ; aaa = [mkR 11 0 11 3]
1391− dcL7 = Position 11 11 ; tcDC = [mkR 7 23 9 16]
1392− dcL12 = Position 16 11 ;
1393− xtcL5 = Position 9 11 ; xtc = [ExpectExternFail, ExpectHoverText ["Int", "Defined in ‘GHC.Types’"]]
1394− tcL6 = Position 10 11 ; tcData = [mkR 7 0 9 16, ExpectHoverText ["TypeConstructor", "GotoHover.hs:8:1"]]
1395− vvL16 = Position 20 12 ; vv = [mkR 20 4 20 6]
1396− opL16 = Position 20 15 ; op = [mkR 21 2 21 4]
1397− opL18 = Position 22 22 ; opp = [mkR 22 13 22 17]
1398− aL18 = Position 22 20 ; apmp = [mkR 22 10 22 11]
1399− b'L19 = Position 23 13 ; bp = [mkR 23 6 23 7]
1400− xvL20 = Position 24 8 ; xvMsg = [ExpectExternFail, ExpectHoverText ["Data.Text.pack", ":: String -> Text"]]
1401− clL23 = Position 27 11 ; cls = [mkR 25 0 26 20, ExpectHoverText ["MyClass", "GotoHover.hs:26:1"]]
1402− clL25 = Position 29 9
1403− eclL15 = Position 19 8 ; ecls = [ExpectExternFail, ExpectHoverText ["Num", "Defined in ‘GHC.Num’"]]
1404− dnbL29 = Position 33 18 ; dnb = [ExpectHoverText [":: ()"], mkR 33 12 33 21]
1405− dnbL30 = Position 34 23
1406− lcbL33 = Position 37 26 ; lcb = [ExpectHoverText [":: Char"], mkR 37 26 37 27]
1407− lclL33 = Position 37 22
1408− mclL36 = Position 40 1 ; mcl = [mkR 40 0 40 14]
1409− mclL37 = Position 41 1
1410− spaceL37 = Position 41 24 ; space = [ExpectNoDefinitions, ExpectHoverText [":: Char"]]
1411− docL41 = Position 45 1 ; doc = [ExpectHoverText ["Recognizable docs: kpqz"]]
1329+ fffL4 = _start fffR ; fffR = mkRange 4 4 4 7 ; fff = [ExpectRange fffR]
1330+ fffL8 = Position 8 4 ;
1331+ fffL14 = Position 14 7 ;
1332+ aaaL14 = Position 14 20 ; aaa = [mkR 7 0 7 3]
1333+ dcL7 = Position 7 11 ; tcDC = [mkR 3 23 5 16]
1334+ dcL12 = Position 12 11 ;
1335+ xtcL5 = Position 5 11 ; xtc = [ExpectExternFail, ExpectHoverText ["Int", "Defined in ‘GHC.Types’"]]
1336+ tcL6 = Position 6 11 ; tcData = [mkR 3 0 5 16, ExpectHoverText ["TypeConstructor", "GotoHover.hs:4:1"]]
1337+ vvL16 = Position 16 12 ; vv = [mkR 16 4 16 6]
1338+ opL16 = Position 16 15 ; op = [mkR 17 2 17 4]
1339+ opL18 = Position 18 22 ; opp = [mkR 18 13 18 17]
1340+ aL18 = Position 18 20 ; apmp = [mkR 18 10 18 11]
1341+ b'L19 = Position 19 13 ; bp = [mkR 19 6 19 7]
1342+ xvL20 = Position 20 8 ; xvMsg = [ExpectExternFail, ExpectHoverText ["Data.Text.pack", ":: String -> Text"]]
1343+ clL23 = Position 23 11 ; cls = [mkR 21 0 22 20, ExpectHoverText ["MyClass", "GotoHover.hs:22:1"]]
1344+ clL25 = Position 25 9
1345+ eclL15 = Position 15 8 ; ecls = [ExpectExternFail, ExpectHoverText ["Num", "Defined in ‘GHC.Num’"]]
1346+ dnbL29 = Position 29 18 ; dnb = [ExpectHoverText [":: ()"], mkR 29 12 29 21]
1347+ dnbL30 = Position 30 23
1348+ lcbL33 = Position 33 26 ; lcb = [ExpectHoverText [":: Char"], mkR 33 26 33 27]
1349+ lclL33 = Position 33 22
1350+ mclL36 = Position 36 1 ; mcl = [mkR 36 0 36 14]
1351+ mclL37 = Position 37 1
1352+ spaceL37 = Position 37 24 ; space = [ExpectNoDefinitions, ExpectHoverText [":: Char"]]
1353+ docL41 = Position 41 1 ; doc = [ExpectHoverText ["Recognizable docs: kpqz"]]
14121354 ; constr = [ExpectHoverText ["Monad m"]]
1413− eitL40 = Position 44 28 ; kindE = [ExpectHoverText [":: * -> * -> *\n"]]
1414− intL40 = Position 44 34 ; kindI = [ExpectHoverText [":: *\n"]]
1415− tvrL40 = Position 44 37 ; kindV = [ExpectHoverText [":: * -> *\n"]]
1416− intL41 = Position 45 20 ; litI = [ExpectHoverText ["7518"]]
1417− chrL36 = Position 41 24 ; litC = [ExpectHoverText ["'f'"]]
1418− txtL8 = Position 12 14 ; litT = [ExpectHoverText ["\"dfgy\""]]
1419− lstL43 = Position 47 12 ; litL = [ExpectHoverText ["[8391 :: Int, 6268]"]]
1420− outL45 = Position 49 3 ; outSig = [ExpectHoverText ["outer", "Bool"], mkR 46 0 46 5]
1421− innL48 = Position 52 5 ; innSig = [ExpectHoverText ["inner", "Char"], mkR 49 2 49 7]
1422− imported = Position 56 13 ; importedSig = getDocUri "Foo.hs" >>= \foo -> return [ExpectHoverText ["foo", "Foo"], mkL foo 4 0 4 3]
1423− reexported = Position 55 14 ; reexportedSig = getDocUri "Bar.hs" >>= \bar -> return [ExpectHoverText ["Bar", "Bar"], mkL bar 2 0 2 14]
1355+ eitL40 = Position 40 28 ; kindE = [ExpectHoverText [":: * -> * -> *\n"]]
1356+ intL40 = Position 40 34 ; kindI = [ExpectHoverText [":: *\n"]]
1357+ tvrL40 = Position 40 37 ; kindV = [ExpectHoverText [":: * -> *\n"]]
1358+ intL41 = Position 41 20 ; litI = [ExpectHoverText ["7518"]]
1359+ chrL36 = Position 37 24 ; litC = [ExpectHoverText ["'f'"]]
1360+ txtL8 = Position 8 14 ; litT = [ExpectHoverText ["\"dfgy\""]]
1361+ lstL43 = Position 43 12 ; litL = [ExpectHoverText ["[8391 :: Int, 6268]"]]
1362+ outL45 = Position 45 3 ; outSig = [ExpectHoverText ["outer", "Bool"], mkR 46 0 46 5]
1363+ innL48 = Position 48 5 ; innSig = [ExpectHoverText ["inner", "Char"], mkR 49 2 49 7]
14241364 in
14251365 mkFindTests
1426− -- def hover look expect
1427− [ test yes yes fffL4 fff "field in record definition"
1428− , test broken broken fffL8 fff "field in record construction #71"
1429− , test yes yes fffL14 fff "field name used as accessor" -- 120 in Calculate.hs
1430− , test yes yes aaaL14 aaa "top-level name" -- 120
1431− , test yes yes dcL7 tcDC "data constructor record #247"
1432− , test yes yes dcL12 tcDC "data constructor plain" -- 121
1433− , test yes yes tcL6 tcData "type constructor #248" -- 147
1434− , test broken yes xtcL5 xtc "type constructor external #248,249"
1435− , test broken yes xvL20 xvMsg "value external package #249" -- 120
1436− , test yes yes vvL16 vv "plain parameter" -- 120
1437− , test yes yes aL18 apmp "pattern match name" -- 120
1438− , test yes yes opL16 op "top-level operator" -- 120, 123
1439− , test yes yes opL18 opp "parameter operator" -- 120
1440− , test yes yes b'L19 bp "name in backticks" -- 120
1441− , test yes yes clL23 cls "class in instance declaration #250"
1442− , test yes yes clL25 cls "class in signature #250" -- 147
1443− , test broken yes eclL15 ecls "external class in signature #249,250"
1444− , test yes yes dnbL29 dnb "do-notation bind" -- 137
1445− , test yes yes dnbL30 dnb "do-notation lookup"
1446− , test yes yes lcbL33 lcb "listcomp bind" -- 137
1447− , test yes yes lclL33 lcb "listcomp lookup"
1448− , test yes yes mclL36 mcl "top-level fn 1st clause"
1449− , test yes yes mclL37 mcl "top-level fn 2nd clause #246"
1450− , test yes yes spaceL37 space "top-level fn on space #315"
1451− , test no broken docL41 doc "documentation #7"
1452− , test no yes eitL40 kindE "kind of Either #273"
1453− , test no yes intL40 kindI "kind of Int #273"
1454− , test no broken tvrL40 kindV "kind of (* -> *) type variable #273"
1455− , test no yes intL41 litI "literal Int in hover info #274"
1456− , test no yes chrL36 litC "literal Char in hover info #274"
1457− , test no yes txtL8 litT "literal Text in hover info #274"
1458− , test no yes lstL43 litL "literal List in hover info #274"
1459− , test no yes docL41 constr "type constraint in hover info #283"
1460− , test broken broken outL45 outSig "top-level signature #310"
1461− , test broken broken innL48 innSig "inner signature #310"
1462− , testM yes yes imported importedSig "Imported symbol"
1463− , testM yes yes reexported reexportedSig "Imported symbol (reexported)"
1366+ -- def hover look expect
1367+ [ test yes yes fffL4 fff "field in record definition"
1368+ , test broken broken fffL8 fff "field in record construction #71"
1369+ , test yes yes fffL14 fff "field name used as accessor" -- 120 in Calculate.hs
1370+ , test yes yes aaaL14 aaa "top-level name" -- 120
1371+ , test yes yes dcL7 tcDC "data constructor record #247"
1372+ , test yes yes dcL12 tcDC "data constructor plain" -- 121
1373+ , test yes yes tcL6 tcData "type constructor #248" -- 147
1374+ , test broken yes xtcL5 xtc "type constructor external #248,249"
1375+ , test broken yes xvL20 xvMsg "value external package #249" -- 120
1376+ , test yes yes vvL16 vv "plain parameter" -- 120
1377+ , test yes yes aL18 apmp "pattern match name" -- 120
1378+ , test yes yes opL16 op "top-level operator" -- 120, 123
1379+ , test yes yes opL18 opp "parameter operator" -- 120
1380+ , test yes yes b'L19 bp "name in backticks" -- 120
1381+ , test yes yes clL23 cls "class in instance declaration #250"
1382+ , test yes yes clL25 cls "class in signature #250" -- 147
1383+ , test broken yes eclL15 ecls "external class in signature #249,250"
1384+ , test yes yes dnbL29 dnb "do-notation bind" -- 137
1385+ , test yes yes dnbL30 dnb "do-notation lookup"
1386+ , test yes yes lcbL33 lcb "listcomp bind" -- 137
1387+ , test yes yes lclL33 lcb "listcomp lookup"
1388+ , test yes yes mclL36 mcl "top-level fn 1st clause"
1389+ , test yes yes mclL37 mcl "top-level fn 2nd clause #246"
1390+ , test yes yes spaceL37 space "top-level fn on space #315"
1391+ , test no broken docL41 doc "documentation #7"
1392+ , test no yes eitL40 kindE "kind of Either #273"
1393+ , test no yes intL40 kindI "kind of Int #273"
1394+ , test no broken tvrL40 kindV "kind of (* -> *) type variable #273"
1395+ , test no yes intL41 litI "literal Int in hover info #274"
1396+ , test no yes chrL36 litC "literal Char in hover info #274"
1397+ , test no yes txtL8 litT "literal Text in hover info #274"
1398+ , test no yes lstL43 litL "literal List in hover info #274"
1399+ , test no yes docL41 constr "type constraint in hover info #283"
1400+ , test broken broken outL45 outSig "top-level signature #310"
1401+ , test broken broken innL48 innSig "inner signature #310"
14641402 ]
14651403 where yes, broken :: (TestTree -> Maybe TestTree)
14661404 yes = Just -- test should run and pass
14671405 broken = Just . (`xfail` "known broken")
14681406 no = const Nothing -- don't run this test at all
14691407
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−
14781408pluginTests :: TestTree
1479−pluginTests = (`xfail8101` "known broken (#556)")
1480− $ testSessionWait "plugins" $ do
1409+pluginTests = testSessionWait "plugins" $ do
14811410 let content =
14821411 T.unlines
14831412 [ "{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}"
@@ -1491,7 +1420,7 @@ pluginTests = (`xfail8101` "known broken (#556)")
14911420 , "foo :: Int -> Int -> Int"
14921421 , "foo a b = a + c"
14931422 ]
1494− _ <- createDoc "Testing.hs" "haskell" content
1423+ _ <- openDoc' "Testing.hs" "haskell" content
14951424 expectDiagnostics
14961425 [ ( "Testing.hs",
14971426 [(DsError, (8, 14), "Variable not in scope: c")]
@@ -1518,7 +1447,7 @@ cppTests =
15181447 run $ expectError content (2, 1)
15191448 )
15201449 , testSessionWait "cpp-ghcide" $ do
1521− _ <- createDoc "A.hs" "haskell" $ T.unlines
1450+ _ <- openDoc' "A.hs" "haskell" $ T.unlines
15221451 ["{-# LANGUAGE CPP #-}"
15231452 ,"main ="
15241453 ,"#ifdef __GHCIDE__"
@@ -1532,7 +1461,7 @@ cppTests =
15321461 where
15331462 expectError :: T.Text -> Cursor -> Session ()
15341463 expectError content cursor = do
1535− _ <- createDoc "Testing.hs" "haskell" content
1464+ _ <- openDoc' "Testing.hs" "haskell" content
15361465 expectDiagnostics
15371466 [ ( "Testing.hs",
15381467 [(DsError, cursor, "error: unterminated")]
@@ -1548,43 +1477,13 @@ preprocessorTests = testSessionWait "preprocessor" $ do
15481477 , "module Testing where"
15491478 , "y = x + z" -- plugin replaces x with y, making this have only one diagnostic
15501479 ]
1551− _ <- createDoc "Testing.hs" "haskell" content
1480+ _ <- openDoc' "Testing.hs" "haskell" content
15521481 expectDiagnostics
15531482 [ ( "Testing.hs",
15541483 [(DsError, (2, 8), "Variable not in scope: z")]
15551484 )
15561485 ]
15571486
1558−
1559−safeTests :: TestTree
1560−safeTests =
1561− testGroup
1562− "SafeHaskell"
1563− [ -- Test for https://github.com/digital-asset/ghcide/issues/424
1564− testSessionWait "load" $ do
1565− let sourceA =
1566− T.unlines
1567− ["{-# LANGUAGE Trustworthy #-}"
1568− ,"module A where"
1569− ,"import System.IO.Unsafe"
1570− ,"import System.IO"
1571− ,"trustWorthyId :: a -> a"
1572− ,"trustWorthyId i = unsafePerformIO $ do"
1573− ," putStrLn \"I'm safe\""
1574− ," return i"]
1575− sourceB =
1576− T.unlines
1577− ["{-# LANGUAGE Safe #-}"
1578− ,"module B where"
1579− ,"import A"
1580− ,"safeId :: a -> a"
1581− ,"safeId = trustWorthyId"
1582− ]
1583−
1584− _ <- createDoc "A.hs" "haskell" sourceA
1585− _ <- createDoc "B.hs" "haskell" sourceB
1586− expectNoMoreDiagnostics 1 ]
1587−
15881487thTests :: TestTree
15891488thTests =
15901489 testGroup
@@ -1610,8 +1509,8 @@ thTests =
16101509 "b :: Integer",
16111510 "b = $(litE $ IntegerL $ a) + n"
16121511 ]
1613− _ <- createDoc "A.hs" "haskell" sourceA
1614− _ <- createDoc "B.hs" "haskell" sourceB
1512+ _ <- openDoc' "A.hs" "haskell" sourceA
1513+ _ <- openDoc' "B.hs" "haskell" sourceB
16151514 expectDiagnostics [ ( "B.hs", [(DsError, (6, 29), "Variable not in scope: n")] ) ]
16161515 , testSessionWait "newtype-closure" $ do
16171516 let sourceA =
@@ -1631,8 +1530,8 @@ thTests =
16311530 ,"import A"
16321531 ,"b :: Int"
16331532 ,"b = $( a )" ]
1634− _ <- createDoc "A.hs" "haskell" sourceA
1635− _ <- createDoc "B.hs" "haskell" sourceB
1533+ _ <- openDoc' "A.hs" "haskell" sourceA
1534+ _ <- openDoc' "B.hs" "haskell" sourceB
16361535 return ()
16371536 ]
16381537
@@ -1641,7 +1540,7 @@ completionTests
16411540 = testGroup "completion"
16421541 [ testSessionWait "variable" $ do
16431542 let source = T.unlines ["module A where", "f = hea"]
1644− docId <- createDoc "A.hs" "haskell" source
1543+ docId <- openDoc' "A.hs" "haskell" source
16451544 compls <- getCompletions docId (Position 1 7)
16461545 liftIO $ map dropDocs compls @?=
16471546 [complItem "head" (Just CiFunction) (Just "[a] -> a")]
@@ -1653,7 +1552,7 @@ completionTests
16531552 ]
16541553 , testSessionWait "constructor" $ do
16551554 let source = T.unlines ["module A where", "f = Tru"]
1656− docId <- createDoc "A.hs" "haskell" source
1555+ docId <- openDoc' "A.hs" "haskell" source
16571556 compls <- getCompletions docId (Position 1 7)
16581557 liftIO $ map dropDocs compls @?=
16591558 [ complItem "True" (Just CiConstructor) (Just "Bool")
@@ -1665,7 +1564,7 @@ completionTests
16651564 ]
16661565 , testSessionWait "type" $ do
16671566 let source = T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: ()", "f = ()"]
1668− docId <- createDoc "A.hs" "haskell" source
1567+ docId <- openDoc' "A.hs" "haskell" source
16691568 expectDiagnostics [ ("A.hs", [(DsWarning, (3,0), "not used")]) ]
16701569 changeDoc docId [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: Bo", "f = True"]]
16711570 compls <- getCompletions docId (Position 2 7)
@@ -1682,7 +1581,7 @@ completionTests
16821581 checkDocText "Bool" boolDocs [ "Defined in 'Prelude'" ]
16831582 , testSessionWait "qualified" $ do
16841583 let source = T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = ()"]
1685− docId <- createDoc "A.hs" "haskell" source
1584+ docId <- openDoc' "A.hs" "haskell" source
16861585 expectDiagnostics [ ("A.hs", [(DsWarning, (2, 0), "not used")]) ]
16871586 changeDoc docId [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = Prelude.hea"]]
16881587 compls <- getCompletions docId (Position 2 15)
@@ -1696,30 +1595,9 @@ completionTests
16961595 ]
16971596 , testSessionWait "keyword" $ do
16981597 let source = T.unlines ["module A where", "f = newty"]
1699− docId <- createDoc "A.hs" "haskell" source
1598+ docId <- openDoc' "A.hs" "haskell" source
17001599 compls <- getCompletions docId (Position 1 9)
17011600 liftIO $ compls @?= [keywordItem "newtype"]
1702− , testSessionWait "type context" $ do
1703− let source = T.unlines
1704− [ "{-# OPTIONS_GHC -Wunused-binds #-}"
1705− , "module A () where"
1706− , "f = f"
1707− ]
1708− docId <- createDoc "A.hs" "haskell" source
1709− expectDiagnostics [("A.hs", [(DsWarning, (2, 0), "not used")])]
1710− changeDoc docId
1711− [ TextDocumentContentChangeEvent Nothing Nothing $ T.unlines
1712− [ "{-# OPTIONS_GHC -Wunused-binds #-}"
1713− , "module A () where"
1714− , "f = f"
1715− , "g :: Intege"
1716− ]
1717− ]
1718− -- At this point the module parses but does not typecheck.
1719− -- This should be sufficient to detect that we are in a
1720− -- type context and only show the completion to the type.
1721− compls <- getCompletions docId (Position 3 11)
1722− liftIO $ map dropDocs compls @?= [complItem "Integer"(Just CiStruct) (Just "*")]
17231601 ]
17241602 where
17251603 dropDocs :: CompletionItem -> CompletionItem
@@ -1727,7 +1605,6 @@ completionTests
17271605 complItem label kind ty = CompletionItem
17281606 { _label = label
17291607 , _kind = kind
1730− , _tags = List []
17311608 , _detail = (":: " <>) <$> ty
17321609 , _documentation = Nothing
17331610 , _deprecated = Nothing
@@ -1745,7 +1622,6 @@ completionTests
17451622 keywordItem label = CompletionItem
17461623 { _label = label
17471624 , _kind = Just CiKeyword
1748− , _tags = List []
17491625 , _detail = Nothing
17501626 , _documentation = Nothing
17511627 , _deprecated = Nothing
@@ -1773,7 +1649,7 @@ outlineTests = testGroup
17731649 "outline"
17741650 [ testSessionWait "type class" $ do
17751651 let source = T.unlines ["module A where", "class A a where a :: a -> Bool"]
1776− docId <- createDoc "A.hs" "haskell" source
1652+ docId <- openDoc' "A.hs" "haskell" source
17771653 symbols <- getDocumentSymbols docId
17781654 liftIO $ symbols @?= Left
17791655 [ moduleSymbol
@@ -1786,7 +1662,7 @@ outlineTests = testGroup
17861662 ]
17871663 , testSessionWait "type class instance " $ do
17881664 let source = T.unlines ["class A a where", "instance A () where"]
1789− docId <- createDoc "A.hs" "haskell" source
1665+ docId <- openDoc' "A.hs" "haskell" source
17901666 symbols <- getDocumentSymbols docId
17911667 liftIO $ symbols @?= Left
17921668 [ classSymbol "A a" (R 0 0 0 15) []
@@ -1794,7 +1670,7 @@ outlineTests = testGroup
17941670 ]
17951671 , testSessionWait "type family" $ do
17961672 let source = T.unlines ["{-# language TypeFamilies #-}", "type family A"]
1797− docId <- createDoc "A.hs" "haskell" source
1673+ docId <- openDoc' "A.hs" "haskell" source
17981674 symbols <- getDocumentSymbols docId
17991675 liftIO $ symbols @?= Left [docSymbolD "A" "type family" SkClass (R 1 0 1 13)]
18001676 , testSessionWait "type family instance " $ do
@@ -1803,7 +1679,7 @@ outlineTests = testGroup
18031679 , "type family A a"
18041680 , "type instance A () = ()"
18051681 ]
1806− docId <- createDoc "A.hs" "haskell" source
1682+ docId <- openDoc' "A.hs" "haskell" source
18071683 symbols <- getDocumentSymbols docId
18081684 liftIO $ symbols @?= Left
18091685 [ docSymbolD "A a" "type family" SkClass (R 1 0 1 15)
@@ -1811,7 +1687,7 @@ outlineTests = testGroup
18111687 ]
18121688 , testSessionWait "data family" $ do
18131689 let source = T.unlines ["{-# language TypeFamilies #-}", "data family A"]
1814− docId <- createDoc "A.hs" "haskell" source
1690+ docId <- openDoc' "A.hs" "haskell" source
18151691 symbols <- getDocumentSymbols docId
18161692 liftIO $ symbols @?= Left [docSymbolD "A" "data family" SkClass (R 1 0 1 11)]
18171693 , testSessionWait "data family instance " $ do
@@ -1820,7 +1696,7 @@ outlineTests = testGroup
18201696 , "data family A a"
18211697 , "data instance A () = A ()"
18221698 ]
1823− docId <- createDoc "A.hs" "haskell" source
1699+ docId <- openDoc' "A.hs" "haskell" source
18241700 symbols <- getDocumentSymbols docId
18251701 liftIO $ symbols @?= Left
18261702 [ docSymbolD "A a" "data family" SkClass (R 1 0 1 11)
@@ -1828,36 +1704,36 @@ outlineTests = testGroup
18281704 ]
18291705 , testSessionWait "constant" $ do
18301706 let source = T.unlines ["a = ()"]
1831− docId <- createDoc "A.hs" "haskell" source
1707+ docId <- openDoc' "A.hs" "haskell" source
18321708 symbols <- getDocumentSymbols docId
18331709 liftIO $ symbols @?= Left
18341710 [docSymbol "a" SkFunction (R 0 0 0 6)]
18351711 , testSessionWait "pattern" $ do
18361712 let source = T.unlines ["Just foo = Just 21"]
1837− docId <- createDoc "A.hs" "haskell" source
1713+ docId <- openDoc' "A.hs" "haskell" source
18381714 symbols <- getDocumentSymbols docId
18391715 liftIO $ symbols @?= Left
18401716 [docSymbol "Just foo" SkFunction (R 0 0 0 18)]
18411717 , testSessionWait "pattern with type signature" $ do
18421718 let source = T.unlines ["{-# language ScopedTypeVariables #-}", "a :: () = ()"]
1843− docId <- createDoc "A.hs" "haskell" source
1719+ docId <- openDoc' "A.hs" "haskell" source
18441720 symbols <- getDocumentSymbols docId
18451721 liftIO $ symbols @?= Left
18461722 [docSymbol "a :: ()" SkFunction (R 1 0 1 12)]
18471723 , testSessionWait "function" $ do
18481724 let source = T.unlines ["a x = ()"]
1849− docId <- createDoc "A.hs" "haskell" source
1725+ docId <- openDoc' "A.hs" "haskell" source
18501726 symbols <- getDocumentSymbols docId
18511727 liftIO $ symbols @?= Left [docSymbol "a" SkFunction (R 0 0 0 8)]
18521728 , testSessionWait "type synonym" $ do
18531729 let source = T.unlines ["type A = Bool"]
1854− docId <- createDoc "A.hs" "haskell" source
1730+ docId <- openDoc' "A.hs" "haskell" source
18551731 symbols <- getDocumentSymbols docId
18561732 liftIO $ symbols @?= Left
18571733 [docSymbol' "A" SkTypeParameter (R 0 0 0 13) (R 0 5 0 6)]
18581734 , testSessionWait "datatype" $ do
18591735 let source = T.unlines ["data A = C"]
1860− docId <- createDoc "A.hs" "haskell" source
1736+ docId <- openDoc' "A.hs" "haskell" source
18611737 symbols <- getDocumentSymbols docId
18621738 liftIO $ symbols @?= Left
18631739 [ docSymbolWithChildren "A"
@@ -1865,21 +1741,9 @@ outlineTests = testGroup
18651741 (R 0 0 0 10)
18661742 [docSymbol "C" SkConstructor (R 0 9 0 10)]
18671743 ]
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− ]
18801744 , testSessionWait "import" $ do
18811745 let source = T.unlines ["import Data.Maybe"]
1882− docId <- createDoc "A.hs" "haskell" source
1746+ docId <- openDoc' "A.hs" "haskell" source
18831747 symbols <- getDocumentSymbols docId
18841748 liftIO $ symbols @?= Left
18851749 [docSymbolWithChildren "imports"
@@ -1890,7 +1754,7 @@ outlineTests = testGroup
18901754 ]
18911755 , testSessionWait "multiple import" $ do
18921756 let source = T.unlines ["", "import Data.Maybe", "", "import Control.Exception", ""]
1893− docId <- createDoc "A.hs" "haskell" source
1757+ docId <- openDoc' "A.hs" "haskell" source
18941758 symbols <- getDocumentSymbols docId
18951759 liftIO $ symbols @?= Left
18961760 [docSymbolWithChildren "imports"
@@ -1905,7 +1769,7 @@ outlineTests = testGroup
19051769 [ "{-# language ForeignFunctionInterface #-}"
19061770 , "foreign import ccall \"a\" a :: Int"
19071771 ]
1908− docId <- createDoc "A.hs" "haskell" source
1772+ docId <- openDoc' "A.hs" "haskell" source
19091773 symbols <- getDocumentSymbols docId
19101774 liftIO $ symbols @?= Left [docSymbolD "a" "import" SkObject (R 1 0 1 33)]
19111775 , testSessionWait "foreign export" $ do
@@ -1913,7 +1777,7 @@ outlineTests = testGroup
19131777 [ "{-# language ForeignFunctionInterface #-}"
19141778 , "foreign export ccall odd :: Int -> Bool"
19151779 ]
1916− docId <- createDoc "A.hs" "haskell" source
1780+ docId <- openDoc' "A.hs" "haskell" source
19171781 symbols <- getDocumentSymbols docId
19181782 liftIO $ symbols @?= Left [docSymbolD "odd" "export" SkObject (R 1 0 1 39)]
19191783 ]
@@ -1926,8 +1790,6 @@ outlineTests = testGroup
19261790 DocumentSymbol name (Just detail) kind Nothing loc loc Nothing
19271791 docSymbolWithChildren name kind loc cc =
19281792 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)
19311793 moduleSymbol name loc cc = DocumentSymbol name
19321794 Nothing
19331795 SkFile
@@ -1949,16 +1811,8 @@ pattern R x y x' y' = Range (Position x y) (Position x' y')
19491811xfail :: TestTree -> String -> TestTree
19501812xfail = flip expectFailBecause
19511813
1952−xfail8101 :: TestTree -> String -> TestTree
1953−#if MIN_GHC_API_VERSION(8,10,0)
1954−xfail8101 = flip expectFailBecause
1955−#else
1956−xfail8101 t _ = t
1957−#endif
1958−
19591814data Expect
19601815 = ExpectRange Range -- Both gotoDef and hover should report this range
1961− | ExpectLocation Location
19621816-- | ExpectDefRange Range -- Only gotoDef should report this range
19631817 | ExpectHoverRange Range -- Only hover should report this range
19641818 | ExpectHoverText [T.Text] -- the hover message must contain these snippets
@@ -1971,9 +1825,6 @@ data Expect
19711825mkR :: Int -> Int -> Int -> Int -> Expect
19721826mkR startLine startColumn endLine endColumn = ExpectRange $ mkRange startLine startColumn endLine endColumn
19731827
1974−mkL :: Uri -> Int -> Int -> Int -> Int -> Expect
1975−mkL uri startLine startColumn endLine endColumn = ExpectLocation $ Location uri $ mkRange startLine startColumn endLine endColumn
1976−
19771828haddockTests :: TestTree
19781829haddockTests
19791830 = testGroup "haddock"
@@ -2033,7 +1884,6 @@ cradleTests :: TestTree
20331884cradleTests = testGroup "cradle"
20341885 [testGroup "dependencies" [sessionDepsArePickedUp]
20351886 ,testGroup "loading" [loadCradleOnlyonce]
2036− ,testGroup "multi" [simpleMultiTest, simpleMultiTest2]
20371887 ]
20381888
20391889loadCradleOnlyonce :: TestTree
@@ -2048,53 +1898,17 @@ loadCradleOnlyonce = testGroup "load cradle only once"
20481898 test dir
20491899 implicit dir = test dir
20501900 test _dir = do
2051− doc <- createDoc "B.hs" "haskell" "module B where\nimport Data.Foo"
1901+ doc <- openDoc' "B.hs" "haskell" "module B where\nimport Data.Foo"
20521902 msgs <- someTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))
20531903 liftIO $ length msgs @?= 1
20541904 changeDoc doc [TextDocumentContentChangeEvent Nothing Nothing "module B where\nimport Data.Maybe"]
20551905 msgs <- manyTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))
20561906 liftIO $ length msgs @?= 0
2057− _ <- createDoc "A.hs" "haskell" "module A where\nimport LoadCradleBar"
1907+ _ <- openDoc' "A.hs" "haskell" "module A where\nimport Bar"
20581908 msgs <- manyTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))
20591909 liftIO $ length msgs @?= 0
20601910
20611911
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−
20981912cradleLoadedMessage :: Session FromServerMessage
20991913cradleLoadedMessage = satisfy $ \case
21001914 NotCustomServer (NotificationMessage _ (CustomServerMethod m) _) -> m == cradleLoadedMethod
@@ -2103,56 +1917,6 @@ cradleLoadedMessage = satisfy $ \case
21031917cradleLoadedMethod :: T.Text
21041918cradleLoadedMethod = "ghcide/cradle/loaded"
21051919
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−
21561920sessionDepsArePickedUp :: TestTree
21571921sessionDepsArePickedUp = testSession'
21581922 "session-deps-are-picked-up"
@@ -2162,7 +1926,7 @@ sessionDepsArePickedUp = testSession'
21621926 (dir </> "hie.yaml")
21631927 "cradle: {direct: {arguments: []}}"
21641928 -- Open without OverloadedStrings and expect an error.
2165− doc <- createDoc "Foo.hs" "haskell" fooContent
1929+ doc <- openDoc' "Foo.hs" "haskell" fooContent
21661930 expectDiagnostics
21671931 [("Foo.hs", [(DsError, (3, 6), "Couldn't match expected type")])]
21681932 -- Update hie.yaml to enable OverloadedStrings.
@@ -2197,9 +1961,6 @@ sessionDepsArePickedUp = testSession'
21971961testSession :: String -> Session () -> TestTree
21981962testSession name = testCase name . run
21991963
2200−testSessionWithExtraFiles :: FilePath -> String -> (FilePath -> Session ()) -> TestTree
2201−testSessionWithExtraFiles prefix name = testCase name . runWithExtraFiles prefix
2202−
22031964testSession' :: String -> (FilePath -> Session ()) -> TestTree
22041965testSession' name = testCase name . run'
22051966
@@ -2234,19 +1995,6 @@ mkRange a b c d = Range (Position a b) (Position c d)
22341995run :: Session a -> IO a
22351996run s = withTempDir $ \dir -> runInDir dir s
22361997
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−
22501998run' :: (FilePath -> Session a) -> IO a
22511999run' s = withTempDir $ \dir -> runInDir dir (s dir)
22522000
@@ -2258,7 +2006,6 @@ runInDir dir s = do
22582006 -- since the package import test creates "Data/List.hs", which otherwise has no physical home
22592007 createDirectoryIfMissing True $ dir ++ "/Data"
22602008
2261−
22622009 let cmd = unwords [ghcideExe, "--lsp", "--test", "--cwd", dir]
22632010 -- HIE calls getXgdDirectory which assumes that HOME is set.
22642011 -- Only sets HOME if it wasn't already set.
@@ -2276,7 +2023,7 @@ runInDir dir s = do
22762023openTestDataDoc :: FilePath -> Session TextDocumentIdentifier
22772024openTestDataDoc path = do
22782025 source <- liftIO $ readFileUtf8 $ "test/data" </> path
2279− createDoc path "haskell" source
2026+ openDoc' path "haskell" source
22802027
22812028findCodeActions :: TextDocumentIdentifier -> Range -> [T.Text] -> Session [CodeAction]
22822029findCodeActions doc range expectedTitles = do
@@ -2304,19 +2051,24 @@ findCodeAction doc range t = head <$> findCodeActions doc range [t]
23042051unitTests :: TestTree
23052052unitTests = do
23062053 testGroup "Unit"
2307− [ testCase "empty file path does NOT work with the empty String literal" $
2308− uriToFilePath' (fromNormalizedUri $ filePathToUri' "") @?= Just "."
2309− , testCase "empty file path works using toNormalizedFilePath'" $
2310− uriToFilePath' (fromNormalizedUri $ filePathToUri' (toNormalizedFilePath' "")) @?= Just ""
2311− , testCase "empty path URI" $ do
2312− Just URI{..} <- pure $ parseURI (T.unpack $ getUri $ fromNormalizedUri emptyPathUri)
2313− uriScheme @?= "file:"
2314− uriPath @?= ""
2315− , testCase "from empty path URI" $ do
2316− let uri = Uri "file://"
2317− uriToFilePath' uri @?= Just ""
2054+ [ testCase "empty file path" $
2055+ uriToFilePath' (fromNormalizedUri $ filePathToUri' "") @?= Just ""
23182056 ]
23192057
2058+-- | Wrapper around 'LSPTest.openDoc'' that sends file creation events
2059+openDoc' :: FilePath -> String -> T.Text -> Session TextDocumentIdentifier
2060+openDoc' fp name contents = do
2061+ res@(TextDocumentIdentifier uri) <- LSPTest.openDoc' fp name contents
2062+ -- Needed as ghcide sets up and relies on WatchedFiles but lsp-test does not track them
2063+ sendNotification WorkspaceDidChangeWatchedFiles (DidChangeWatchedFilesParams $ List [FileEvent uri FcCreated])
2064+ return res
2065+
2066+-- | Version of 'LSPTest.openDoc'' that does not send WatchedFiles events for files outside the workspace
2067+openDoc'' :: FilePath -> String -> T.Text -> Session TextDocumentIdentifier
2068+-- At the moment this is just LSPTest.openDoc' but it may change in the future
2069+-- when/if lsp-test implements WatchedFiles
2070+openDoc'' = LSPTest.openDoc'
2071+
23202072positionMappingTests :: TestTree
23212073positionMappingTests =
23222074 testGroup "position mapping"
@@ -2486,11 +2238,11 @@ nthLine i r
24862238 | i >= Rope.rows r = error $ "Row number out of bounds: " <> show i <> "/" <> show (Rope.rows r)
24872239 | otherwise = Rope.takeWhile (/= '\n') $ fst $ Rope.splitAtLine 1 $ snd $ Rope.splitAtLine (i - 1) r
24882240
2489−getWatchedFilesSubscriptionsUntil :: forall end . (FromJSON end, Typeable end) => Session [Maybe Value]
2490−getWatchedFilesSubscriptionsUntil = do
2491− msgs <- manyTill (Just <$> message @RegisterCapabilityRequest <|> Nothing <$ anyMessage) (message @end)
2241+getWatchedFilesSubscriptionsUntilProgressEnd :: Session [Maybe Value]
2242+getWatchedFilesSubscriptionsUntilProgressEnd = do
2243+ msgs <- manyTill (Just <$> message @RegisterCapabilityRequest <|> Nothing <$ anyMessage) (message @WorkDoneProgressEndNotification)
24922244 return
24932245 [ args
2494− | Just RequestMessage{_params = RegistrationParams (List regs)} <- msgs
2246+ | Just (RequestMessage{_params = RegistrationParams (List regs)}) <- msgs
24952247 , Registration _id WorkspaceDidChangeWatchedFiles args <- regs
24962248 ]