@@ -1,7 +1,6 @@
1-- Copyright (c) 2019 The DAML Authors. All rights reserved.
1-- Copyright (c) 2019 The DAML Authors. All rights reserved.
2-- SPDX-License-Identifier: Apache-2.0
2-- SPDX-License-Identifier: Apache-2.0
4−{-# LANGUAGE AllowAmbiguousTypes #-}
5{-# LANGUAGE DuplicateRecordFields #-}
4{-# LANGUAGE DuplicateRecordFields #-}
6{-# LANGUAGE PatternSynonyms #-}
5{-# LANGUAGE PatternSynonyms #-}
7{-# LANGUAGE CPP #-}
6{-# LANGUAGE CPP #-}
@@ -10,32 +9,31 @@
10module Main (main) where
9module Main (main) where
12import Control.Applicative.Combinators
11import Control.Applicative.Combinators
13−import Control.Exception (bracket, catch)
12+import Control.Exception (catch)
14−import qualified Control.Lens as Lens
15import Control.Monad
13import Control.Monad
16import Control.Monad.IO.Class (liftIO)
14import Control.Monad.IO.Class (liftIO)
17−import Data.Aeson (FromJSON, Value)
15+import Data.Aeson (Value)
16+import Data.Char (toLower)
18import Data.Foldable
17import Data.Foldable
19−import Data.List.Extra
18+import Data.List
20import Data.Rope.UTF16 (Rope)
19import Data.Rope.UTF16 (Rope)
21import qualified Data.Rope.UTF16 as Rope
20import qualified Data.Rope.UTF16 as Rope
22import Development.IDE.Core.PositionMapping (fromCurrent, toCurrent)
21import Development.IDE.Core.PositionMapping (fromCurrent, toCurrent)
23import Development.IDE.GHC.Util
22import Development.IDE.GHC.Util
24import qualified Data.Text as T
23import qualified Data.Text as T
26import Development.IDE.Spans.Common
24import Development.IDE.Spans.Common
27import Development.IDE.Test
25import Development.IDE.Test
28import Development.IDE.Test.Runfiles
26import Development.IDE.Test.Runfiles
29import Development.IDE.Types.Location
27import Development.IDE.Types.Location
30import Development.Shake (getDirectoryFilesIO)
28import Development.Shake (getDirectoryFilesIO)
31−import Language.Haskell.LSP.Test
29+import qualified Language.Haskell.LSP.Test as LSPTest
30+import Language.Haskell.LSP.Test hiding (openDoc')
32import Language.Haskell.LSP.Messages
31import Language.Haskell.LSP.Messages
33import Language.Haskell.LSP.Types
32import Language.Haskell.LSP.Types
34import Language.Haskell.LSP.Types.Capabilities
33import Language.Haskell.LSP.Types.Capabilities
35−import qualified Language.Haskell.LSP.Types.Lens as Lsp (diagnostics, params, message)
36import Language.Haskell.LSP.VFS (applyChange)
34import Language.Haskell.LSP.VFS (applyChange)
37import Network.URI
35import Network.URI
38−import System.Environment.Blank (getEnv, setEnv, unsetEnv)
36+import System.Environment.Blank (setEnv)
39import System.FilePath
37import System.FilePath
40import System.IO.Extra
38import System.IO.Extra
41import System.Directory
39import System.Directory
@@ -49,35 +47,31 @@ import Test.Tasty.QuickCheck
49import Data.Maybe
47import Data.Maybe
51main :: IO ()
49main :: IO ()
53− -- We mess with env vars so run single-threaded.
54− setEnv "TASTY_NUM_THREADS" "1" True
55− defaultMainWithRerun $ testGroup "HIE"
50+main = defaultMainWithRerun $ testGroup "HIE"
56− [ testSession "open close" $ do
51+ [ testSession "open close" $ do
57− doc <- createDoc "Testing.hs" "haskell" ""
52+ doc <- openDoc' "Testing.hs" "haskell" ""
58− void (skipManyTill anyMessage message :: Session WorkDoneProgressCreateRequest)
53+ void (skipManyTill anyMessage message :: Session WorkDoneProgressCreateRequest)
59− void (skipManyTill anyMessage message :: Session WorkDoneProgressBeginNotification)
54+ void (skipManyTill anyMessage message :: Session WorkDoneProgressBeginNotification)
60− closeDoc doc
55+ closeDoc doc
61− void (skipManyTill anyMessage message :: Session WorkDoneProgressEndNotification)
56+ void (skipManyTill anyMessage message :: Session WorkDoneProgressEndNotification)
62− , initializeResponseTests
57+ , initializeResponseTests
63− , completionTests
58+ , completionTests
64− , cppTests
59+ , cppTests
65− , diagnosticTests
60+ , diagnosticTests
66− , codeActionTests
61+ , codeActionTests
67− , codeLensesTests
62+ , codeLensesTests
68− , outlineTests
63+ , outlineTests
69− , findDefinitionAndHoverTests
64+ , findDefinitionAndHoverTests
70− , pluginTests
65+ , pluginTests
71− , preprocessorTests
66+ , preprocessorTests
72− , thTests
67+ , thTests
73− , safeTests
68+ , safeTests
74− , unitTests
69+ , unitTests
75− , haddockTests
70+ , haddockTests
76− , positionMappingTests
71+ , positionMappingTests
77− , watchedFilesTests
72+ , watchedFilesTests
78− , cradleTests
73+ , cradleTests
82initializeResponseTests :: TestTree
76initializeResponseTests :: TestTree
83initializeResponseTests = withResource acquire release tests where
77initializeResponseTests = withResource acquire release tests where
@@ -112,7 +106,7 @@ initializeResponseTests = withResource acquire release tests where
112 , chk "NO doc link" _documentLinkProvider Nothing
106 , chk "NO doc link" _documentLinkProvider Nothing
113 , chk "NO color" _colorProvider (Just $ ColorOptionsStatic False)
107 , chk "NO color" _colorProvider (Just $ ColorOptionsStatic False)
114 , chk "NO folding range" _foldingRangeProvider (Just $ FoldingRangeOptionsStatic False)
108 , chk "NO folding range" _foldingRangeProvider (Just $ FoldingRangeOptionsStatic False)
115− , che " execute command" _executeCommandProvider (Just $ ExecuteCommandOptions $ List ["typesignature.add"])
109+ , chk " execute command" _executeCommandProvider (Just $ ExecuteCommandOptions $ List ["typesignature.add"])
116 , chk " workspace" _workspace (Just $ WorkspaceOptions (Just WorkspaceFolderOptions{_supported = Just True, _changeNotifications = Just ( WorkspaceFolderChangeNotificationsBool True )}))
110 , chk " workspace" _workspace (Just $ WorkspaceOptions (Just WorkspaceFolderOptions{_supported = Just True, _changeNotifications = Just ( WorkspaceFolderChangeNotificationsBool True )}))
117 , chk "NO experimental" _experimental Nothing
111 , chk "NO experimental" _experimental Nothing
@@ -128,17 +122,8 @@ initializeResponseTests = withResource acquire release tests where
128 chk title getActual expected =
122 chk title getActual expected =
129 testCase title $ getInitializeResponse >>= \ir -> expected @=? (getActual . innerCaps) ir
123 testCase title $ getInitializeResponse >>= \ir -> expected @=? (getActual . innerCaps) ir
131− che :: TestName -> (InitializeResponseCapabilitiesInner -> Maybe ExecuteCommandOptions) -> Maybe ExecuteCommandOptions -> TestTree
132− che title getActual _expected = testCase title doTest
135− ir <- getInitializeResponse
136− let Just ExecuteCommandOptions {_commands = List [command]} = getActual $ innerCaps ir
137− True @=? T.isSuffixOf "typesignature.add" command
140 innerCaps :: InitializeResponse -> InitializeResponseCapabilitiesInner
125 innerCaps :: InitializeResponse -> InitializeResponseCapabilitiesInner
141− innerCaps (ResponseMessage _ _ (Right (InitializeResponseCapabilities c))) = c
126+ innerCaps (ResponseMessage _ _ (Just (InitializeResponseCapabilities c)) _) = c
142 innerCaps _ = error "this test only expects inner capabilities"
127 innerCaps _ = error "this test only expects inner capabilities"
144 acquire :: IO InitializeResponse
129 acquire :: IO InitializeResponse
@@ -152,7 +137,7 @@ diagnosticTests :: TestTree
152diagnosticTests = testGroup "diagnostics"
137diagnosticTests = testGroup "diagnostics"
153 [ testSessionWait "fix syntax error" $ do
138 [ testSessionWait "fix syntax error" $ do
154 let content = T.unlines [ "module Testing wher" ]
139 let content = T.unlines [ "module Testing wher" ]
155− doc <- createDoc "Testing.hs" "haskell" content
140+ doc <- openDoc' "Testing.hs" "haskell" content
156 expectDiagnostics [("Testing.hs", [(DsError, (0, 15), "parse error")])]
141 expectDiagnostics [("Testing.hs", [(DsError, (0, 15), "parse error")])]
157 let change = TextDocumentContentChangeEvent
142 let change = TextDocumentContentChangeEvent
158 { _range = Just (Range (Position 0 15) (Position 0 19))
143 { _range = Just (Range (Position 0 15) (Position 0 19))
@@ -163,7 +148,7 @@ diagnosticTests = testGroup "diagnostics"
163 expectDiagnostics [("Testing.hs", [])]
148 expectDiagnostics [("Testing.hs", [])]
164 , testSessionWait "introduce syntax error" $ do
149 , testSessionWait "introduce syntax error" $ do
165 let content = T.unlines [ "module Testing where" ]
150 let content = T.unlines [ "module Testing where" ]
166− doc <- createDoc "Testing.hs" "haskell" content
151+ doc <- openDoc' "Testing.hs" "haskell" content
167 void $ skipManyTill anyMessage (message :: Session WorkDoneProgressCreateRequest)
152 void $ skipManyTill anyMessage (message :: Session WorkDoneProgressCreateRequest)
168 void $ skipManyTill anyMessage (message :: Session WorkDoneProgressBeginNotification)
153 void $ skipManyTill anyMessage (message :: Session WorkDoneProgressBeginNotification)
169 let change = TextDocumentContentChangeEvent
154 let change = TextDocumentContentChangeEvent
@@ -181,7 +166,7 @@ diagnosticTests = testGroup "diagnostics"
181 , "bar :: Int -> Int -> Int"
166 , "bar :: Int -> Int -> Int"
182 , "bar a b = cd + b"
167 , "bar a b = cd + b"
184− _ <- createDoc "Testing.hs" "haskell" content
169+ _ <- openDoc' "Testing.hs" "haskell" content
185 expectDiagnostics
170 expectDiagnostics
186 [ ( "Testing.hs"
171 [ ( "Testing.hs"
187 , [ (DsError, (2, 14), "Variable not in scope: ab")
172 , [ (DsError, (2, 14), "Variable not in scope: ab")
@@ -195,7 +180,7 @@ diagnosticTests = testGroup "diagnostics"
195 , "foo :: Int -> String -> Int"
180 , "foo :: Int -> String -> Int"
196 , "foo a b = a + b"
181 , "foo a b = a + b"
198− _ <- createDoc "Testing.hs" "haskell" content
183+ _ <- openDoc' "Testing.hs" "haskell" content
199 expectDiagnostics
184 expectDiagnostics
200 [ ( "Testing.hs"
185 [ ( "Testing.hs"
201 , [(DsError, (2, 14), "Couldn't match type '[Char]' with 'Int'")]
186 , [(DsError, (2, 14), "Couldn't match type '[Char]' with 'Int'")]
@@ -207,7 +192,7 @@ diagnosticTests = testGroup "diagnostics"
207 , "foo :: Int -> String"
192 , "foo :: Int -> String"
208 , "foo a = _ a"
193 , "foo a = _ a"
210− _ <- createDoc "Testing.hs" "haskell" content
195+ _ <- openDoc' "Testing.hs" "haskell" content
211 expectDiagnostics
196 expectDiagnostics
212 [ ( "Testing.hs"
197 [ ( "Testing.hs"
213 , [(DsError, (2, 8), "Found hole: _ :: Int -> String")]
198 , [(DsError, (2, 8), "Found hole: _ :: Int -> String")]
@@ -229,23 +214,24 @@ diagnosticTests = testGroup "diagnostics"
229 [ ("A.hs", [(DsError, (2,4), aMessage)])
214 [ ("A.hs", [(DsError, (2,4), aMessage)])
230 , ("B.hs", [(DsError, (3,4), bMessage)])]
215 , ("B.hs", [(DsError, (3,4), bMessage)])]
231 deferralTest title binding msg = testSessionWait title $ do
216 deferralTest title binding msg = testSessionWait title $ do
232− _ <- createDoc "A.hs" "haskell" $ sourceA binding
217+ _ <- openDoc' "A.hs" "haskell" $ sourceA binding
233− _ <- createDoc "B.hs" "haskell" sourceB
218+ _ <- openDoc' "B.hs" "haskell" sourceB
234 expectDiagnostics $ expectedDs msg
219 expectDiagnostics $ expectedDs msg
236 [ deferralTest "type error" "True" "Couldn't match expected type"
221 [ deferralTest "type error" "True" "Couldn't match expected type"
237 , deferralTest "typed hole" "_" "Found hole"
222 , deferralTest "typed hole" "_" "Found hole"
238 , deferralTest "out of scope var" "unbound" "Variable not in scope"
223 , deferralTest "out of scope var" "unbound" "Variable not in scope"
224+ , deferralTest "message shows error" "True" "A.hs:3:5: error:"
241 , testSessionWait "remove required module" $ do
227 , testSessionWait "remove required module" $ do
242 let contentA = T.unlines [ "module ModuleA where" ]
228 let contentA = T.unlines [ "module ModuleA where" ]
243− docA <- createDoc "ModuleA.hs" "haskell" contentA
229+ docA <- openDoc' "ModuleA.hs" "haskell" contentA
244 let contentB = T.unlines
230 let contentB = T.unlines
245 [ "module ModuleB where"
231 [ "module ModuleB where"
246 , "import ModuleA"
232 , "import ModuleA"
248− _ <- createDoc "ModuleB.hs" "haskell" contentB
234+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
249 let change = TextDocumentContentChangeEvent
235 let change = TextDocumentContentChangeEvent
250 { _range = Just (Range (Position 0 0) (Position 0 20))
236 { _range = Just (Range (Position 0 0) (Position 0 20))
251 , _rangeLength = Nothing
237 , _rangeLength = Nothing
@@ -258,20 +244,20 @@ diagnosticTests = testGroup "diagnostics"
258 [ "module ModuleB where"
244 [ "module ModuleB where"
259 , "import ModuleA"
245 , "import ModuleA"
261− _ <- createDoc "ModuleB.hs" "haskell" contentB
247+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
262 expectDiagnostics [("ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]
248 expectDiagnostics [("ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]
263 let contentA = T.unlines [ "module ModuleA where" ]
249 let contentA = T.unlines [ "module ModuleA where" ]
264− _ <- createDoc "ModuleA.hs" "haskell" contentA
250+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
265 expectDiagnostics [("ModuleB.hs", [])]
251 expectDiagnostics [("ModuleB.hs", [])]
266 , testSessionWait "add missing module (non workspace)" $ do
252 , testSessionWait "add missing module (non workspace)" $ do
267 let contentB = T.unlines
253 let contentB = T.unlines
268 [ "module ModuleB where"
254 [ "module ModuleB where"
269 , "import ModuleA"
255 , "import ModuleA"
271− _ <- createDoc "/tmp/ModuleB.hs" "haskell" contentB
257+ _ <- openDoc'' "/tmp/ModuleB.hs" "haskell" contentB
272 expectDiagnostics [("/tmp/ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]
258 expectDiagnostics [("/tmp/ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]
273 let contentA = T.unlines [ "module ModuleA where" ]
259 let contentA = T.unlines [ "module ModuleA where" ]
274− _ <- createDoc "/tmp/ModuleA.hs" "haskell" contentA
260+ _ <- openDoc'' "/tmp/ModuleA.hs" "haskell" contentA
275 expectDiagnostics [("/tmp/ModuleB.hs", [])]
261 expectDiagnostics [("/tmp/ModuleB.hs", [])]
276 , testSessionWait "cyclic module dependency" $ do
262 , testSessionWait "cyclic module dependency" $ do
277 let contentA = T.unlines
263 let contentA = T.unlines
@@ -282,8 +268,8 @@ diagnosticTests = testGroup "diagnostics"
282 [ "module ModuleB where"
268 [ "module ModuleB where"
283 , "import ModuleA"
269 , "import ModuleA"
285− _ <- createDoc "ModuleA.hs" "haskell" contentA
271+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
286− _ <- createDoc "ModuleB.hs" "haskell" contentB
272+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
287 expectDiagnostics
273 expectDiagnostics
288 [ ( "ModuleA.hs"
274 [ ( "ModuleA.hs"
289 , [(DsError, (1, 7), "Cyclic module dependency between ModuleA, ModuleB")]
275 , [(DsError, (1, 7), "Cyclic module dependency between ModuleA, ModuleB")]
@@ -304,9 +290,9 @@ diagnosticTests = testGroup "diagnostics"
304 let contentBboot = T.unlines
290 let contentBboot = T.unlines
305 [ "module ModuleB where"
291 [ "module ModuleB where"
307− _ <- createDoc "ModuleA.hs" "haskell" contentA
293+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
308− _ <- createDoc "ModuleB.hs" "haskell" contentB
294+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
309− _ <- createDoc "ModuleB.hs-boot" "haskell" contentBboot
295+ _ <- openDoc' "ModuleB.hs-boot" "haskell" contentBboot
310 expectDiagnostics []
296 expectDiagnostics []
311 , testSessionWait "correct reference used with hs-boot" $ do
297 , testSessionWait "correct reference used with hs-boot" $ do
312 let contentB = T.unlines
298 let contentB = T.unlines
@@ -328,10 +314,10 @@ diagnosticTests = testGroup "diagnostics"
328 -- resolved to the hs-boot file
314 -- resolved to the hs-boot file
329 , "y = x"
315 , "y = x"
331− _ <- createDoc "ModuleB.hs" "haskell" contentB
317+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
332− _ <- createDoc "ModuleA.hs" "haskell" contentA
318+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
333− _ <- createDoc "ModuleA.hs-boot" "haskell" contentAboot
319+ _ <- openDoc' "ModuleA.hs-boot" "haskell" contentAboot
334− _ <- createDoc "ModuleC.hs" "haskell" contentC
320+ _ <- openDoc' "ModuleC.hs" "haskell" contentC
335 expectDiagnostics []
321 expectDiagnostics []
336 , testSessionWait "redundant import" $ do
322 , testSessionWait "redundant import" $ do
337 let contentA = T.unlines ["module ModuleA where"]
323 let contentA = T.unlines ["module ModuleA where"]
@@ -340,8 +326,8 @@ diagnosticTests = testGroup "diagnostics"
340 , "module ModuleB where"
326 , "module ModuleB where"
341 , "import ModuleA"
327 , "import ModuleA"
343− _ <- createDoc "ModuleA.hs" "haskell" contentA
329+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
344− _ <- createDoc "ModuleB.hs" "haskell" contentB
330+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
345 expectDiagnostics
331 expectDiagnostics
346 [ ( "ModuleB.hs"
332 [ ( "ModuleB.hs"
347 , [(DsWarning, (2, 0), "The import of 'ModuleA' is redundant")]
333 , [(DsWarning, (2, 0), "The import of 'ModuleA' is redundant")]
@@ -363,8 +349,8 @@ diagnosticTests = testGroup "diagnostics"
363 , "wrong1 = ThisList.map"
349 , "wrong1 = ThisList.map"
364 , "wrong2 = BaseList.x"
350 , "wrong2 = BaseList.x"
366− _ <- createDoc "Data/List.hs" "haskell" thisDataListContent
352+ _ <- openDoc' "Data/List.hs" "haskell" thisDataListContent
367− _ <- createDoc "Main.hs" "haskell" mainContent
353+ _ <- openDoc' "Main.hs" "haskell" mainContent
368 expectDiagnostics
354 expectDiagnostics
369 [ ( "Main.hs"
355 [ ( "Main.hs"
370 , [(DsError, (6, 9), "Not in scope: \8216ThisList.map\8217")
356 , [(DsError, (6, 9), "Not in scope: \8216ThisList.map\8217")
@@ -379,7 +365,7 @@ diagnosticTests = testGroup "diagnostics"
379 , "foo :: Ord a => a -> Int"
365 , "foo :: Ord a => a -> Int"
380 , "foo a = 1"
366 , "foo a = 1"
382− _ <- createDoc "Foo.hs" "haskell" fooContent
368+ _ <- openDoc' "Foo.hs" "haskell" fooContent
383 expectDiagnostics
369 expectDiagnostics
384 [ ( "Foo.hs"
370 [ ( "Foo.hs"
385 -- The test is to make sure that warnings contain unqualified names
371 -- The test is to make sure that warnings contain unqualified names
@@ -404,14 +390,14 @@ diagnosticTests = testGroup "diagnostics"
404 Just pathB <- pure $ uriToFilePath uriB
390 Just pathB <- pure $ uriToFilePath uriB
405 uriB <- pure $
391 uriB <- pure $
406 let (drive, suffix) = splitDrive pathB
392 let (drive, suffix) = splitDrive pathB
407− in filePathToUri (joinDrive (lower drive) suffix)
393+ in filePathToUri (joinDrive (map toLower drive ) suffix)
408 liftIO $ createDirectoryIfMissing True (takeDirectory pathB)
394 liftIO $ createDirectoryIfMissing True (takeDirectory pathB)
409 liftIO $ writeFileUTF8 pathB $ T.unpack bContent
395 liftIO $ writeFileUTF8 pathB $ T.unpack bContent
410 uriA <- getDocUri "A/A.hs"
396 uriA <- getDocUri "A/A.hs"
411 Just pathA <- pure $ uriToFilePath uriA
397 Just pathA <- pure $ uriToFilePath uriA
412 uriA <- pure $
398 uriA <- pure $
413 let (drive, suffix) = splitDrive pathA
399 let (drive, suffix) = splitDrive pathA
414− in filePathToUri (joinDrive (lower drive) suffix)
400+ in filePathToUri (joinDrive (map toLower drive ) suffix)
415 let itemA = TextDocumentItem uriA "haskell" 0 aContent
401 let itemA = TextDocumentItem uriA "haskell" 0 aContent
416 let a = TextDocumentIdentifier uriA
402 let a = TextDocumentIdentifier uriA
417 sendNotification TextDocumentDidOpen (DidOpenTextDocumentParams itemA)
403 sendNotification TextDocumentDidOpen (DidOpenTextDocumentParams itemA)
@@ -424,38 +410,6 @@ diagnosticTests = testGroup "diagnostics"
424 liftIO $ unless ("redundant" `T.isInfixOf` msg) $
410 liftIO $ unless ("redundant" `T.isInfixOf` msg) $
425 assertFailure ("Expected redundant import but got " <> T.unpack msg)
411 assertFailure ("Expected redundant import but got " <> T.unpack msg)
426 closeDoc a
412 closeDoc a
427− , testSessionWait "haddock parse error" $ do
428− let fooContent = T.unlines
429− [ "module Foo where"
433− _ <- createDoc "Foo.hs" "haskell" fooContent
436− , [(DsError, (2, 8), "Parse error on input")
440− , testSessionWait "strip file path" $ do
444− [ "module " <> name <> " where"
445− , "value :: Maybe ()"
448− _ <- createDoc (T.unpack name <> ".hs") "haskell" content
449− notification <- skipManyTill anyMessage diagnostic
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
461codeActionTests :: TestTree
415codeActionTests :: TestTree
@@ -481,26 +435,26 @@ codeLensesTests = testGroup "code lenses"
481watchedFilesTests :: TestTree
435watchedFilesTests :: TestTree
482watchedFilesTests = testGroup "watched files"
436watchedFilesTests = testGroup "watched files"
483 [ testSession' "workspace files" $ \sessionDir -> do
437 [ testSession' "workspace files" $ \sessionDir -> do
484− liftIO $ writeFile (sessionDir </> "hie.yaml") "cradle: {direct: {arguments: [\"-isrc\"]}}"
438+ liftIO $ writeFile (sessionDir </> "hie.yaml") $ "cradle: {direct: {arguments: [\"-isrc\"]}}"
485− _doc <- createDoc "A.hs" "haskell" "{-#LANGUAGE NoImplicitPrelude #-}\nmodule A where\nimport WatchedFilesMissingModule"
439+ _ <- openDoc' "A.hs" "haskell" "{-#LANGUAGE NoImplicitPrelude #-}\nmodule A where\nimport B"
486− watchedFileRegs <- getWatchedFilesSubscriptionsUntil @PublishDiagnosticsNotification
440+ watchedFileRegs <- getWatchedFilesSubscriptionsUntilProgressEnd
488− -- Expect 4 subscriptions (A does not get any because it's VFS):
442+ -- Expect 6 subscriptions (A does not get any because it's VFS):
489− -- - /path-to-workspace/WatchedFilesMissingModule.hs
443+ -- - /path-to-workspace/B.hs
490− -- - /path-to-workspace/WatchedFilesMissingModule.lhs
444+ -- - /path-to-workspace/B.lhs
491− -- - /path-to-workspace/src/WatchedFilesMissingModule.hs
445+ -- - B.hs
492− -- - /path-to-workspace/src/WatchedFilesMissingModule.lhs
446+ -- - B.lhs
493− liftIO $ length watchedFileRegs @?= 4
449+ liftIO $ length watchedFileRegs @?= 6
495 , testSession' "non workspace file" $ \sessionDir -> do
451 , testSession' "non workspace file" $ \sessionDir -> do
496− liftIO $ writeFile (sessionDir </> "hie.yaml") "cradle: {direct: {arguments: [\"-i/tmp\"]}}"
452+ liftIO $ writeFile (sessionDir </> "hie.yaml") $ "cradle: {direct: {arguments: [\"-i/tmp\"]}}"
497− _doc <- createDoc "A.hs" "haskell" "{-# LANGUAGE NoImplicitPrelude#-}\nmodule A where\nimport WatchedFilesMissingModule"
453+ _ <- openDoc' "A.hs" "haskell" "{-# LANGUAGE NoImplicitPrelude#-}\nmodule A where\nimport B"
498− watchedFileRegs <- getWatchedFilesSubscriptionsUntil @PublishDiagnosticsNotification
454+ watchedFileRegs <- getWatchedFilesSubscriptionsUntilProgressEnd
500− -- Expect 2 subscriptions (/tmp does not get any as it is out of the workspace):
456+ -- Expect 4 subscriptions:
501− -- - /path-to-workspace/WatchedFilesMissingModule.hs
502− -- - /path-to-workspace/WatchedFilesMissingModule.lhs
503− liftIO $ length watchedFileRegs @?= 2
457+ liftIO $ length watchedFileRegs @?= 4
505 -- TODO add a test for didChangeWorkspaceFolder
459 -- TODO add a test for didChangeWorkspaceFolder
@@ -513,7 +467,7 @@ renameActionTests = testGroup "rename actions"
513 , "foo :: Int -> Int"
467 , "foo :: Int -> Int"
514 , "foo argName = argNme"
468 , "foo argName = argNme"
516− doc <- createDoc "Testing.hs" "haskell" content
470+ doc <- openDoc' "Testing.hs" "haskell" content
517 _ <- waitForDiagnostics
471 _ <- waitForDiagnostics
518 action <- findCodeAction doc (Range (Position 2 14) (Position 2 20)) "Replace with ‘argName’"
472 action <- findCodeAction doc (Range (Position 2 14) (Position 2 20)) "Replace with ‘argName’"
519 executeCodeAction action
473 executeCodeAction action
@@ -531,7 +485,7 @@ renameActionTests = testGroup "rename actions"
531 , "foo :: Maybe a -> [a]"
485 , "foo :: Maybe a -> [a]"
532 , "foo = maybToList"
486 , "foo = maybToList"
534− doc <- createDoc "Testing.hs" "haskell" content
488+ doc <- openDoc' "Testing.hs" "haskell" content
535 _ <- waitForDiagnostics
489 _ <- waitForDiagnostics
536 action <- findCodeAction doc (Range (Position 3 6) (Position 3 16)) "Replace with ‘maybeToList’"
490 action <- findCodeAction doc (Range (Position 3 6) (Position 3 16)) "Replace with ‘maybeToList’"
537 executeCodeAction action
491 executeCodeAction action
@@ -549,7 +503,7 @@ renameActionTests = testGroup "rename actions"
549 , "foo :: Char -> Char -> Char -> Char"
503 , "foo :: Char -> Char -> Char -> Char"
550 , "foo argument1 argument2 argument3 = argumentX"
504 , "foo argument1 argument2 argument3 = argumentX"
552− doc <- createDoc "Testing.hs" "haskell" content
506+ doc <- openDoc' "Testing.hs" "haskell" content
553 _ <- waitForDiagnostics
507 _ <- waitForDiagnostics
554 _ <- findCodeActions doc (Range (Position 2 36) (Position 2 45))
508 _ <- findCodeActions doc (Range (Position 2 36) (Position 2 45))
555 ["Replace with ‘argument1’", "Replace with ‘argument2’", "Replace with ‘argument3’"]
509 ["Replace with ‘argument1’", "Replace with ‘argument2’", "Replace with ‘argument3’"]
@@ -561,7 +515,7 @@ renameActionTests = testGroup "rename actions"
561 , "monus x y = max 0 (x - y)"
515 , "monus x y = max 0 (x - y)"
562 , "foo x y = x `monnus` y"
516 , "foo x y = x `monnus` y"
564− doc <- createDoc "Testing.hs" "haskell" content
518+ doc <- openDoc' "Testing.hs" "haskell" content
565 _ <- waitForDiagnostics
519 _ <- waitForDiagnostics
566 actionsOrCommands <- getCodeActions doc (Range (Position 3 12) (Position 3 20))
520 actionsOrCommands <- getCodeActions doc (Range (Position 3 12) (Position 3 20))
567 [fixTypo] <- pure [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, "monus" `T.isInfixOf` actionTitle ]
521 [fixTypo] <- pure [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, "monus" `T.isInfixOf` actionTitle ]
@@ -584,7 +538,7 @@ typeWildCardActionTests = testGroup "type wildcard actions"
584 , "func :: _"
538 , "func :: _"
585 , "func x = x"
539 , "func x = x"
587− doc <- createDoc "Testing.hs" "haskell" content
541+ doc <- openDoc' "Testing.hs" "haskell" content
588 _ <- waitForDiagnostics
542 _ <- waitForDiagnostics
589 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
543 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
590 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
544 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
@@ -604,7 +558,7 @@ typeWildCardActionTests = testGroup "type wildcard actions"
604 , "func :: _"
558 , "func :: _"
605 , "func x y = x + y"
559 , "func x y = x + y"
607− doc <- createDoc "Testing.hs" "haskell" content
561+ doc <- openDoc' "Testing.hs" "haskell" content
608 _ <- waitForDiagnostics
562 _ <- waitForDiagnostics
609 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
563 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
610 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
564 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
@@ -627,7 +581,7 @@ typeWildCardActionTests = testGroup "type wildcard actions"
627 , " y = x * 2"
581 , " y = x * 2"
628 , " in y"
582 , " in y"
630− doc <- createDoc "Testing.hs" "haskell" content
584+ doc <- openDoc' "Testing.hs" "haskell" content
631 _ <- waitForDiagnostics
585 _ <- waitForDiagnostics
632 actionsOrCommands <- getCodeActions doc (Range (Position 4 1) (Position 4 10))
586 actionsOrCommands <- getCodeActions doc (Range (Position 4 1) (Position 4 10))
633 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
587 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
@@ -652,7 +606,7 @@ removeImportTests = testGroup "remove import actions"
652 let contentA = T.unlines
606 let contentA = T.unlines
653 [ "module ModuleA where"
607 [ "module ModuleA where"
655− _docA <- createDoc "ModuleA.hs" "haskell" contentA
609+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
656 let contentB = T.unlines
610 let contentB = T.unlines
657 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
611 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
658 , "module ModuleB where"
612 , "module ModuleB where"
@@ -660,7 +614,7 @@ removeImportTests = testGroup "remove import actions"
660 , "stuffB :: Integer"
614 , "stuffB :: Integer"
661 , "stuffB = 123"
615 , "stuffB = 123"
663− docB <- createDoc "ModuleB.hs" "haskell" contentB
617+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
664 _ <- waitForDiagnostics
618 _ <- waitForDiagnostics
665 [CACodeAction action@CodeAction { _title = actionTitle }]
619 [CACodeAction action@CodeAction { _title = actionTitle }]
666 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
620 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -678,7 +632,7 @@ removeImportTests = testGroup "remove import actions"
678 let contentA = T.unlines
632 let contentA = T.unlines
679 [ "module ModuleA where"
633 [ "module ModuleA where"
681− _docA <- createDoc "ModuleA.hs" "haskell" contentA
635+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
682 let contentB = T.unlines
636 let contentB = T.unlines
683 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
637 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
684 , "module ModuleB where"
638 , "module ModuleB where"
@@ -686,7 +640,7 @@ removeImportTests = testGroup "remove import actions"
686 , "stuffB :: Integer"
640 , "stuffB :: Integer"
687 , "stuffB = 123"
641 , "stuffB = 123"
689− docB <- createDoc "ModuleB.hs" "haskell" contentB
643+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
690 _ <- waitForDiagnostics
644 _ <- waitForDiagnostics
691 [CACodeAction action@CodeAction { _title = actionTitle }]
645 [CACodeAction action@CodeAction { _title = actionTitle }]
692 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
646 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -708,14 +662,14 @@ removeImportTests = testGroup "remove import actions"
708 , "stuffB = 123"
662 , "stuffB = 123"
709 , "stuffC = ()"
663 , "stuffC = ()"
711− _docA <- createDoc "ModuleA.hs" "haskell" contentA
665+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
712 let contentB = T.unlines
666 let contentB = T.unlines
713 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
667 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
714 , "module ModuleB where"
668 , "module ModuleB where"
715 , "import ModuleA (stuffA, stuffB, stuffC, stuffA)"
669 , "import ModuleA (stuffA, stuffB, stuffC, stuffA)"
716 , "main = print stuffB"
670 , "main = print stuffB"
718− docB <- createDoc "ModuleB.hs" "haskell" contentB
672+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
719 _ <- waitForDiagnostics
673 _ <- waitForDiagnostics
720 [CACodeAction action@CodeAction { _title = actionTitle }]
674 [CACodeAction action@CodeAction { _title = actionTitle }]
721 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
675 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -737,18 +691,22 @@ removeImportTests = testGroup "remove import actions"
737 , "stuffB :: Integer"
691 , "stuffB :: Integer"
738 , "stuffB = 123"
692 , "stuffB = 123"
740− _docA <- createDoc "ModuleA.hs" "haskell" contentA
694+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
741 let contentB = T.unlines
695 let contentB = T.unlines
742 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
696 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
743 , "module ModuleB where"
697 , "module ModuleB where"
744 , "import qualified ModuleA as A ((<?>), stuffB, (!!))"
698 , "import qualified ModuleA as A ((<?>), stuffB, (!!))"
745 , "main = print A.stuffB"
699 , "main = print A.stuffB"
747− docB <- createDoc "ModuleB.hs" "haskell" contentB
701+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
748 _ <- waitForDiagnostics
702 _ <- waitForDiagnostics
749 [CACodeAction action@CodeAction { _title = actionTitle }]
703 [CACodeAction action@CodeAction { _title = actionTitle }]
750 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
704 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
705+#if MIN_GHC_API_VERSION(8,6,0)
751 liftIO $ "Remove !!, <?> from import" @=? actionTitle
706 liftIO $ "Remove !!, <?> from import" @=? actionTitle
708+ liftIO $ "Remove A.!!, A.<?> from import" @=? actionTitle
752 executeCodeAction action
710 executeCodeAction action
753 contentAfterAction <- documentContents docB
711 contentAfterAction <- documentContents docB
754 let expectedContentAfterAction = T.unlines
712 let expectedContentAfterAction = T.unlines
@@ -765,14 +723,14 @@ removeImportTests = testGroup "remove import actions"
765 , "stuffB :: Integer"
723 , "stuffB :: Integer"
766 , "stuffB = 123"
724 , "stuffB = 123"
768− _docA <- createDoc "ModuleA.hs" "haskell" contentA
726+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
769 let contentB = T.unlines
727 let contentB = T.unlines
770 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
728 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
771 , "module ModuleB where"
729 , "module ModuleB where"
772 , "import ModuleA (A(..), stuffB)"
730 , "import ModuleA (A(..), stuffB)"
773 , "main = print stuffB"
731 , "main = print stuffB"
775− docB <- createDoc "ModuleB.hs" "haskell" contentB
733+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
776 _ <- waitForDiagnostics
734 _ <- waitForDiagnostics
777 [CACodeAction action@CodeAction { _title = actionTitle }]
735 [CACodeAction action@CodeAction { _title = actionTitle }]
778 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
736 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -792,14 +750,14 @@ removeImportTests = testGroup "remove import actions"
792 , "data D = A | B"
750 , "data D = A | B"
793 , "data E = F"
751 , "data E = F"
795− _docA <- createDoc "ModuleA.hs" "haskell" contentA
753+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
796 let contentB = T.unlines
754 let contentB = T.unlines
797 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
755 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
798 , "module ModuleB where"
756 , "module ModuleB where"
799 , "import ModuleA (D(A,B), E(F))"
757 , "import ModuleA (D(A,B), E(F))"
800 , "main = B"
758 , "main = B"
802− docB <- createDoc "ModuleB.hs" "haskell" contentB
760+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
803 _ <- waitForDiagnostics
761 _ <- waitForDiagnostics
804 [CACodeAction action@CodeAction { _title = actionTitle }]
762 [CACodeAction action@CodeAction { _title = actionTitle }]
805 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
763 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -940,8 +898,8 @@ extendImportTests = testGroup "extend import actions"
942 template contentA contentB range expectedAction expectedContentB = do
900 template contentA contentB range expectedAction expectedContentB = do
943− _docA <- createDoc "ModuleA.hs" "haskell" contentA
901+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
944− docB <- createDoc "ModuleB.hs" "haskell" contentB
902+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
945 _ <- waitForDiagnostics
903 _ <- waitForDiagnostics
946 CACodeAction action@CodeAction { _title = actionTitle } : _
904 CACodeAction action@CodeAction { _title = actionTitle } : _
947 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
905 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -981,8 +939,6 @@ suggestImportTests = testGroup "suggest import actions"
981 , test True [] "f :: Typeable a => a" ["f = undefined"] "import Data.Typeable (Typeable)"
939 , test True [] "f :: Typeable a => a" ["f = undefined"] "import Data.Typeable (Typeable)"
982 , test True [] "f = pack" [] "import Data.Text (pack)"
940 , test True [] "f = pack" [] "import Data.Text (pack)"
983 , test True [] "f :: Text" ["f = undefined"] "import Data.Text (Text)"
941 , 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 ((&))"
@@ -991,20 +947,19 @@ suggestImportTests = testGroup "suggest import actions"
991 after = T.unlines $ "module A where" : ["import " <> x | x <- imps] ++ [newImp] ++ def : other
947 after = T.unlines $ "module A where" : ["import " <> x | x <- imps] ++ [newImp] ++ def : other
992 cradle = "cradle: {direct: {arguments: [-hide-all-packages, -package, base, -package, text, -package-env, -]}}"
948 cradle = "cradle: {direct: {arguments: [-hide-all-packages, -package, base, -package, text, -package-env, -]}}"
993 liftIO $ writeFileUTF8 (dir </> "hie.yaml") cradle
949 liftIO $ writeFileUTF8 (dir </> "hie.yaml") cradle
994− doc <- createDoc "Test.hs" "haskell" before
950+ doc <- openDoc' "Test.hs" "haskell" before
995 _diags <- waitForDiagnostics
951 _diags <- waitForDiagnostics
996 let defLine = length imps + 1
952 let defLine = length imps + 1
997 range = Range (Position defLine 0) (Position defLine maxBound)
953 range = Range (Position defLine 0) (Position defLine maxBound)
998 actions <- getCodeActions doc range
954 actions <- getCodeActions doc range
999− if wanted
955+ case wanted of
1000− then do
956+ False ->
1001− action <- liftIO $ pickActionWithTitle newImp actions
1002− executeCodeAction action
1003− contentAfterAction <- documentContents doc
1004− liftIO $ after @=? contentAfterAction
1006− liftIO $ [_title | CACodeAction CodeAction{_title} <- actions, _title == newImp ] @?= []
957+ liftIO $ [_title | CACodeAction CodeAction{_title} <- actions, _title == newImp ] @?= []
959+ action <- liftIO $ pickActionWithTitle newImp actions
960+ executeCodeAction action
961+ contentAfterAction <- documentContents doc
962+ liftIO $ after @=? contentAfterAction
1009addExtensionTests :: TestTree
964addExtensionTests :: TestTree
1010addExtensionTests = testGroup "add language extension actions"
965addExtensionTests = testGroup "add language extension actions"
@@ -1051,7 +1006,7 @@ addExtensionTests = testGroup "add language extension actions"
1053 template initialContent range expectedAction expectedContents = do
1008 template initialContent range expectedAction expectedContents = do
1054− doc <- createDoc "Module.hs" "haskell" initialContent
1009+ doc <- openDoc' "Module.hs" "haskell" initialContent
1055 _ <- waitForDiagnostics
1010 _ <- waitForDiagnostics
1056 CACodeAction action@CodeAction { _title = actionTitle } : _
1011 CACodeAction action@CodeAction { _title = actionTitle } : _
1057 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
1012 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1074,7 +1029,7 @@ insertNewDefinitionTests = testGroup "insert new definition actions"
1075 ,"someOtherCode = ()"
1030 ,"someOtherCode = ()"
1077− docB <- createDoc "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
1032+ docB <- openDoc' "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
1078 _ <- waitForDiagnostics
1033 _ <- waitForDiagnostics
1079 CACodeAction action@CodeAction { _title = actionTitle } : _
1034 CACodeAction action@CodeAction { _title = actionTitle } : _
1080 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
1035 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1098,7 +1053,7 @@ insertNewDefinitionTests = testGroup "insert new definition actions"
1099 ,"someOtherCode = ()"
1054 ,"someOtherCode = ()"
1101− docB <- createDoc "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
1056+ docB <- openDoc' "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
1102 _ <- waitForDiagnostics
1057 _ <- waitForDiagnostics
1103 CACodeAction action@CodeAction { _title = actionTitle } : _
1058 CACodeAction action@CodeAction { _title = actionTitle } : _
1104 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
1059 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1137,8 +1092,8 @@ fixConstructorImportTests = testGroup "fix import actions"
1139 template contentA contentB range expectedAction expectedContentB = do
1094 template contentA contentB range expectedAction expectedContentB = do
1140− _docA <- createDoc "ModuleA.hs" "haskell" contentA
1095+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
1141− docB <- createDoc "ModuleB.hs" "haskell" contentB
1096+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
1142 _diags <- waitForDiagnostics
1097 _diags <- waitForDiagnostics
1143 CACodeAction action@CodeAction { _title = actionTitle } : _
1098 CACodeAction action@CodeAction { _title = actionTitle } : _
1144 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
1099 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1157,7 +1112,7 @@ importRenameActionTests = testGroup "import rename actions"
1157 [ "module Testing where"
1112 [ "module Testing where"
1158 , "import Data.Mape"
1113 , "import Data.Mape"
1160− doc <- createDoc "Testing.hs" "haskell" content
1115+ doc <- openDoc' "Testing.hs" "haskell" content
1161 _ <- waitForDiagnostics
1116 _ <- waitForDiagnostics
1162 actionsOrCommands <- getCodeActions doc (Range (Position 2 8) (Position 2 16))
1117 actionsOrCommands <- getCodeActions doc (Range (Position 2 8) (Position 2 16))
1163 let [changeToMap] = [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, ("Data." <> modname) `T.isInfixOf` actionTitle ]
1118 let [changeToMap] = [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, ("Data." <> modname) `T.isInfixOf` actionTitle ]
@@ -1194,7 +1149,7 @@ fillTypedHoleTests = let
1194 newA newB newC = testSession (T.unpack actionTitle) $ do
1149 newA newB newC = testSession (T.unpack actionTitle) $ do
1195 let originalCode = sourceCode oldA oldB oldC
1150 let originalCode = sourceCode oldA oldB oldC
1196 let expectedCode = sourceCode newA newB newC
1151 let expectedCode = sourceCode newA newB newC
1197− doc <- createDoc "Testing.hs" "haskell" originalCode
1152+ doc <- openDoc' "Testing.hs" "haskell" originalCode
1198 _ <- waitForDiagnostics
1153 _ <- waitForDiagnostics
1199 actionsOrCommands <- getCodeActions doc (Range (Position 9 0) (Position 9 maxBound))
1154 actionsOrCommands <- getCodeActions doc (Range (Position 9 0) (Position 9 maxBound))
1200 chosenAction <- liftIO $ pickActionWithTitle actionTitle actionsOrCommands
1155 chosenAction <- liftIO $ pickActionWithTitle actionTitle actionsOrCommands
@@ -1242,7 +1197,7 @@ addSigActionTests = let
1242 def >:: sig = testSession (T.unpack def) $ do
1197 def >:: sig = testSession (T.unpack def) $ do
1243 let originalCode = before def
1198 let originalCode = before def
1244 let expectedCode = after' def sig
1199 let expectedCode = after' def sig
1245− doc <- createDoc "Sigs.hs" "haskell" originalCode
1200+ doc <- openDoc' "Sigs.hs" "haskell" originalCode
1246 _ <- waitForDiagnostics
1201 _ <- waitForDiagnostics
1247 actionsOrCommands <- getCodeActions doc (Range (Position 3 1) (Position 3 maxBound))
1202 actionsOrCommands <- getCodeActions doc (Range (Position 3 1) (Position 3 maxBound))
1248 chosenAction <- liftIO $ pickActionWithTitle ("add signature: " <> sig) actionsOrCommands
1203 chosenAction <- liftIO $ pickActionWithTitle ("add signature: " <> sig) actionsOrCommands
@@ -1274,7 +1229,7 @@ addSigLensesTests = let
1274 sigSession withMissing def sig = testSession (T.unpack def) $ do
1229 sigSession withMissing def sig = testSession (T.unpack def) $ do
1275 let originalCode = before withMissing def
1230 let originalCode = before withMissing def
1276 let expectedCode = after' withMissing def sig
1231 let expectedCode = after' withMissing def sig
1277− doc <- createDoc "Sigs.hs" "haskell" originalCode
1232+ doc <- openDoc' "Sigs.hs" "haskell" originalCode
1278 [CodeLens {_command = Just c}] <- getCodeLenses doc
1233 [CodeLens {_command = Just c}] <- getCodeLenses doc
1279 executeCommand c
1234 executeCommand c
1280 modifiedCode <- getDocumentEdit doc
1235 modifiedCode <- getDocumentEdit doc
@@ -1296,36 +1251,33 @@ addSigLensesTests = let
1299−checkDefs :: [Location] -> Session [Expect] -> Session ()
1300−checkDefs defs mkExpectations = traverse_ check =<< mkExpectations where
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
1313− assertNDefinitionsFound :: Int -> [a] -> Session ()
1314− assertNDefinitionsFound n defs = liftIO $ assertEqual "number of definitions" n (length defs)
1316− assertRangeCorrect Location{_range = foundRange} expectedRange =
1317− liftIO $ expectedRange @=? foundRange
1320findDefinitionAndHoverTests :: TestTree
1254findDefinitionAndHoverTests :: TestTree
1321findDefinitionAndHoverTests = let
1255findDefinitionAndHoverTests = let
1323− tst (get, check) pos targetRange title = testSessionWithExtraFiles "hover" title $ \dir -> do
1257+ tst (get, check) pos targetRange title = testSession title $ do
1324− doc <- openTestDataDoc (dir </> sourceFilePath)
1258+ doc <- openTestDataDoc sourceFilePath
1325 found <- get doc pos
1259 found <- get doc pos
1326 check found targetRange
1260 check found targetRange
1262+ checkDefs :: [Location] -> Session [Expect] -> Session ()
1263+ checkDefs defs mkExpectations = traverse_ check =<< mkExpectations where
1265+ check (ExpectRange expectedRange) = do
1266+ assertNDefinitionsFound 1 defs
1267+ assertRangeCorrect (head defs) expectedRange
1268+ check (ExpectLocation expectedLocation) = do
1269+ assertNDefinitionsFound 1 defs
1270+ liftIO $ head defs @?= expectedLocation
1271+ check ExpectNoDefinitions = do
1272+ assertNDefinitionsFound 0 defs
1273+ check ExpectExternFail = liftIO $ assertFailure "Expecting to fail to find in external file"
1274+ check _ = pure () -- all other expectations not relevant to getDefinition
1276+ assertNDefinitionsFound :: Int -> [a] -> Session ()
1277+ assertNDefinitionsFound n defs = liftIO $ assertEqual "number of definitions" n (length defs)
1279+ assertRangeCorrect Location{_range = foundRange} expectedRange =
1280+ liftIO $ expectedRange @=? foundRange
1330 checkHover :: Maybe Hover -> Session [Expect] -> Session ()
1282 checkHover :: Maybe Hover -> Session [Expect] -> Session ()
1331 checkHover hover expectations = traverse_ check =<< expectations where
1283 checkHover hover expectations = traverse_ check =<< expectations where
@@ -1371,8 +1323,7 @@ findDefinitionAndHoverTests = let
1372 mkFindTests tests = testGroup "get"
1324 mkFindTests tests = testGroup "get"
1373 [ testGroup "definition" $ mapMaybe fst tests
1325 [ testGroup "definition" $ mapMaybe fst tests
1374− , testGroup "hover" $ mapMaybe snd tests
1326+ , testGroup "hover" $ mapMaybe snd tests ]
1375− , checkFileCompiles sourceFilePath ]
1377 test runDef runHover look expect = testM runDef runHover look (return expect)
1328 test runDef runHover look expect = testM runDef runHover look (return expect)
@@ -1467,17 +1418,8 @@ findDefinitionAndHoverTests = let
1467 broken = Just . (`xfail` "known broken")
1418 broken = Just . (`xfail` "known broken")
1468 no = const Nothing -- don't run this test at all
1419 no = const Nothing -- don't run this test at all
1470−checkFileCompiles :: FilePath -> TestTree
1471−checkFileCompiles fp =
1472− testSessionWithExtraFiles "hover" ("Does " ++ fp ++ " compile") $ \dir -> do
1473− void (openTestDataDoc (dir </> fp))
1474− expectNoMoreDiagnostics 0.5
1478pluginTests :: TestTree
1421pluginTests :: TestTree
1479−pluginTests = (`xfail8101` "known broken (#556)")
1480− $ testSessionWait "plugins" $ do
1422+pluginTests = testSessionWait "plugins" $ do
1481 let content =
1423 let content =
1482 T.unlines
1424 T.unlines
1483 [ "{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}"
1425 [ "{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}"
@@ -1491,7 +1433,7 @@ pluginTests = (`xfail8101` "known broken (#556)")
1491 , "foo :: Int -> Int -> Int"
1433 , "foo :: Int -> Int -> Int"
1492 , "foo a b = a + c"
1434 , "foo a b = a + c"
1494− _ <- createDoc "Testing.hs" "haskell" content
1436+ _ <- openDoc' "Testing.hs" "haskell" content
1495 expectDiagnostics
1437 expectDiagnostics
1496 [ ( "Testing.hs",
1438 [ ( "Testing.hs",
1497 [(DsError, (8, 14), "Variable not in scope: c")]
1439 [(DsError, (8, 14), "Variable not in scope: c")]
@@ -1518,7 +1460,7 @@ cppTests =
1518 run $ expectError content (2, 1)
1460 run $ expectError content (2, 1)
1520 , testSessionWait "cpp-ghcide" $ do
1462 , testSessionWait "cpp-ghcide" $ do
1521− _ <- createDoc "A.hs" "haskell" $ T.unlines
1463+ _ <- openDoc' "A.hs" "haskell" $ T.unlines
1522 ["{-# LANGUAGE CPP #-}"
1464 ["{-# LANGUAGE CPP #-}"
1523 ,"main ="
1465 ,"main ="
1524 ,"#ifdef __GHCIDE__"
1466 ,"#ifdef __GHCIDE__"
@@ -1532,7 +1474,7 @@ cppTests =
1533 expectError :: T.Text -> Cursor -> Session ()
1475 expectError :: T.Text -> Cursor -> Session ()
1534 expectError content cursor = do
1476 expectError content cursor = do
1535− _ <- createDoc "Testing.hs" "haskell" content
1477+ _ <- openDoc' "Testing.hs" "haskell" content
1536 expectDiagnostics
1478 expectDiagnostics
1537 [ ( "Testing.hs",
1479 [ ( "Testing.hs",
1538 [(DsError, cursor, "error: unterminated")]
1480 [(DsError, cursor, "error: unterminated")]
@@ -1548,7 +1490,7 @@ preprocessorTests = testSessionWait "preprocessor" $ do
1548 , "module Testing where"
1490 , "module Testing where"
1549 , "y = x + z" -- plugin replaces x with y, making this have only one diagnostic
1491 , "y = x + z" -- plugin replaces x with y, making this have only one diagnostic
1551− _ <- createDoc "Testing.hs" "haskell" content
1493+ _ <- openDoc' "Testing.hs" "haskell" content
1552 expectDiagnostics
1494 expectDiagnostics
1553 [ ( "Testing.hs",
1495 [ ( "Testing.hs",
1554 [(DsError, (2, 8), "Variable not in scope: z")]
1496 [(DsError, (2, 8), "Variable not in scope: z")]
@@ -1581,8 +1523,8 @@ safeTests =
1581 ,"safeId = trustWorthyId"
1523 ,"safeId = trustWorthyId"
1584− _ <- createDoc "A.hs" "haskell" sourceA
1526+ _ <- openDoc' "A.hs" "haskell" sourceA
1585− _ <- createDoc "B.hs" "haskell" sourceB
1527+ _ <- openDoc' "B.hs" "haskell" sourceB
1586 expectNoMoreDiagnostics 1 ]
1528 expectNoMoreDiagnostics 1 ]
1588thTests :: TestTree
1530thTests :: TestTree
@@ -1610,8 +1552,8 @@ thTests =
1610 "b :: Integer",
1552 "b :: Integer",
1611 "b = $(litE $ IntegerL $ a) + n"
1553 "b = $(litE $ IntegerL $ a) + n"
1613− _ <- createDoc "A.hs" "haskell" sourceA
1555+ _ <- openDoc' "A.hs" "haskell" sourceA
1614− _ <- createDoc "B.hs" "haskell" sourceB
1556+ _ <- openDoc' "B.hs" "haskell" sourceB
1615 expectDiagnostics [ ( "B.hs", [(DsError, (6, 29), "Variable not in scope: n")] ) ]
1557 expectDiagnostics [ ( "B.hs", [(DsError, (6, 29), "Variable not in scope: n")] ) ]
1616 , testSessionWait "newtype-closure" $ do
1558 , testSessionWait "newtype-closure" $ do
1617 let sourceA =
1559 let sourceA =
@@ -1631,8 +1573,8 @@ thTests =
1631 ,"import A"
1573 ,"import A"
1632 ,"b :: Int"
1574 ,"b :: Int"
1633 ,"b = $( a )" ]
1575 ,"b = $( a )" ]
1634− _ <- createDoc "A.hs" "haskell" sourceA
1576+ _ <- openDoc' "A.hs" "haskell" sourceA
1635− _ <- createDoc "B.hs" "haskell" sourceB
1577+ _ <- openDoc' "B.hs" "haskell" sourceB
1636 return ()
1578 return ()
@@ -1641,7 +1583,7 @@ completionTests
1641 = testGroup "completion"
1583 = testGroup "completion"
1642 [ testSessionWait "variable" $ do
1584 [ testSessionWait "variable" $ do
1643 let source = T.unlines ["module A where", "f = hea"]
1585 let source = T.unlines ["module A where", "f = hea"]
1644− docId <- createDoc "A.hs" "haskell" source
1586+ docId <- openDoc' "A.hs" "haskell" source
1645 compls <- getCompletions docId (Position 1 7)
1587 compls <- getCompletions docId (Position 1 7)
1646 liftIO $ map dropDocs compls @?=
1588 liftIO $ map dropDocs compls @?=
1647 [complItem "head" (Just CiFunction) (Just "[a] -> a")]
1589 [complItem "head" (Just CiFunction) (Just "[a] -> a")]
@@ -1653,7 +1595,7 @@ completionTests
1654 , testSessionWait "constructor" $ do
1596 , testSessionWait "constructor" $ do
1655 let source = T.unlines ["module A where", "f = Tru"]
1597 let source = T.unlines ["module A where", "f = Tru"]
1656− docId <- createDoc "A.hs" "haskell" source
1598+ docId <- openDoc' "A.hs" "haskell" source
1657 compls <- getCompletions docId (Position 1 7)
1599 compls <- getCompletions docId (Position 1 7)
1658 liftIO $ map dropDocs compls @?=
1600 liftIO $ map dropDocs compls @?=
1659 [ complItem "True" (Just CiConstructor) (Just "Bool")
1601 [ complItem "True" (Just CiConstructor) (Just "Bool")
@@ -1665,7 +1607,7 @@ completionTests
1666 , testSessionWait "type" $ do
1608 , testSessionWait "type" $ do
1667 let source = T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: ()", "f = ()"]
1609 let source = T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: ()", "f = ()"]
1668− docId <- createDoc "A.hs" "haskell" source
1610+ docId <- openDoc' "A.hs" "haskell" source
1669 expectDiagnostics [ ("A.hs", [(DsWarning, (3,0), "not used")]) ]
1611 expectDiagnostics [ ("A.hs", [(DsWarning, (3,0), "not used")]) ]
1670 changeDoc docId [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: Bo", "f = True"]]
1612 changeDoc docId [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: Bo", "f = True"]]
1671 compls <- getCompletions docId (Position 2 7)
1613 compls <- getCompletions docId (Position 2 7)
@@ -1682,7 +1624,7 @@ completionTests
1682 checkDocText "Bool" boolDocs [ "Defined in 'Prelude'" ]
1624 checkDocText "Bool" boolDocs [ "Defined in 'Prelude'" ]
1683 , testSessionWait "qualified" $ do
1625 , testSessionWait "qualified" $ do
1684 let source = T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = ()"]
1626 let source = T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = ()"]
1685− docId <- createDoc "A.hs" "haskell" source
1627+ docId <- openDoc' "A.hs" "haskell" source
1686 expectDiagnostics [ ("A.hs", [(DsWarning, (2, 0), "not used")]) ]
1628 expectDiagnostics [ ("A.hs", [(DsWarning, (2, 0), "not used")]) ]
1687 changeDoc docId [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = Prelude.hea"]]
1629 changeDoc docId [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = Prelude.hea"]]
1688 compls <- getCompletions docId (Position 2 15)
1630 compls <- getCompletions docId (Position 2 15)
@@ -1696,7 +1638,7 @@ completionTests
1697 , testSessionWait "keyword" $ do
1639 , testSessionWait "keyword" $ do
1698 let source = T.unlines ["module A where", "f = newty"]
1640 let source = T.unlines ["module A where", "f = newty"]
1699− docId <- createDoc "A.hs" "haskell" source
1641+ docId <- openDoc' "A.hs" "haskell" source
1700 compls <- getCompletions docId (Position 1 9)
1642 compls <- getCompletions docId (Position 1 9)
1701 liftIO $ compls @?= [keywordItem "newtype"]
1643 liftIO $ compls @?= [keywordItem "newtype"]
1702 , testSessionWait "type context" $ do
1644 , testSessionWait "type context" $ do
@@ -1705,7 +1647,7 @@ completionTests
1705 , "module A () where"
1647 , "module A () where"
1706 , "f = f"
1648 , "f = f"
1708− docId <- createDoc "A.hs" "haskell" source
1650+ docId <- openDoc' "A.hs" "haskell" source
1709 expectDiagnostics [("A.hs", [(DsWarning, (2, 0), "not used")])]
1651 expectDiagnostics [("A.hs", [(DsWarning, (2, 0), "not used")])]
1710 changeDoc docId
1652 changeDoc docId
1711 [ TextDocumentContentChangeEvent Nothing Nothing $ T.unlines
1653 [ TextDocumentContentChangeEvent Nothing Nothing $ T.unlines
@@ -1773,7 +1715,7 @@ outlineTests = testGroup
1773 "outline"
1715 "outline"
1774 [ testSessionWait "type class" $ do
1716 [ testSessionWait "type class" $ do
1775 let source = T.unlines ["module A where", "class A a where a :: a -> Bool"]
1717 let source = T.unlines ["module A where", "class A a where a :: a -> Bool"]
1776− docId <- createDoc "A.hs" "haskell" source
1718+ docId <- openDoc' "A.hs" "haskell" source
1777 symbols <- getDocumentSymbols docId
1719 symbols <- getDocumentSymbols docId
1778 liftIO $ symbols @?= Left
1720 liftIO $ symbols @?= Left
1779 [ moduleSymbol
1721 [ moduleSymbol
@@ -1786,7 +1728,7 @@ outlineTests = testGroup
1787 , testSessionWait "type class instance " $ do
1729 , testSessionWait "type class instance " $ do
1788 let source = T.unlines ["class A a where", "instance A () where"]
1730 let source = T.unlines ["class A a where", "instance A () where"]
1789− docId <- createDoc "A.hs" "haskell" source
1731+ docId <- openDoc' "A.hs" "haskell" source
1790 symbols <- getDocumentSymbols docId
1732 symbols <- getDocumentSymbols docId
1791 liftIO $ symbols @?= Left
1733 liftIO $ symbols @?= Left
1792 [ classSymbol "A a" (R 0 0 0 15) []
1734 [ classSymbol "A a" (R 0 0 0 15) []
@@ -1794,7 +1736,7 @@ outlineTests = testGroup
1795 , testSessionWait "type family" $ do
1737 , testSessionWait "type family" $ do
1796 let source = T.unlines ["{-# language TypeFamilies #-}", "type family A"]
1738 let source = T.unlines ["{-# language TypeFamilies #-}", "type family A"]
1797− docId <- createDoc "A.hs" "haskell" source
1739+ docId <- openDoc' "A.hs" "haskell" source
1798 symbols <- getDocumentSymbols docId
1740 symbols <- getDocumentSymbols docId
1799 liftIO $ symbols @?= Left [docSymbolD "A" "type family" SkClass (R 1 0 1 13)]
1741 liftIO $ symbols @?= Left [docSymbolD "A" "type family" SkClass (R 1 0 1 13)]
1800 , testSessionWait "type family instance " $ do
1742 , testSessionWait "type family instance " $ do
@@ -1803,7 +1745,7 @@ outlineTests = testGroup
1803 , "type family A a"
1745 , "type family A a"
1804 , "type instance A () = ()"
1746 , "type instance A () = ()"
1806− docId <- createDoc "A.hs" "haskell" source
1748+ docId <- openDoc' "A.hs" "haskell" source
1807 symbols <- getDocumentSymbols docId
1749 symbols <- getDocumentSymbols docId
1808 liftIO $ symbols @?= Left
1750 liftIO $ symbols @?= Left
1809 [ docSymbolD "A a" "type family" SkClass (R 1 0 1 15)
1751 [ docSymbolD "A a" "type family" SkClass (R 1 0 1 15)
@@ -1811,7 +1753,7 @@ outlineTests = testGroup
1812 , testSessionWait "data family" $ do
1754 , testSessionWait "data family" $ do
1813 let source = T.unlines ["{-# language TypeFamilies #-}", "data family A"]
1755 let source = T.unlines ["{-# language TypeFamilies #-}", "data family A"]
1814− docId <- createDoc "A.hs" "haskell" source
1756+ docId <- openDoc' "A.hs" "haskell" source
1815 symbols <- getDocumentSymbols docId
1757 symbols <- getDocumentSymbols docId
1816 liftIO $ symbols @?= Left [docSymbolD "A" "data family" SkClass (R 1 0 1 11)]
1758 liftIO $ symbols @?= Left [docSymbolD "A" "data family" SkClass (R 1 0 1 11)]
1817 , testSessionWait "data family instance " $ do
1759 , testSessionWait "data family instance " $ do
@@ -1820,7 +1762,7 @@ outlineTests = testGroup
1820 , "data family A a"
1762 , "data family A a"
1821 , "data instance A () = A ()"
1763 , "data instance A () = A ()"
1823− docId <- createDoc "A.hs" "haskell" source
1765+ docId <- openDoc' "A.hs" "haskell" source
1824 symbols <- getDocumentSymbols docId
1766 symbols <- getDocumentSymbols docId
1825 liftIO $ symbols @?= Left
1767 liftIO $ symbols @?= Left
1826 [ docSymbolD "A a" "data family" SkClass (R 1 0 1 11)
1768 [ docSymbolD "A a" "data family" SkClass (R 1 0 1 11)
@@ -1828,36 +1770,36 @@ outlineTests = testGroup
1829 , testSessionWait "constant" $ do
1771 , testSessionWait "constant" $ do
1830 let source = T.unlines ["a = ()"]
1772 let source = T.unlines ["a = ()"]
1831− docId <- createDoc "A.hs" "haskell" source
1773+ docId <- openDoc' "A.hs" "haskell" source
1832 symbols <- getDocumentSymbols docId
1774 symbols <- getDocumentSymbols docId
1833 liftIO $ symbols @?= Left
1775 liftIO $ symbols @?= Left
1834 [docSymbol "a" SkFunction (R 0 0 0 6)]
1776 [docSymbol "a" SkFunction (R 0 0 0 6)]
1835 , testSessionWait "pattern" $ do
1777 , testSessionWait "pattern" $ do
1836 let source = T.unlines ["Just foo = Just 21"]
1778 let source = T.unlines ["Just foo = Just 21"]
1837− docId <- createDoc "A.hs" "haskell" source
1779+ docId <- openDoc' "A.hs" "haskell" source
1838 symbols <- getDocumentSymbols docId
1780 symbols <- getDocumentSymbols docId
1839 liftIO $ symbols @?= Left
1781 liftIO $ symbols @?= Left
1840 [docSymbol "Just foo" SkFunction (R 0 0 0 18)]
1782 [docSymbol "Just foo" SkFunction (R 0 0 0 18)]
1841 , testSessionWait "pattern with type signature" $ do
1783 , testSessionWait "pattern with type signature" $ do
1842 let source = T.unlines ["{-# language ScopedTypeVariables #-}", "a :: () = ()"]
1784 let source = T.unlines ["{-# language ScopedTypeVariables #-}", "a :: () = ()"]
1843− docId <- createDoc "A.hs" "haskell" source
1785+ docId <- openDoc' "A.hs" "haskell" source
1844 symbols <- getDocumentSymbols docId
1786 symbols <- getDocumentSymbols docId
1845 liftIO $ symbols @?= Left
1787 liftIO $ symbols @?= Left
1846 [docSymbol "a :: ()" SkFunction (R 1 0 1 12)]
1788 [docSymbol "a :: ()" SkFunction (R 1 0 1 12)]
1847 , testSessionWait "function" $ do
1789 , testSessionWait "function" $ do
1848 let source = T.unlines ["a x = ()"]
1790 let source = T.unlines ["a x = ()"]
1849− docId <- createDoc "A.hs" "haskell" source
1791+ docId <- openDoc' "A.hs" "haskell" source
1850 symbols <- getDocumentSymbols docId
1792 symbols <- getDocumentSymbols docId
1851 liftIO $ symbols @?= Left [docSymbol "a" SkFunction (R 0 0 0 8)]
1793 liftIO $ symbols @?= Left [docSymbol "a" SkFunction (R 0 0 0 8)]
1852 , testSessionWait "type synonym" $ do
1794 , testSessionWait "type synonym" $ do
1853 let source = T.unlines ["type A = Bool"]
1795 let source = T.unlines ["type A = Bool"]
1854− docId <- createDoc "A.hs" "haskell" source
1796+ docId <- openDoc' "A.hs" "haskell" source
1855 symbols <- getDocumentSymbols docId
1797 symbols <- getDocumentSymbols docId
1856 liftIO $ symbols @?= Left
1798 liftIO $ symbols @?= Left
1857 [docSymbol' "A" SkTypeParameter (R 0 0 0 13) (R 0 5 0 6)]
1799 [docSymbol' "A" SkTypeParameter (R 0 0 0 13) (R 0 5 0 6)]
1858 , testSessionWait "datatype" $ do
1800 , testSessionWait "datatype" $ do
1859 let source = T.unlines ["data A = C"]
1801 let source = T.unlines ["data A = C"]
1860− docId <- createDoc "A.hs" "haskell" source
1802+ docId <- openDoc' "A.hs" "haskell" source
1861 symbols <- getDocumentSymbols docId
1803 symbols <- getDocumentSymbols docId
1862 liftIO $ symbols @?= Left
1804 liftIO $ symbols @?= Left
1863 [ docSymbolWithChildren "A"
1805 [ docSymbolWithChildren "A"
@@ -1865,21 +1807,9 @@ outlineTests = testGroup
1865 (R 0 0 0 10)
1807 (R 0 0 0 10)
1866 [docSymbol "C" SkConstructor (R 0 9 0 10)]
1808 [docSymbol "C" SkConstructor (R 0 9 0 10)]
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)
1880 , testSessionWait "import" $ do
1810 , testSessionWait "import" $ do
1881 let source = T.unlines ["import Data.Maybe"]
1811 let source = T.unlines ["import Data.Maybe"]
1882− docId <- createDoc "A.hs" "haskell" source
1812+ docId <- openDoc' "A.hs" "haskell" source
1883 symbols <- getDocumentSymbols docId
1813 symbols <- getDocumentSymbols docId
1884 liftIO $ symbols @?= Left
1814 liftIO $ symbols @?= Left
1885 [docSymbolWithChildren "imports"
1815 [docSymbolWithChildren "imports"
@@ -1890,7 +1820,7 @@ outlineTests = testGroup
1891 , testSessionWait "multiple import" $ do
1821 , testSessionWait "multiple import" $ do
1892 let source = T.unlines ["", "import Data.Maybe", "", "import Control.Exception", ""]
1822 let source = T.unlines ["", "import Data.Maybe", "", "import Control.Exception", ""]
1893− docId <- createDoc "A.hs" "haskell" source
1823+ docId <- openDoc' "A.hs" "haskell" source
1894 symbols <- getDocumentSymbols docId
1824 symbols <- getDocumentSymbols docId
1895 liftIO $ symbols @?= Left
1825 liftIO $ symbols @?= Left
1896 [docSymbolWithChildren "imports"
1826 [docSymbolWithChildren "imports"
@@ -1905,7 +1835,7 @@ outlineTests = testGroup
1905 [ "{-# language ForeignFunctionInterface #-}"
1835 [ "{-# language ForeignFunctionInterface #-}"
1906 , "foreign import ccall \"a\" a :: Int"
1836 , "foreign import ccall \"a\" a :: Int"
1908− docId <- createDoc "A.hs" "haskell" source
1838+ docId <- openDoc' "A.hs" "haskell" source
1909 symbols <- getDocumentSymbols docId
1839 symbols <- getDocumentSymbols docId
1910 liftIO $ symbols @?= Left [docSymbolD "a" "import" SkObject (R 1 0 1 33)]
1840 liftIO $ symbols @?= Left [docSymbolD "a" "import" SkObject (R 1 0 1 33)]
1911 , testSessionWait "foreign export" $ do
1841 , testSessionWait "foreign export" $ do
@@ -1913,7 +1843,7 @@ outlineTests = testGroup
1913 [ "{-# language ForeignFunctionInterface #-}"
1843 [ "{-# language ForeignFunctionInterface #-}"
1914 , "foreign export ccall odd :: Int -> Bool"
1844 , "foreign export ccall odd :: Int -> Bool"
1916− docId <- createDoc "A.hs" "haskell" source
1846+ docId <- openDoc' "A.hs" "haskell" source
1917 symbols <- getDocumentSymbols docId
1847 symbols <- getDocumentSymbols docId
1918 liftIO $ symbols @?= Left [docSymbolD "odd" "export" SkObject (R 1 0 1 39)]
1848 liftIO $ symbols @?= Left [docSymbolD "odd" "export" SkObject (R 1 0 1 39)]
@@ -1926,8 +1856,6 @@ outlineTests = testGroup
1926 DocumentSymbol name (Just detail) kind Nothing loc loc Nothing
1856 DocumentSymbol name (Just detail) kind Nothing loc loc Nothing
1927 docSymbolWithChildren name kind loc cc =
1857 docSymbolWithChildren name kind loc cc =
1928 DocumentSymbol name Nothing kind Nothing loc loc (Just $ List cc)
1858 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)
1931 moduleSymbol name loc cc = DocumentSymbol name
1859 moduleSymbol name loc cc = DocumentSymbol name
@@ -1949,13 +1877,6 @@ pattern R x y x' y' = Range (Position x y) (Position x' y')
1949xfail :: TestTree -> String -> TestTree
1877xfail :: TestTree -> String -> TestTree
1950xfail = flip expectFailBecause
1878xfail = flip expectFailBecause
1952−xfail8101 :: TestTree -> String -> TestTree
1953−#if MIN_GHC_API_VERSION(8,10,0)
1954−xfail8101 = flip expectFailBecause
1959data Expect
1880data Expect
1960 = ExpectRange Range -- Both gotoDef and hover should report this range
1881 = ExpectRange Range -- Both gotoDef and hover should report this range
1961 | ExpectLocation Location
1882 | ExpectLocation Location
@@ -2033,7 +1954,6 @@ cradleTests :: TestTree
2033cradleTests = testGroup "cradle"
1954cradleTests = testGroup "cradle"
2034 [testGroup "dependencies" [sessionDepsArePickedUp]
1955 [testGroup "dependencies" [sessionDepsArePickedUp]
2035 ,testGroup "loading" [loadCradleOnlyonce]
1956 ,testGroup "loading" [loadCradleOnlyonce]
2036− ,testGroup "multi" [simpleMultiTest, simpleMultiTest2]
2039loadCradleOnlyonce :: TestTree
1959loadCradleOnlyonce :: TestTree
@@ -2048,53 +1968,17 @@ loadCradleOnlyonce = testGroup "load cradle only once"
2048 test dir
1968 test dir
2049 implicit dir = test dir
1969 implicit dir = test dir
2050 test _dir = do
1970 test _dir = do
2051− doc <- createDoc "B.hs" "haskell" "module B where\nimport Data.Foo"
1971+ doc <- openDoc' "B.hs" "haskell" "module B where\nimport Data.Foo"
2052 msgs <- someTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))
1972 msgs <- someTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))
2053 liftIO $ length msgs @?= 1
1973 liftIO $ length msgs @?= 1
2054 changeDoc doc [TextDocumentContentChangeEvent Nothing Nothing "module B where\nimport Data.Maybe"]
1974 changeDoc doc [TextDocumentContentChangeEvent Nothing Nothing "module B where\nimport Data.Maybe"]
2055 msgs <- manyTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))
1975 msgs <- manyTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))
2056 liftIO $ length msgs @?= 0
1976 liftIO $ length msgs @?= 0
2057− _ <- createDoc "A.hs" "haskell" "module A where\nimport LoadCradleBar"
1977+ _ <- openDoc' "A.hs" "haskell" "module A where\nimport LoadCradleBar"
2058 msgs <- manyTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))
1978 msgs <- manyTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))
2059 liftIO $ length msgs @?= 0
1979 liftIO $ length msgs @?= 0
2062−dependentFileTest :: TestTree
2063−dependentFileTest = testGroup "addDependentFile"
2064− [testGroup "file-changed" [testSession' "test" test]
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"
2077− , " qAddDependentFile \"dep-file.txt\""
2078− , " f <- qRunIO (readFile \"dep-file.txt\")"
2079− , " if f == \"B\" then [| 1 |] else lift f)"
2081− let bazContent = T.unlines ["module Baz where", "import Foo"]
2082− _ <-createDoc "Foo.hs" "haskell" fooContent
2083− doc <- createDoc "Baz.hs" "haskell" bazContent
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
2093− -- Modifying Baz will now trigger Foo to be rebuilt as well
2094− changeDoc doc [change]
2095− expectDiagnostics [("Foo.hs", [])]
2098cradleLoadedMessage :: Session FromServerMessage
1982cradleLoadedMessage :: Session FromServerMessage
2099cradleLoadedMessage = satisfy $ \case
1983cradleLoadedMessage = satisfy $ \case
2100 NotCustomServer (NotificationMessage _ (CustomServerMethod m) _) -> m == cradleLoadedMethod
1984 NotCustomServer (NotificationMessage _ (CustomServerMethod m) _) -> m == cradleLoadedMethod
@@ -2103,56 +1987,6 @@ cradleLoadedMessage = satisfy $ \case
2103cradleLoadedMethod :: T.Text
1987cradleLoadedMethod :: T.Text
2104cradleLoadedMethod = "ghcide/cradle/loaded"
1988cradleLoadedMethod = "ghcide/cradle/loaded"
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
2111− (mapM getEnv vars >>= \prevState -> mapM_ unsetEnv vars >> pure prevState)
2112− (\prevState -> mapM_ (\(var, value) -> restore var value) (zip vars prevState))
2115− [ "GHC_PACKAGE_PATH"
2116− , "GHC_ENVIRONMENT"
2117− , "HASKELL_DIST_DIR"
2118− , "HASKELL_PACKAGE_SANDBOX"
2119− , "HASKELL_PACKAGE_SANDBOXES"
2121− restore var Nothing = unsetEnv var
2122− restore var (Just val) = setEnv var val True
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
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
2156sessionDepsArePickedUp :: TestTree
1990sessionDepsArePickedUp :: TestTree
2157sessionDepsArePickedUp = testSession'
1991sessionDepsArePickedUp = testSession'
2158 "session-deps-are-picked-up"
1992 "session-deps-are-picked-up"
@@ -2162,7 +1996,7 @@ sessionDepsArePickedUp = testSession'
2162 (dir </> "hie.yaml")
1996 (dir </> "hie.yaml")
2163 "cradle: {direct: {arguments: []}}"
1997 "cradle: {direct: {arguments: []}}"
2164 -- Open without OverloadedStrings and expect an error.
1998 -- Open without OverloadedStrings and expect an error.
2165− doc <- createDoc "Foo.hs" "haskell" fooContent
1999+ doc <- openDoc' "Foo.hs" "haskell" fooContent
2166 expectDiagnostics
2000 expectDiagnostics
2167 [("Foo.hs", [(DsError, (3, 6), "Couldn't match expected type")])]
2001 [("Foo.hs", [(DsError, (3, 6), "Couldn't match expected type")])]
2168 -- Update hie.yaml to enable OverloadedStrings.
2002 -- Update hie.yaml to enable OverloadedStrings.
@@ -2197,9 +2031,6 @@ sessionDepsArePickedUp = testSession'
2197testSession :: String -> Session () -> TestTree
2031testSession :: String -> Session () -> TestTree
2198testSession name = testCase name . run
2032testSession name = testCase name . run
2200−testSessionWithExtraFiles :: FilePath -> String -> (FilePath -> Session ()) -> TestTree
2201−testSessionWithExtraFiles prefix name = testCase name . runWithExtraFiles prefix
2203testSession' :: String -> (FilePath -> Session ()) -> TestTree
2034testSession' :: String -> (FilePath -> Session ()) -> TestTree
2204testSession' name = testCase name . run'
2035testSession' name = testCase name . run'
@@ -2234,19 +2065,6 @@ mkRange a b c d = Range (Position a b) (Position c d)
2234run :: Session a -> IO a
2065run :: Session a -> IO a
2235run s = withTempDir $ \dir -> runInDir dir s
2066run s = withTempDir $ \dir -> runInDir dir s
2237−runWithExtraFiles :: FilePath -> (FilePath -> Session a) -> IO a
2238−runWithExtraFiles prefix s = withTempDir $ \dir -> do
2239− copyTestDataFiles dir prefix
2240− runInDir dir (s dir)
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)
2250run' :: (FilePath -> Session a) -> IO a
2068run' :: (FilePath -> Session a) -> IO a
2251run' s = withTempDir $ \dir -> runInDir dir (s dir)
2069run' s = withTempDir $ \dir -> runInDir dir (s dir)
@@ -2258,6 +2076,11 @@ runInDir dir s = do
2258 -- since the package import test creates "Data/List.hs", which otherwise has no physical home
2076 -- since the package import test creates "Data/List.hs", which otherwise has no physical home
2259 createDirectoryIfMissing True $ dir ++ "/Data"
2077 createDirectoryIfMissing True $ dir ++ "/Data"
2079+ -- Copy all the test data files to the temporary workspace
2080+ testDataFiles <- getDirectoryFilesIO "test/data" ["//*"]
2081+ for_ testDataFiles $ \f -> do
2082+ createDirectoryIfMissing True $ dir </> takeDirectory f
2083+ copyFile ("test/data" </> f) (dir </> f)
2262 let cmd = unwords [ghcideExe, "--lsp", "--test", "--cwd", dir]
2085 let cmd = unwords [ghcideExe, "--lsp", "--test", "--cwd", dir]
2263 -- HIE calls getXgdDirectory which assumes that HOME is set.
2086 -- HIE calls getXgdDirectory which assumes that HOME is set.
@@ -2276,7 +2099,7 @@ runInDir dir s = do
2276openTestDataDoc :: FilePath -> Session TextDocumentIdentifier
2099openTestDataDoc :: FilePath -> Session TextDocumentIdentifier
2277openTestDataDoc path = do
2100openTestDataDoc path = do
2278 source <- liftIO $ readFileUtf8 $ "test/data" </> path
2101 source <- liftIO $ readFileUtf8 $ "test/data" </> path
2279− createDoc path "haskell" source
2102+ openDoc' path "haskell" source
2281findCodeActions :: TextDocumentIdentifier -> Range -> [T.Text] -> Session [CodeAction]
2104findCodeActions :: TextDocumentIdentifier -> Range -> [T.Text] -> Session [CodeAction]
2282findCodeActions doc range expectedTitles = do
2105findCodeActions doc range expectedTitles = do
@@ -2317,6 +2140,20 @@ unitTests = do
2317 uriToFilePath' uri @?= Just ""
2140 uriToFilePath' uri @?= Just ""
2143+-- | Wrapper around 'LSPTest.openDoc'' that sends file creation events
2144+openDoc' :: FilePath -> String -> T.Text -> Session TextDocumentIdentifier
2145+openDoc' fp name contents = do
2146+ res@(TextDocumentIdentifier uri) <- LSPTest.openDoc' fp name contents
2147+ -- Needed as ghcide sets up and relies on WatchedFiles but lsp-test does not track them
2148+ sendNotification WorkspaceDidChangeWatchedFiles (DidChangeWatchedFilesParams $ List [FileEvent uri FcCreated])
2151+-- | Version of 'LSPTest.openDoc'' that does not send WatchedFiles events for files outside the workspace
2152+openDoc'' :: FilePath -> String -> T.Text -> Session TextDocumentIdentifier
2153+-- At the moment this is just LSPTest.openDoc' but it may change in the future
2154+-- when/if lsp-test implements WatchedFiles
2155+openDoc'' = LSPTest.openDoc'
2320positionMappingTests :: TestTree
2157positionMappingTests :: TestTree
2321positionMappingTests =
2158positionMappingTests =
2322 testGroup "position mapping"
2159 testGroup "position mapping"
@@ -2486,11 +2323,11 @@ nthLine i r
2486 | i >= Rope.rows r = error $ "Row number out of bounds: " <> show i <> "/" <> show (Rope.rows r)
2323 | i >= Rope.rows r = error $ "Row number out of bounds: " <> show i <> "/" <> show (Rope.rows r)
2487 | otherwise = Rope.takeWhile (/= '\n') $ fst $ Rope.splitAtLine 1 $ snd $ Rope.splitAtLine (i - 1) r
2324 | otherwise = Rope.takeWhile (/= '\n') $ fst $ Rope.splitAtLine 1 $ snd $ Rope.splitAtLine (i - 1) r
2489−getWatchedFilesSubscriptionsUntil :: forall end . (FromJSON end, Typeable end) => Session [Maybe Value]
2326+getWatchedFilesSubscriptionsUntilProgressEnd :: Session [Maybe Value]
2490−getWatchedFilesSubscriptionsUntil = do
2327+getWatchedFilesSubscriptionsUntilProgressEnd = do
2491− msgs <- manyTill (Just <$> message @RegisterCapabilityRequest <|> Nothing <$ anyMessage) (message @end)
2328+ msgs <- manyTill (Just <$> message @RegisterCapabilityRequest <|> Nothing <$ anyMessage) (message @WorkDoneProgressEndNotification)
2494− | Just RequestMessage{_params = RegistrationParams (List regs)} <- msgs
2331+ | Just (RequestMessage{_params = RegistrationParams (List regs)}) <- msgs
2495 , Registration _id WorkspaceDidChangeWatchedFiles args <- regs
2332 , Registration _id WorkspaceDidChangeWatchedFiles args <- regs