@@ -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,27 @@
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.Char (toLower)
18import Data.Foldable
16import Data.Foldable
19−import Data.List.Extra
17+import Data.List
20import Data.Rope.UTF16 (Rope)
18import Data.Rope.UTF16 (Rope)
21import qualified Data.Rope.UTF16 as Rope
19import qualified Data.Rope.UTF16 as Rope
22import Development.IDE.Core.PositionMapping (fromCurrent, toCurrent)
20import Development.IDE.Core.PositionMapping (fromCurrent, toCurrent)
23import Development.IDE.GHC.Util
21import Development.IDE.GHC.Util
24import qualified Data.Text as T
22import qualified Data.Text as T
26import Development.IDE.Spans.Common
23import Development.IDE.Spans.Common
27import Development.IDE.Test
24import Development.IDE.Test
28import Development.IDE.Test.Runfiles
25import Development.IDE.Test.Runfiles
29import Development.IDE.Types.Location
26import Development.IDE.Types.Location
30−import Development.Shake (getDirectoryFilesIO)
27+import qualified Language.Haskell.LSP.Test as LSPTest
31−import Language.Haskell.LSP.Test
28+import Language.Haskell.LSP.Test hiding (openDoc')
32−import Language.Haskell.LSP.Messages
33import Language.Haskell.LSP.Types
29import Language.Haskell.LSP.Types
34import Language.Haskell.LSP.Types.Capabilities
30import Language.Haskell.LSP.Types.Capabilities
35−import qualified Language.Haskell.LSP.Types.Lens as Lsp (diagnostics, params, message)
36import Language.Haskell.LSP.VFS (applyChange)
31import Language.Haskell.LSP.VFS (applyChange)
38−import System.Environment.Blank (getEnv, setEnv, unsetEnv)
32+import System.Environment.Blank (setEnv)
39import System.FilePath
33import System.FilePath
40import System.IO.Extra
34import System.IO.Extra
41import System.Directory
35import System.Directory
@@ -43,41 +37,35 @@ import Test.QuickCheck
43import Test.QuickCheck.Instances ()
37import Test.QuickCheck.Instances ()
44import Test.Tasty
38import Test.Tasty
45import Test.Tasty.ExpectedFailure
39import Test.Tasty.ExpectedFailure
46−import Test.Tasty.Ingredients.Rerun
47import Test.Tasty.HUnit
40import Test.Tasty.HUnit
48import Test.Tasty.QuickCheck
41import Test.Tasty.QuickCheck
49import Data.Maybe
42import Data.Maybe
51main :: IO ()
44main :: IO ()
53− -- We mess with env vars so run single-threaded.
54− setEnv "TASTY_NUM_THREADS" "1" True
55− defaultMainWithRerun $ testGroup "HIE"
45+main = defaultMain $ testGroup "HIE"
56− [ testSession "open close" $ do
46+ [ testSession "open close" $ do
57− doc <- createDoc "Testing.hs" "haskell" ""
47+ doc <- openDoc' "Testing.hs" "haskell" ""
58− void (skipManyTill anyMessage message :: Session WorkDoneProgressCreateRequest)
48+ void (message :: Session WorkDoneProgressCreateRequest)
59− void (skipManyTill anyMessage message :: Session WorkDoneProgressBeginNotification)
49+ void (message :: Session WorkDoneProgressBeginNotification)
60− closeDoc doc
50+ closeDoc doc
61− void (skipManyTill anyMessage message :: Session WorkDoneProgressEndNotification)
51+ void (message :: Session WorkDoneProgressEndNotification)
62− , initializeResponseTests
52+ , initializeResponseTests
63− , completionTests
53+ , completionTests
64− , cppTests
54+ , cppTests
65− , diagnosticTests
55+ , diagnosticTests
66− , codeActionTests
56+ , codeActionTests
67− , codeLensesTests
57+ , codeLensesTests
68− , outlineTests
58+ , outlineTests
69− , findDefinitionAndHoverTests
59+ , findDefinitionAndHoverTests
70− , pluginTests
60+ , pluginTests
71− , preprocessorTests
61+ , preprocessorTests
72− , thTests
62+ , thTests
74− , unitTests
63+ , unitTests
75− , haddockTests
64+ , haddockTests
76− , positionMappingTests
65+ , positionMappingTests
77− , watchedFilesTests
66+ , watchedFilesTests
78− , cradleTests
67+ , sessionDepsArePickedUp
82initializeResponseTests :: TestTree
70initializeResponseTests :: TestTree
83initializeResponseTests = withResource acquire release tests where
71initializeResponseTests = withResource acquire release tests where
@@ -112,7 +100,7 @@ initializeResponseTests = withResource acquire release tests where
112 , chk "NO doc link" _documentLinkProvider Nothing
100 , chk "NO doc link" _documentLinkProvider Nothing
113 , chk "NO color" _colorProvider (Just $ ColorOptionsStatic False)
101 , chk "NO color" _colorProvider (Just $ ColorOptionsStatic False)
114 , chk "NO folding range" _foldingRangeProvider (Just $ FoldingRangeOptionsStatic False)
102 , chk "NO folding range" _foldingRangeProvider (Just $ FoldingRangeOptionsStatic False)
115− , che " execute command" _executeCommandProvider (Just $ ExecuteCommandOptions $ List ["typesignature.add"])
103+ , chk " execute command" _executeCommandProvider (Just $ ExecuteCommandOptions $ List ["typesignature.add"])
116 , chk " workspace" _workspace (Just $ WorkspaceOptions (Just WorkspaceFolderOptions{_supported = Just True, _changeNotifications = Just ( WorkspaceFolderChangeNotificationsBool True )}))
104 , chk " workspace" _workspace (Just $ WorkspaceOptions (Just WorkspaceFolderOptions{_supported = Just True, _changeNotifications = Just ( WorkspaceFolderChangeNotificationsBool True )}))
117 , chk "NO experimental" _experimental Nothing
105 , chk "NO experimental" _experimental Nothing
@@ -128,17 +116,8 @@ initializeResponseTests = withResource acquire release tests where
128 chk title getActual expected =
116 chk title getActual expected =
129 testCase title $ getInitializeResponse >>= \ir -> expected @=? (getActual . innerCaps) ir
117 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
119 innerCaps :: InitializeResponse -> InitializeResponseCapabilitiesInner
141− innerCaps (ResponseMessage _ _ (Right (InitializeResponseCapabilities c))) = c
120+ innerCaps (ResponseMessage _ _ (Just (InitializeResponseCapabilities c)) _) = c
142 innerCaps _ = error "this test only expects inner capabilities"
121 innerCaps _ = error "this test only expects inner capabilities"
144 acquire :: IO InitializeResponse
123 acquire :: IO InitializeResponse
@@ -152,7 +131,7 @@ diagnosticTests :: TestTree
152diagnosticTests = testGroup "diagnostics"
131diagnosticTests = testGroup "diagnostics"
153 [ testSessionWait "fix syntax error" $ do
132 [ testSessionWait "fix syntax error" $ do
154 let content = T.unlines [ "module Testing wher" ]
133 let content = T.unlines [ "module Testing wher" ]
155− doc <- createDoc "Testing.hs" "haskell" content
134+ doc <- openDoc' "Testing.hs" "haskell" content
156 expectDiagnostics [("Testing.hs", [(DsError, (0, 15), "parse error")])]
135 expectDiagnostics [("Testing.hs", [(DsError, (0, 15), "parse error")])]
157 let change = TextDocumentContentChangeEvent
136 let change = TextDocumentContentChangeEvent
158 { _range = Just (Range (Position 0 15) (Position 0 19))
137 { _range = Just (Range (Position 0 15) (Position 0 19))
@@ -163,9 +142,9 @@ diagnosticTests = testGroup "diagnostics"
163 expectDiagnostics [("Testing.hs", [])]
142 expectDiagnostics [("Testing.hs", [])]
164 , testSessionWait "introduce syntax error" $ do
143 , testSessionWait "introduce syntax error" $ do
165 let content = T.unlines [ "module Testing where" ]
144 let content = T.unlines [ "module Testing where" ]
166− doc <- createDoc "Testing.hs" "haskell" content
145+ doc <- openDoc' "Testing.hs" "haskell" content
167− void $ skipManyTill anyMessage (message :: Session WorkDoneProgressCreateRequest)
146+ void (message :: Session WorkDoneProgressCreateRequest)
168− void $ skipManyTill anyMessage (message :: Session WorkDoneProgressBeginNotification)
147+ void (message :: Session WorkDoneProgressBeginNotification)
169 let change = TextDocumentContentChangeEvent
148 let change = TextDocumentContentChangeEvent
170 { _range = Just (Range (Position 0 15) (Position 0 18))
149 { _range = Just (Range (Position 0 15) (Position 0 18))
171 , _rangeLength = Nothing
150 , _rangeLength = Nothing
@@ -181,7 +160,7 @@ diagnosticTests = testGroup "diagnostics"
181 , "bar :: Int -> Int -> Int"
160 , "bar :: Int -> Int -> Int"
182 , "bar a b = cd + b"
161 , "bar a b = cd + b"
184− _ <- createDoc "Testing.hs" "haskell" content
163+ _ <- openDoc' "Testing.hs" "haskell" content
185 expectDiagnostics
164 expectDiagnostics
186 [ ( "Testing.hs"
165 [ ( "Testing.hs"
187 , [ (DsError, (2, 14), "Variable not in scope: ab")
166 , [ (DsError, (2, 14), "Variable not in scope: ab")
@@ -195,7 +174,7 @@ diagnosticTests = testGroup "diagnostics"
195 , "foo :: Int -> String -> Int"
174 , "foo :: Int -> String -> Int"
196 , "foo a b = a + b"
175 , "foo a b = a + b"
198− _ <- createDoc "Testing.hs" "haskell" content
177+ _ <- openDoc' "Testing.hs" "haskell" content
199 expectDiagnostics
178 expectDiagnostics
200 [ ( "Testing.hs"
179 [ ( "Testing.hs"
201 , [(DsError, (2, 14), "Couldn't match type '[Char]' with 'Int'")]
180 , [(DsError, (2, 14), "Couldn't match type '[Char]' with 'Int'")]
@@ -207,7 +186,7 @@ diagnosticTests = testGroup "diagnostics"
207 , "foo :: Int -> String"
186 , "foo :: Int -> String"
208 , "foo a = _ a"
187 , "foo a = _ a"
210− _ <- createDoc "Testing.hs" "haskell" content
189+ _ <- openDoc' "Testing.hs" "haskell" content
211 expectDiagnostics
190 expectDiagnostics
212 [ ( "Testing.hs"
191 [ ( "Testing.hs"
213 , [(DsError, (2, 8), "Found hole: _ :: Int -> String")]
192 , [(DsError, (2, 8), "Found hole: _ :: Int -> String")]
@@ -229,23 +208,24 @@ diagnosticTests = testGroup "diagnostics"
229 [ ("A.hs", [(DsError, (2,4), aMessage)])
208 [ ("A.hs", [(DsError, (2,4), aMessage)])
230 , ("B.hs", [(DsError, (3,4), bMessage)])]
209 , ("B.hs", [(DsError, (3,4), bMessage)])]
231 deferralTest title binding msg = testSessionWait title $ do
210 deferralTest title binding msg = testSessionWait title $ do
232− _ <- createDoc "A.hs" "haskell" $ sourceA binding
211+ _ <- openDoc' "A.hs" "haskell" $ sourceA binding
233− _ <- createDoc "B.hs" "haskell" sourceB
212+ _ <- openDoc' "B.hs" "haskell" sourceB
234 expectDiagnostics $ expectedDs msg
213 expectDiagnostics $ expectedDs msg
236 [ deferralTest "type error" "True" "Couldn't match expected type"
215 [ deferralTest "type error" "True" "Couldn't match expected type"
237 , deferralTest "typed hole" "_" "Found hole"
216 , deferralTest "typed hole" "_" "Found hole"
238 , deferralTest "out of scope var" "unbound" "Variable not in scope"
217 , deferralTest "out of scope var" "unbound" "Variable not in scope"
218+ , deferralTest "message shows error" "True" "A.hs:3:5: error:"
241 , testSessionWait "remove required module" $ do
221 , testSessionWait "remove required module" $ do
242 let contentA = T.unlines [ "module ModuleA where" ]
222 let contentA = T.unlines [ "module ModuleA where" ]
243− docA <- createDoc "ModuleA.hs" "haskell" contentA
223+ docA <- openDoc' "ModuleA.hs" "haskell" contentA
244 let contentB = T.unlines
224 let contentB = T.unlines
245 [ "module ModuleB where"
225 [ "module ModuleB where"
246 , "import ModuleA"
226 , "import ModuleA"
248− _ <- createDoc "ModuleB.hs" "haskell" contentB
228+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
249 let change = TextDocumentContentChangeEvent
229 let change = TextDocumentContentChangeEvent
250 { _range = Just (Range (Position 0 0) (Position 0 20))
230 { _range = Just (Range (Position 0 0) (Position 0 20))
251 , _rangeLength = Nothing
231 , _rangeLength = Nothing
@@ -258,20 +238,20 @@ diagnosticTests = testGroup "diagnostics"
258 [ "module ModuleB where"
238 [ "module ModuleB where"
259 , "import ModuleA"
239 , "import ModuleA"
261− _ <- createDoc "ModuleB.hs" "haskell" contentB
241+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
262 expectDiagnostics [("ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]
242 expectDiagnostics [("ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]
263 let contentA = T.unlines [ "module ModuleA where" ]
243 let contentA = T.unlines [ "module ModuleA where" ]
264− _ <- createDoc "ModuleA.hs" "haskell" contentA
244+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
265 expectDiagnostics [("ModuleB.hs", [])]
245 expectDiagnostics [("ModuleB.hs", [])]
266 , testSessionWait "add missing module (non workspace)" $ do
246 , testSessionWait "add missing module (non workspace)" $ do
267 let contentB = T.unlines
247 let contentB = T.unlines
268 [ "module ModuleB where"
248 [ "module ModuleB where"
269 , "import ModuleA"
249 , "import ModuleA"
271− _ <- createDoc "/tmp/ModuleB.hs" "haskell" contentB
251+ _ <- openDoc'' "/tmp/ModuleB.hs" "haskell" contentB
272 expectDiagnostics [("/tmp/ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]
252 expectDiagnostics [("/tmp/ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]
273 let contentA = T.unlines [ "module ModuleA where" ]
253 let contentA = T.unlines [ "module ModuleA where" ]
274− _ <- createDoc "/tmp/ModuleA.hs" "haskell" contentA
254+ _ <- openDoc'' "/tmp/ModuleA.hs" "haskell" contentA
275 expectDiagnostics [("/tmp/ModuleB.hs", [])]
255 expectDiagnostics [("/tmp/ModuleB.hs", [])]
276 , testSessionWait "cyclic module dependency" $ do
256 , testSessionWait "cyclic module dependency" $ do
277 let contentA = T.unlines
257 let contentA = T.unlines
@@ -282,8 +262,8 @@ diagnosticTests = testGroup "diagnostics"
282 [ "module ModuleB where"
262 [ "module ModuleB where"
283 , "import ModuleA"
263 , "import ModuleA"
285− _ <- createDoc "ModuleA.hs" "haskell" contentA
265+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
286− _ <- createDoc "ModuleB.hs" "haskell" contentB
266+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
287 expectDiagnostics
267 expectDiagnostics
288 [ ( "ModuleA.hs"
268 [ ( "ModuleA.hs"
289 , [(DsError, (1, 7), "Cyclic module dependency between ModuleA, ModuleB")]
269 , [(DsError, (1, 7), "Cyclic module dependency between ModuleA, ModuleB")]
@@ -304,9 +284,9 @@ diagnosticTests = testGroup "diagnostics"
304 let contentBboot = T.unlines
284 let contentBboot = T.unlines
305 [ "module ModuleB where"
285 [ "module ModuleB where"
307− _ <- createDoc "ModuleA.hs" "haskell" contentA
287+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
308− _ <- createDoc "ModuleB.hs" "haskell" contentB
288+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
309− _ <- createDoc "ModuleB.hs-boot" "haskell" contentBboot
289+ _ <- openDoc' "ModuleB.hs-boot" "haskell" contentBboot
310 expectDiagnostics []
290 expectDiagnostics []
311 , testSessionWait "correct reference used with hs-boot" $ do
291 , testSessionWait "correct reference used with hs-boot" $ do
312 let contentB = T.unlines
292 let contentB = T.unlines
@@ -328,10 +308,10 @@ diagnosticTests = testGroup "diagnostics"
328 -- resolved to the hs-boot file
308 -- resolved to the hs-boot file
329 , "y = x"
309 , "y = x"
331− _ <- createDoc "ModuleB.hs" "haskell" contentB
311+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
332− _ <- createDoc "ModuleA.hs" "haskell" contentA
312+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
333− _ <- createDoc "ModuleA.hs-boot" "haskell" contentAboot
313+ _ <- openDoc' "ModuleA.hs-boot" "haskell" contentAboot
334− _ <- createDoc "ModuleC.hs" "haskell" contentC
314+ _ <- openDoc' "ModuleC.hs" "haskell" contentC
335 expectDiagnostics []
315 expectDiagnostics []
336 , testSessionWait "redundant import" $ do
316 , testSessionWait "redundant import" $ do
337 let contentA = T.unlines ["module ModuleA where"]
317 let contentA = T.unlines ["module ModuleA where"]
@@ -340,8 +320,8 @@ diagnosticTests = testGroup "diagnostics"
340 , "module ModuleB where"
320 , "module ModuleB where"
341 , "import ModuleA"
321 , "import ModuleA"
343− _ <- createDoc "ModuleA.hs" "haskell" contentA
323+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
344− _ <- createDoc "ModuleB.hs" "haskell" contentB
324+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
345 expectDiagnostics
325 expectDiagnostics
346 [ ( "ModuleB.hs"
326 [ ( "ModuleB.hs"
347 , [(DsWarning, (2, 0), "The import of 'ModuleA' is redundant")]
327 , [(DsWarning, (2, 0), "The import of 'ModuleA' is redundant")]
@@ -363,8 +343,8 @@ diagnosticTests = testGroup "diagnostics"
363 , "wrong1 = ThisList.map"
343 , "wrong1 = ThisList.map"
364 , "wrong2 = BaseList.x"
344 , "wrong2 = BaseList.x"
366− _ <- createDoc "Data/List.hs" "haskell" thisDataListContent
346+ _ <- openDoc' "Data/List.hs" "haskell" thisDataListContent
367− _ <- createDoc "Main.hs" "haskell" mainContent
347+ _ <- openDoc' "Main.hs" "haskell" mainContent
368 expectDiagnostics
348 expectDiagnostics
369 [ ( "Main.hs"
349 [ ( "Main.hs"
370 , [(DsError, (6, 9), "Not in scope: \8216ThisList.map\8217")
350 , [(DsError, (6, 9), "Not in scope: \8216ThisList.map\8217")
@@ -379,7 +359,7 @@ diagnosticTests = testGroup "diagnostics"
379 , "foo :: Ord a => a -> Int"
359 , "foo :: Ord a => a -> Int"
380 , "foo a = 1"
360 , "foo a = 1"
382− _ <- createDoc "Foo.hs" "haskell" fooContent
362+ _ <- openDoc' "Foo.hs" "haskell" fooContent
383 expectDiagnostics
363 expectDiagnostics
384 [ ( "Foo.hs"
364 [ ( "Foo.hs"
385 -- The test is to make sure that warnings contain unqualified names
365 -- The test is to make sure that warnings contain unqualified names
@@ -404,18 +384,18 @@ diagnosticTests = testGroup "diagnostics"
404 Just pathB <- pure $ uriToFilePath uriB
384 Just pathB <- pure $ uriToFilePath uriB
405 uriB <- pure $
385 uriB <- pure $
406 let (drive, suffix) = splitDrive pathB
386 let (drive, suffix) = splitDrive pathB
407− in filePathToUri (joinDrive (lower drive) suffix)
387+ in filePathToUri (joinDrive (map toLower drive ) suffix)
408 liftIO $ createDirectoryIfMissing True (takeDirectory pathB)
388 liftIO $ createDirectoryIfMissing True (takeDirectory pathB)
409 liftIO $ writeFileUTF8 pathB $ T.unpack bContent
389 liftIO $ writeFileUTF8 pathB $ T.unpack bContent
410 uriA <- getDocUri "A/A.hs"
390 uriA <- getDocUri "A/A.hs"
411 Just pathA <- pure $ uriToFilePath uriA
391 Just pathA <- pure $ uriToFilePath uriA
412 uriA <- pure $
392 uriA <- pure $
413 let (drive, suffix) = splitDrive pathA
393 let (drive, suffix) = splitDrive pathA
414− in filePathToUri (joinDrive (lower drive) suffix)
394+ in filePathToUri (joinDrive (map toLower drive ) suffix)
415 let itemA = TextDocumentItem uriA "haskell" 0 aContent
395 let itemA = TextDocumentItem uriA "haskell" 0 aContent
416 let a = TextDocumentIdentifier uriA
396 let a = TextDocumentIdentifier uriA
417 sendNotification TextDocumentDidOpen (DidOpenTextDocumentParams itemA)
397 sendNotification TextDocumentDidOpen (DidOpenTextDocumentParams itemA)
418− diagsNot <- skipManyTill anyMessage diagnostic
398+ diagsNot <- skipManyTill anyMessage message :: Session PublishDiagnosticsNotification
419 let PublishDiagnosticsParams fileUri diags = _params (diagsNot :: PublishDiagnosticsNotification)
399 let PublishDiagnosticsParams fileUri diags = _params (diagsNot :: PublishDiagnosticsNotification)
420 -- Check that if we put a lower-case drive in for A.A
400 -- Check that if we put a lower-case drive in for A.A
421 -- the diagnostics for A.B will also be lower-case.
401 -- the diagnostics for A.B will also be lower-case.
@@ -424,38 +404,6 @@ diagnosticTests = testGroup "diagnostics"
424 liftIO $ unless ("redundant" `T.isInfixOf` msg) $
404 liftIO $ unless ("redundant" `T.isInfixOf` msg) $
425 assertFailure ("Expected redundant import but got " <> T.unpack msg)
405 assertFailure ("Expected redundant import but got " <> T.unpack msg)
426 closeDoc a
406 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
409codeActionTests :: TestTree
@@ -464,7 +412,6 @@ codeActionTests = testGroup "code actions"
464 , typeWildCardActionTests
412 , typeWildCardActionTests
465 , removeImportTests
413 , removeImportTests
466 , extendImportTests
414 , extendImportTests
467− , suggestImportTests
468 , addExtensionTests
415 , addExtensionTests
469 , fixConstructorImportTests
416 , fixConstructorImportTests
470 , importRenameActionTests
417 , importRenameActionTests
@@ -480,28 +427,21 @@ codeLensesTests = testGroup "code lenses"
481watchedFilesTests :: TestTree
428watchedFilesTests :: TestTree
482watchedFilesTests = testGroup "watched files"
429watchedFilesTests = testGroup "watched files"
483− [ testSession' "workspace files" $ \sessionDir -> do
430+ [ testSession "workspace file" $ do
484− liftIO $ writeFile (sessionDir </> "hie.yaml") "cradle: {direct: {arguments: [\"-isrc\"]}}"
431+ _ <- openDoc' "A.hs" "haskell" "module A where"
485− _doc <- createDoc "A.hs" "haskell" "{-#LANGUAGE NoImplicitPrelude #-}\nmodule A where\nimport WatchedFilesMissingModule"
432+ RequestMessage{_params = RegistrationParams (List regs)} <- skipManyTill anyMessage (message @RegisterCapabilityRequest)
486− watchedFileRegs <- getWatchedFilesSubscriptionsUntil @PublishDiagnosticsNotification
433+ let watchedFileRegs =
487−
434+ [ args | Registration _id WorkspaceDidChangeWatchedFiles args <- regs ]
488− -- Expect 4 subscriptions (A does not get any because it's VFS):
435+ liftIO $ assertBool "watches workspace files" $ not $ null watchedFileRegs
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
495− , testSession' "non workspace file" $ \sessionDir -> do
436+ , testSession "non workspace file" $ do
496− liftIO $ writeFile (sessionDir </> "hie.yaml") "cradle: {direct: {arguments: [\"-i/tmp\"]}}"
437+ _ <- openDoc' "/tmp/A.hs" "haskell" "module A where"
497− _doc <- createDoc "A.hs" "haskell" "{-# LANGUAGE NoImplicitPrelude#-}\nmodule A where\nimport WatchedFilesMissingModule"
438+ msgs <- manyTill (Just <$> message @RegisterCapabilityRequest <|> Nothing <$ anyMessage) (message @WorkDoneProgressEndNotification)
498− watchedFileRegs <- getWatchedFilesSubscriptionsUntil @PublishDiagnosticsNotification
439+ let watchedFileRegs =
500− -- Expect 2 subscriptions (/tmp does not get any as it is out of the workspace):
441+ | Just (RequestMessage{_params = RegistrationParams (List regs)}) <- msgs
501− -- - /path-to-workspace/WatchedFilesMissingModule.hs
442+ , Registration _id WorkspaceDidChangeWatchedFiles args <- regs
502− -- - /path-to-workspace/WatchedFilesMissingModule.lhs
443+ ]
503− liftIO $ length watchedFileRegs @?= 2
444+ liftIO $ watchedFileRegs @?= []
505 -- TODO add a test for didChangeWorkspaceFolder
445 -- TODO add a test for didChangeWorkspaceFolder
@@ -513,7 +453,7 @@ renameActionTests = testGroup "rename actions"
513 , "foo :: Int -> Int"
453 , "foo :: Int -> Int"
514 , "foo argName = argNme"
454 , "foo argName = argNme"
516− doc <- createDoc "Testing.hs" "haskell" content
456+ doc <- openDoc' "Testing.hs" "haskell" content
517 _ <- waitForDiagnostics
457 _ <- waitForDiagnostics
518 action <- findCodeAction doc (Range (Position 2 14) (Position 2 20)) "Replace with ‘argName’"
458 action <- findCodeAction doc (Range (Position 2 14) (Position 2 20)) "Replace with ‘argName’"
519 executeCodeAction action
459 executeCodeAction action
@@ -531,7 +471,7 @@ renameActionTests = testGroup "rename actions"
531 , "foo :: Maybe a -> [a]"
471 , "foo :: Maybe a -> [a]"
532 , "foo = maybToList"
472 , "foo = maybToList"
534− doc <- createDoc "Testing.hs" "haskell" content
474+ doc <- openDoc' "Testing.hs" "haskell" content
535 _ <- waitForDiagnostics
475 _ <- waitForDiagnostics
536 action <- findCodeAction doc (Range (Position 3 6) (Position 3 16)) "Replace with ‘maybeToList’"
476 action <- findCodeAction doc (Range (Position 3 6) (Position 3 16)) "Replace with ‘maybeToList’"
537 executeCodeAction action
477 executeCodeAction action
@@ -549,7 +489,7 @@ renameActionTests = testGroup "rename actions"
549 , "foo :: Char -> Char -> Char -> Char"
489 , "foo :: Char -> Char -> Char -> Char"
550 , "foo argument1 argument2 argument3 = argumentX"
490 , "foo argument1 argument2 argument3 = argumentX"
552− doc <- createDoc "Testing.hs" "haskell" content
492+ doc <- openDoc' "Testing.hs" "haskell" content
553 _ <- waitForDiagnostics
493 _ <- waitForDiagnostics
554 _ <- findCodeActions doc (Range (Position 2 36) (Position 2 45))
494 _ <- findCodeActions doc (Range (Position 2 36) (Position 2 45))
555 ["Replace with ‘argument1’", "Replace with ‘argument2’", "Replace with ‘argument3’"]
495 ["Replace with ‘argument1’", "Replace with ‘argument2’", "Replace with ‘argument3’"]
@@ -561,7 +501,7 @@ renameActionTests = testGroup "rename actions"
561 , "monus x y = max 0 (x - y)"
501 , "monus x y = max 0 (x - y)"
562 , "foo x y = x `monnus` y"
502 , "foo x y = x `monnus` y"
564− doc <- createDoc "Testing.hs" "haskell" content
504+ doc <- openDoc' "Testing.hs" "haskell" content
565 _ <- waitForDiagnostics
505 _ <- waitForDiagnostics
566 actionsOrCommands <- getCodeActions doc (Range (Position 3 12) (Position 3 20))
506 actionsOrCommands <- getCodeActions doc (Range (Position 3 12) (Position 3 20))
567 [fixTypo] <- pure [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, "monus" `T.isInfixOf` actionTitle ]
507 [fixTypo] <- pure [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, "monus" `T.isInfixOf` actionTitle ]
@@ -584,7 +524,7 @@ typeWildCardActionTests = testGroup "type wildcard actions"
584 , "func :: _"
524 , "func :: _"
585 , "func x = x"
525 , "func x = x"
587− doc <- createDoc "Testing.hs" "haskell" content
527+ doc <- openDoc' "Testing.hs" "haskell" content
588 _ <- waitForDiagnostics
528 _ <- waitForDiagnostics
589 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
529 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
590 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
530 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
@@ -604,7 +544,7 @@ typeWildCardActionTests = testGroup "type wildcard actions"
604 , "func :: _"
544 , "func :: _"
605 , "func x y = x + y"
545 , "func x y = x + y"
607− doc <- createDoc "Testing.hs" "haskell" content
547+ doc <- openDoc' "Testing.hs" "haskell" content
608 _ <- waitForDiagnostics
548 _ <- waitForDiagnostics
609 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
549 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
610 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
550 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
@@ -627,7 +567,7 @@ typeWildCardActionTests = testGroup "type wildcard actions"
627 , " y = x * 2"
567 , " y = x * 2"
628 , " in y"
568 , " in y"
630− doc <- createDoc "Testing.hs" "haskell" content
570+ doc <- openDoc' "Testing.hs" "haskell" content
631 _ <- waitForDiagnostics
571 _ <- waitForDiagnostics
632 actionsOrCommands <- getCodeActions doc (Range (Position 4 1) (Position 4 10))
572 actionsOrCommands <- getCodeActions doc (Range (Position 4 1) (Position 4 10))
633 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
573 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
@@ -652,7 +592,7 @@ removeImportTests = testGroup "remove import actions"
652 let contentA = T.unlines
592 let contentA = T.unlines
653 [ "module ModuleA where"
593 [ "module ModuleA where"
655− _docA <- createDoc "ModuleA.hs" "haskell" contentA
595+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
656 let contentB = T.unlines
596 let contentB = T.unlines
657 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
597 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
658 , "module ModuleB where"
598 , "module ModuleB where"
@@ -660,7 +600,7 @@ removeImportTests = testGroup "remove import actions"
660 , "stuffB :: Integer"
600 , "stuffB :: Integer"
661 , "stuffB = 123"
601 , "stuffB = 123"
663− docB <- createDoc "ModuleB.hs" "haskell" contentB
603+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
664 _ <- waitForDiagnostics
604 _ <- waitForDiagnostics
665 [CACodeAction action@CodeAction { _title = actionTitle }]
605 [CACodeAction action@CodeAction { _title = actionTitle }]
666 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
606 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -678,7 +618,7 @@ removeImportTests = testGroup "remove import actions"
678 let contentA = T.unlines
618 let contentA = T.unlines
679 [ "module ModuleA where"
619 [ "module ModuleA where"
681− _docA <- createDoc "ModuleA.hs" "haskell" contentA
621+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
682 let contentB = T.unlines
622 let contentB = T.unlines
683 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
623 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
684 , "module ModuleB where"
624 , "module ModuleB where"
@@ -686,7 +626,7 @@ removeImportTests = testGroup "remove import actions"
686 , "stuffB :: Integer"
626 , "stuffB :: Integer"
687 , "stuffB = 123"
627 , "stuffB = 123"
689− docB <- createDoc "ModuleB.hs" "haskell" contentB
629+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
690 _ <- waitForDiagnostics
630 _ <- waitForDiagnostics
691 [CACodeAction action@CodeAction { _title = actionTitle }]
631 [CACodeAction action@CodeAction { _title = actionTitle }]
692 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
632 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -708,14 +648,14 @@ removeImportTests = testGroup "remove import actions"
708 , "stuffB = 123"
648 , "stuffB = 123"
709 , "stuffC = ()"
649 , "stuffC = ()"
711− _docA <- createDoc "ModuleA.hs" "haskell" contentA
651+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
712 let contentB = T.unlines
652 let contentB = T.unlines
713 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
653 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
714 , "module ModuleB where"
654 , "module ModuleB where"
715 , "import ModuleA (stuffA, stuffB, stuffC, stuffA)"
655 , "import ModuleA (stuffA, stuffB, stuffC, stuffA)"
716 , "main = print stuffB"
656 , "main = print stuffB"
718− docB <- createDoc "ModuleB.hs" "haskell" contentB
658+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
719 _ <- waitForDiagnostics
659 _ <- waitForDiagnostics
720 [CACodeAction action@CodeAction { _title = actionTitle }]
660 [CACodeAction action@CodeAction { _title = actionTitle }]
721 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
661 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -729,26 +669,29 @@ removeImportTests = testGroup "remove import actions"
729 , "main = print stuffB"
669 , "main = print stuffB"
731 liftIO $ expectedContentAfterAction @=? contentAfterAction
671 liftIO $ expectedContentAfterAction @=? contentAfterAction
732− , testSession "redundant operator" $ do
672+ , testSession "redundant symbol binding" $ do
733 let contentA = T.unlines
673 let contentA = T.unlines
734 [ "module ModuleA where"
674 [ "module ModuleA where"
735 , "a !! b = a"
675 , "a !! b = a"
737 , "stuffB :: Integer"
676 , "stuffB :: Integer"
738 , "stuffB = 123"
677 , "stuffB = 123"
740− _docA <- createDoc "ModuleA.hs" "haskell" contentA
679+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
741 let contentB = T.unlines
680 let contentB = T.unlines
742 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
681 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
743 , "module ModuleB where"
682 , "module ModuleB where"
744− , "import qualified ModuleA as A ((<?>), stuffB, (!!))"
683+ , "import qualified ModuleA as A ((!!), stuffB, (!!))"
745 , "main = print A.stuffB"
684 , "main = print A.stuffB"
747− docB <- createDoc "ModuleB.hs" "haskell" contentB
686+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
748 _ <- waitForDiagnostics
687 _ <- waitForDiagnostics
749 [CACodeAction action@CodeAction { _title = actionTitle }]
688 [CACodeAction action@CodeAction { _title = actionTitle }]
750 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
689 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
690+#if MIN_GHC_API_VERSION(8,6,0)
691+ liftIO $ "Remove !! from import" @=? actionTitle
751− liftIO $ "Remove !!, <?> from import" @=? actionTitle
693+ liftIO $ "Remove A.!! from import" @=? actionTitle
752 executeCodeAction action
695 executeCodeAction action
753 contentAfterAction <- documentContents docB
696 contentAfterAction <- documentContents docB
754 let expectedContentAfterAction = T.unlines
697 let expectedContentAfterAction = T.unlines
@@ -758,21 +701,21 @@ removeImportTests = testGroup "remove import actions"
758 , "main = print A.stuffB"
701 , "main = print A.stuffB"
760 liftIO $ expectedContentAfterAction @=? contentAfterAction
703 liftIO $ expectedContentAfterAction @=? contentAfterAction
761− , testSession "redundant all import" $ do
704+ , (`xfail` "known broken (#299)") $ testSession "redundant hierarchical import" $ do
762 let contentA = T.unlines
705 let contentA = T.unlines
763 [ "module ModuleA where"
706 [ "module ModuleA where"
764 , "data A = A"
707 , "data A = A"
765 , "stuffB :: Integer"
708 , "stuffB :: Integer"
766 , "stuffB = 123"
709 , "stuffB = 123"
768− _docA <- createDoc "ModuleA.hs" "haskell" contentA
711+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
769 let contentB = T.unlines
712 let contentB = T.unlines
770 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
713 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
771 , "module ModuleB where"
714 , "module ModuleB where"
772 , "import ModuleA (A(..), stuffB)"
715 , "import ModuleA (A(..), stuffB)"
773 , "main = print stuffB"
716 , "main = print stuffB"
775− docB <- createDoc "ModuleB.hs" "haskell" contentB
718+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
776 _ <- waitForDiagnostics
719 _ <- waitForDiagnostics
777 [CACodeAction action@CodeAction { _title = actionTitle }]
720 [CACodeAction action@CodeAction { _title = actionTitle }]
778 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
721 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -786,33 +729,6 @@ removeImportTests = testGroup "remove import actions"
786 , "main = print stuffB"
729 , "main = print stuffB"
788 liftIO $ expectedContentAfterAction @=? contentAfterAction
731 liftIO $ expectedContentAfterAction @=? contentAfterAction
789− , testSession "redundant constructor import" $ do
790− let contentA = T.unlines
791− [ "module ModuleA where"
795− _docA <- createDoc "ModuleA.hs" "haskell" contentA
796− let contentB = T.unlines
797− [ "{-# OPTIONS_GHC -Wunused-imports #-}"
798− , "module ModuleB where"
799− , "import ModuleA (D(A,B), E(F))"
802− docB <- createDoc "ModuleB.hs" "haskell" contentB
803− _ <- waitForDiagnostics
804− [CACodeAction action@CodeAction { _title = actionTitle }]
805− <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
806− liftIO $ "Remove A, E, F from import" @=? actionTitle
807− executeCodeAction action
808− contentAfterAction <- documentContents docB
809− let expectedContentAfterAction = T.unlines
810− [ "{-# OPTIONS_GHC -Wunused-imports #-}"
811− , "module ModuleB where"
812− , "import ModuleA (D(B))"
815− liftIO $ expectedContentAfterAction @=? contentAfterAction
818extendImportTests :: TestTree
734extendImportTests :: TestTree
@@ -940,8 +856,8 @@ extendImportTests = testGroup "extend import actions"
942 template contentA contentB range expectedAction expectedContentB = do
858 template contentA contentB range expectedAction expectedContentB = do
943− _docA <- createDoc "ModuleA.hs" "haskell" contentA
859+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
944− docB <- createDoc "ModuleB.hs" "haskell" contentB
860+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
945 _ <- waitForDiagnostics
861 _ <- waitForDiagnostics
946 CACodeAction action@CodeAction { _title = actionTitle } : _
862 CACodeAction action@CodeAction { _title = actionTitle } : _
947 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
863 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -951,61 +867,6 @@ extendImportTests = testGroup "extend import actions"
951 contentAfterAction <- documentContents docB
867 contentAfterAction <- documentContents docB
952 liftIO $ expectedContentB @=? contentAfterAction
868 liftIO $ expectedContentB @=? contentAfterAction
954−suggestImportTests :: TestTree
955−suggestImportTests = testGroup "suggest import actions"
956− [ testGroup "Dont want suggestion"
958− test False ["Data.List.NonEmpty ()"] "f = nonEmpty" [] "import Data.List.NonEmpty (nonEmpty)"
960− , test False [] "f = First" [] "import Data.Monoid (First)"
962− , test False [] "f :: Typeable a => a" ["f = undefined"] "import Data.Typeable.Internal (Typeable)"
963− -- package not in scope
964− , test False [] "f = quickCheck" [] "import Test.QuickCheck (quickCheck)"
966− , testGroup "want suggestion"
967− [ test True [] "f = nonEmpty" [] "import Data.List.NonEmpty (nonEmpty)"
968− , test True [] "f = (:|)" [] "import Data.List.NonEmpty (NonEmpty((:|)))"
969− , test True [] "f :: Natural" ["f = undefined"] "import Numeric.Natural (Natural)"
970− , test True [] "f :: NonEmpty ()" ["f = () :| []"] "import Data.List.NonEmpty (NonEmpty)"
971− , test True [] "f = First" [] "import Data.Monoid (First(First))"
972− , test True [] "f = Endo" [] "import Data.Monoid (Endo(Endo))"
973− , test True [] "f = Version" [] "import Data.Version (Version(Version))"
974− , test True [] "f ExitSuccess = ()" [] "import System.Exit (ExitCode(ExitSuccess))"
975− , test True [] "f = AssertionFailed" [] "import Control.Exception (AssertionFailed(AssertionFailed))"
976− , test True ["Prelude"] "f = nonEmpty" [] "import Data.List.NonEmpty (nonEmpty)"
977− , test True [] "f :: Alternative f => f ()" ["f = undefined"] "import Control.Applicative (Alternative)"
978− , test True [] "f = empty" [] "import Control.Applicative (Alternative(empty))"
979− , test True [] "f = (&)" [] "import Data.Function ((&))"
980− , test True [] "f = NE.nonEmpty" [] "import qualified Data.List.NonEmpty as NE"
981− , test True [] "f :: Typeable a => a" ["f = undefined"] "import Data.Typeable (Typeable)"
982− , test True [] "f = pack" [] "import Data.Text (pack)"
983− , 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 ((&))"
989− test wanted imps def other newImp = testSession' (T.unpack def) $ \dir -> do
990− let before = T.unlines $ "module A where" : ["import " <> x | x <- imps] ++ def : other
991− 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, -]}}"
993− liftIO $ writeFileUTF8 (dir </> "hie.yaml") cradle
994− doc <- createDoc "Test.hs" "haskell" before
995− _diags <- waitForDiagnostics
996− let defLine = length imps + 1
997− range = Range (Position defLine 0) (Position defLine maxBound)
998− actions <- getCodeActions doc range
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 ] @?= []
1009addExtensionTests :: TestTree
870addExtensionTests :: TestTree
1010addExtensionTests = testGroup "add language extension actions"
871addExtensionTests = testGroup "add language extension actions"
1011 [ testSession "add NamedFieldPuns language extension" $ template
872 [ testSession "add NamedFieldPuns language extension" $ template
@@ -1051,7 +912,7 @@ addExtensionTests = testGroup "add language extension actions"
1053 template initialContent range expectedAction expectedContents = do
914 template initialContent range expectedAction expectedContents = do
1054− doc <- createDoc "Module.hs" "haskell" initialContent
915+ doc <- openDoc' "Module.hs" "haskell" initialContent
1055 _ <- waitForDiagnostics
916 _ <- waitForDiagnostics
1056 CACodeAction action@CodeAction { _title = actionTitle } : _
917 CACodeAction action@CodeAction { _title = actionTitle } : _
1057 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
918 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1074,7 +935,7 @@ insertNewDefinitionTests = testGroup "insert new definition actions"
1075 ,"someOtherCode = ()"
936 ,"someOtherCode = ()"
1077− docB <- createDoc "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
938+ docB <- openDoc' "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
1078 _ <- waitForDiagnostics
939 _ <- waitForDiagnostics
1079 CACodeAction action@CodeAction { _title = actionTitle } : _
940 CACodeAction action@CodeAction { _title = actionTitle } : _
1080 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
941 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1098,7 +959,7 @@ insertNewDefinitionTests = testGroup "insert new definition actions"
1099 ,"someOtherCode = ()"
960 ,"someOtherCode = ()"
1101− docB <- createDoc "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
962+ docB <- openDoc' "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
1102 _ <- waitForDiagnostics
963 _ <- waitForDiagnostics
1103 CACodeAction action@CodeAction { _title = actionTitle } : _
964 CACodeAction action@CodeAction { _title = actionTitle } : _
1104 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
965 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1137,8 +998,8 @@ fixConstructorImportTests = testGroup "fix import actions"
1139 template contentA contentB range expectedAction expectedContentB = do
1000 template contentA contentB range expectedAction expectedContentB = do
1140− _docA <- createDoc "ModuleA.hs" "haskell" contentA
1001+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
1141− docB <- createDoc "ModuleB.hs" "haskell" contentB
1002+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
1142 _diags <- waitForDiagnostics
1003 _diags <- waitForDiagnostics
1143 CACodeAction action@CodeAction { _title = actionTitle } : _
1004 CACodeAction action@CodeAction { _title = actionTitle } : _
1144 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
1005 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1157,7 +1018,7 @@ importRenameActionTests = testGroup "import rename actions"
1157 [ "module Testing where"
1018 [ "module Testing where"
1158 , "import Data.Mape"
1019 , "import Data.Mape"
1160− doc <- createDoc "Testing.hs" "haskell" content
1021+ doc <- openDoc' "Testing.hs" "haskell" content
1161 _ <- waitForDiagnostics
1022 _ <- waitForDiagnostics
1162 actionsOrCommands <- getCodeActions doc (Range (Position 2 8) (Position 2 16))
1023 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 ]
1024 let [changeToMap] = [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, ("Data." <> modname) `T.isInfixOf` actionTitle ]
@@ -1194,10 +1055,10 @@ fillTypedHoleTests = let
1194 newA newB newC = testSession (T.unpack actionTitle) $ do
1055 newA newB newC = testSession (T.unpack actionTitle) $ do
1195 let originalCode = sourceCode oldA oldB oldC
1056 let originalCode = sourceCode oldA oldB oldC
1196 let expectedCode = sourceCode newA newB newC
1057 let expectedCode = sourceCode newA newB newC
1197− doc <- createDoc "Testing.hs" "haskell" originalCode
1058+ doc <- openDoc' "Testing.hs" "haskell" originalCode
1198 _ <- waitForDiagnostics
1059 _ <- waitForDiagnostics
1199 actionsOrCommands <- getCodeActions doc (Range (Position 9 0) (Position 9 maxBound))
1060 actionsOrCommands <- getCodeActions doc (Range (Position 9 0) (Position 9 maxBound))
1200− chosenAction <- liftIO $ pickActionWithTitle actionTitle actionsOrCommands
1061+ let chosenAction = pickActionWithTitle actionTitle actionsOrCommands
1201 executeCodeAction chosenAction
1062 executeCodeAction chosenAction
1202 modifiedCode <- documentContents doc
1063 modifiedCode <- documentContents doc
1203 liftIO $ expectedCode @=? modifiedCode
1064 liftIO $ expectedCode @=? modifiedCode
@@ -1234,37 +1095,36 @@ fillTypedHoleTests = let
1235addSigActionTests :: TestTree
1096addSigActionTests :: TestTree
1236addSigActionTests = let
1097addSigActionTests = let
1237− header = "{-# OPTIONS_GHC -Wmissing-signatures -Wmissing-pattern-synonym-signatures #-}"
1098+ header = "{-# OPTIONS_GHC -Wmissing-signatures #-}"
1238− moduleH = "{-# LANGUAGE PatternSynonyms #-}\nmodule Sigs where"
1099+ moduleH = "module Sigs where"
1239 before def = T.unlines [header, moduleH, def]
1100 before def = T.unlines [header, moduleH, def]
1240 after' def sig = T.unlines [header, moduleH, sig, def]
1101 after' def sig = T.unlines [header, moduleH, sig, def]
1242 def >:: sig = testSession (T.unpack def) $ do
1103 def >:: sig = testSession (T.unpack def) $ do
1243 let originalCode = before def
1104 let originalCode = before def
1244 let expectedCode = after' def sig
1105 let expectedCode = after' def sig
1245− doc <- createDoc "Sigs.hs" "haskell" originalCode
1106+ doc <- openDoc' "Sigs.hs" "haskell" originalCode
1246 _ <- waitForDiagnostics
1107 _ <- waitForDiagnostics
1247 actionsOrCommands <- getCodeActions doc (Range (Position 3 1) (Position 3 maxBound))
1108 actionsOrCommands <- getCodeActions doc (Range (Position 3 1) (Position 3 maxBound))
1248− chosenAction <- liftIO $ pickActionWithTitle ("add signature: " <> sig) actionsOrCommands
1109+ let chosenAction = pickActionWithTitle ("add signature: " <> sig) actionsOrCommands
1249 executeCodeAction chosenAction
1110 executeCodeAction chosenAction
1250 modifiedCode <- documentContents doc
1111 modifiedCode <- documentContents doc
1251 liftIO $ expectedCode @=? modifiedCode
1112 liftIO $ expectedCode @=? modifiedCode
1253 testGroup "add signature"
1114 testGroup "add signature"
1254− [ "abc = True" >:: "abc :: Bool"
1115+ [ "abc = True" >:: "abc :: Bool"
1255− , "foo a b = a + b" >:: "foo :: Num a => a -> a -> a"
1116+ , "foo a b = a + b" >:: "foo :: Num a => a -> a -> a"
1256− , "bar a b = show $ a + b" >:: "bar :: (Show a, Num a) => a -> a -> String"
1117+ , "bar a b = show $ a + b" >:: "bar :: (Show a, Num a) => a -> a -> String"
1257− , "(!!!) a b = a > b" >:: "(!!!) :: Ord a => a -> a -> Bool"
1118+ , "(!!!) a b = a > b" >:: "(!!!) :: Ord a => a -> a -> Bool"
1258− , "a >>>> b = a + b" >:: "(>>>>) :: Num a => a -> a -> a"
1119+ , "a >>>> b = a + b" >:: "(>>>>) :: Num a => a -> a -> a"
1259− , "a `haha` b = a b" >:: "haha :: (t1 -> t2) -> t1 -> t2"
1120+ , "a `haha` b = a b" >:: "haha :: (t1 -> t2) -> t1 -> t2"
1260− , "pattern Some a = Just a" >:: "pattern Some :: a -> Maybe a"
1263addSigLensesTests :: TestTree
1123addSigLensesTests :: TestTree
1264addSigLensesTests = let
1124addSigLensesTests = let
1265− missing = "{-# OPTIONS_GHC -Wmissing-signatures -Wmissing-pattern-synonym-signatures -Wunused-matches #-}"
1125+ missing = "{-# OPTIONS_GHC -Wmissing-signatures -Wunused-matches #-}"
1266 notMissing = "{-# OPTIONS_GHC -Wunused-matches #-}"
1126 notMissing = "{-# OPTIONS_GHC -Wunused-matches #-}"
1267− moduleH = "{-# LANGUAGE PatternSynonyms #-}\nmodule Sigs where"
1127+ moduleH = "module Sigs where"
1268 other = T.unlines ["f :: Integer -> Integer", "f x = 3"]
1128 other = T.unlines ["f :: Integer -> Integer", "f x = 3"]
1269 before withMissing def
1129 before withMissing def
1270 = T.unlines $ (if withMissing then (missing :) else (notMissing :)) [moduleH, def, other]
1130 = T.unlines $ (if withMissing then (missing :) else (notMissing :)) [moduleH, def, other]
@@ -1274,61 +1134,58 @@ addSigLensesTests = let
1274 sigSession withMissing def sig = testSession (T.unpack def) $ do
1134 sigSession withMissing def sig = testSession (T.unpack def) $ do
1275 let originalCode = before withMissing def
1135 let originalCode = before withMissing def
1276 let expectedCode = after' withMissing def sig
1136 let expectedCode = after' withMissing def sig
1277− doc <- createDoc "Sigs.hs" "haskell" originalCode
1137+ doc <- openDoc' "Sigs.hs" "haskell" originalCode
1278 [CodeLens {_command = Just c}] <- getCodeLenses doc
1138 [CodeLens {_command = Just c}] <- getCodeLenses doc
1279 executeCommand c
1139 executeCommand c
1280 modifiedCode <- getDocumentEdit doc
1140 modifiedCode <- getDocumentEdit doc
1281 liftIO $ expectedCode @=? modifiedCode
1141 liftIO $ expectedCode @=? modifiedCode
1283 testGroup "add signature"
1143 testGroup "add signature"
1284− [ testGroup title
1144+ [ testGroup "with warnings enabled"
1285− [ sigSession enableWarnings "abc = True" "abc :: Bool"
1145+ [ sigSession True "abc = True" "abc :: Bool"
1286− , sigSession enableWarnings "foo a b = a + b" "foo :: Num a => a -> a -> a"
1146+ , sigSession True "foo a b = a + b" "foo :: Num a => a -> a -> a"
1287− , sigSession enableWarnings "bar a b = show $ a + b" "bar :: (Show a, Num a) => a -> a -> String"
1147+ , sigSession True "bar a b = show $ a + b" "bar :: (Show a, Num a) => a -> a -> String"
1288− , sigSession enableWarnings "(!!!) a b = a > b" "(!!!) :: Ord a => a -> a -> Bool"
1148+ , sigSession True "(!!!) a b = a > b" "(!!!) :: Ord a => a -> a -> Bool"
1289− , sigSession enableWarnings "a >>>> b = a + b" "(>>>>) :: Num a => a -> a -> a"
1149+ , sigSession True "a >>>> b = a + b" "(>>>>) :: Num a => a -> a -> a"
1290− , sigSession enableWarnings "a `haha` b = a b" "haha :: (t1 -> t2) -> t1 -> t2"
1150+ , sigSession True "a `haha` b = a b" "haha :: (t1 -> t2) -> t1 -> t2"
1291− , sigSession enableWarnings "pattern Some a = Just a" "pattern Some :: a -> Maybe a"
1151+ ]
1152+ , testGroup "with warnings disabled"
1153+ [ sigSession False "abc = True" "abc :: Bool"
1154+ , sigSession False "foo a b = a + b" "foo :: Num a => a -> a -> a"
1155+ , sigSession False "bar a b = show $ a + b" "bar :: (Show a, Num a) => a -> a -> String"
1156+ , sigSession False "(!!!) a b = a > b" "(!!!) :: Ord a => a -> a -> Bool"
1157+ , sigSession False "a >>>> b = a + b" "(>>>>) :: Num a => a -> a -> a"
1158+ , sigSession False "a `haha` b = a b" "haha :: (t1 -> t2) -> t1 -> t2"
1293− | (title, enableWarnings) <-
1294− [("with warnings enabled", True)
1295− ,("with warnings disabled", False)
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
1162findDefinitionAndHoverTests :: TestTree
1321findDefinitionAndHoverTests = let
1163findDefinitionAndHoverTests = let
1323− tst (get, check) pos targetRange title = testSessionWithExtraFiles "hover" title $ \dir -> do
1165+ tst (get, check) pos targetRange title = testSession title $ do
1324− doc <- openTestDataDoc (dir </> sourceFilePath)
1166+ doc <- openTestDataDoc sourceFilePath
1325 found <- get doc pos
1167 found <- get doc pos
1326 check found targetRange
1168 check found targetRange
1170+ checkDefs :: [Location] -> [Expect] -> Session ()
1171+ checkDefs defs expectations = traverse_ check expectations where
1173+ check (ExpectRange expectedRange) = do
1174+ assertNDefinitionsFound 1 defs
1175+ assertRangeCorrect (head defs) expectedRange
1176+ check ExpectNoDefinitions = do
1177+ assertNDefinitionsFound 0 defs
1178+ check ExpectExternFail = liftIO $ assertFailure "Expecting to fail to find in external file"
1179+ check _ = pure () -- all other expectations not relevant to getDefinition
1181+ assertNDefinitionsFound :: Int -> [a] -> Session ()
1182+ assertNDefinitionsFound n defs = liftIO $ assertEqual "number of definitions" n (length defs)
1184+ assertRangeCorrect Location{_range = foundRange} expectedRange =
1185+ liftIO $ expectedRange @=? foundRange
1330− checkHover :: Maybe Hover -> Session [Expect] -> Session ()
1187+ checkHover :: Maybe Hover -> [Expect] -> Session ()
1331− checkHover hover expectations = traverse_ check =<< expectations where
1188+ checkHover hover expectations = traverse_ check expectations where
1333 check expected =
1190 check expected =
1334 case hover of
1191 case hover of
@@ -1371,12 +1228,9 @@ findDefinitionAndHoverTests = let
1372 mkFindTests tests = testGroup "get"
1229 mkFindTests tests = testGroup "get"
1373 [ testGroup "definition" $ mapMaybe fst tests
1230 [ testGroup "definition" $ mapMaybe fst tests
1374− , testGroup "hover" $ mapMaybe snd tests
1231+ , testGroup "hover" $ mapMaybe snd tests ]
1375− , checkFileCompiles sourceFilePath ]
1377− test runDef runHover look expect = testM runDef runHover look (return expect)
1233+ test runDef runHover look expect title =
1379− testM runDef runHover look expect title =
1380 ( runDef $ tst def look expect title
1234 ( runDef $ tst def look expect title
1381 , runHover $ tst hover look expect title ) where
1235 , runHover $ tst hover look expect title ) where
1382 def = (getDefinitions, checkDefs)
1236 def = (getDefinitions, checkDefs)
@@ -1384,100 +1238,87 @@ findDefinitionAndHoverTests = let
1384 --type_ = (getTypeDefinitions, checkTDefs) -- getTypeDefinitions always times out
1238 --type_ = (getTypeDefinitions, checkTDefs) -- getTypeDefinitions always times out
1386 -- search locations expectations on results
1240 -- search locations expectations on results
1387− fffL4 = _start fffR ; fffR = mkRange 8 4 8 7 ; fff = [ExpectRange fffR]
1241+ fffL4 = _start fffR ; fffR = mkRange 4 4 4 7 ; fff = [ExpectRange fffR]
1388− fffL8 = Position 12 4 ;
1242+ fffL8 = Position 8 4 ;
1389− fffL14 = Position 18 7 ;
1243+ fffL14 = Position 14 7 ;
1390− aaaL14 = Position 18 20 ; aaa = [mkR 11 0 11 3]
1244+ aaaL14 = Position 14 20 ; aaa = [mkR 7 0 7 3]
1391− dcL7 = Position 11 11 ; tcDC = [mkR 7 23 9 16]
1245+ dcL7 = Position 7 11 ; tcDC = [mkR 3 23 5 16]
1392− dcL12 = Position 16 11 ;
1246+ dcL12 = Position 12 11 ;
1393− xtcL5 = Position 9 11 ; xtc = [ExpectExternFail, ExpectHoverText ["Int", "Defined in ‘GHC.Types’"]]
1247+ xtcL5 = Position 5 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"]]
1248+ tcL6 = Position 6 11 ; tcData = [mkR 3 0 5 16, ExpectHoverText ["TypeConstructor", "GotoHover.hs:4:1"]]
1395− vvL16 = Position 20 12 ; vv = [mkR 20 4 20 6]
1249+ vvL16 = Position 16 12 ; vv = [mkR 16 4 16 6]
1396− opL16 = Position 20 15 ; op = [mkR 21 2 21 4]
1250+ opL16 = Position 16 15 ; op = [mkR 17 2 17 4]
1397− opL18 = Position 22 22 ; opp = [mkR 22 13 22 17]
1251+ opL18 = Position 18 22 ; opp = [mkR 18 13 18 17]
1398− aL18 = Position 22 20 ; apmp = [mkR 22 10 22 11]
1252+ aL18 = Position 18 20 ; apmp = [mkR 18 10 18 11]
1399− b'L19 = Position 23 13 ; bp = [mkR 23 6 23 7]
1253+ b'L19 = Position 19 13 ; bp = [mkR 19 6 19 7]
1400− xvL20 = Position 24 8 ; xvMsg = [ExpectExternFail, ExpectHoverText ["Data.Text.pack", ":: String -> Text"]]
1254+ xvL20 = Position 20 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"]]
1255+ clL23 = Position 23 11 ; cls = [mkR 21 0 22 20, ExpectHoverText ["MyClass", "GotoHover.hs:22:1"]]
1402− clL25 = Position 29 9
1256+ clL25 = Position 25 9
1403− eclL15 = Position 19 8 ; ecls = [ExpectExternFail, ExpectHoverText ["Num", "Defined in ‘GHC.Num’"]]
1257+ eclL15 = Position 15 8 ; ecls = [ExpectExternFail, ExpectHoverText ["Num", "Defined in ‘GHC.Num’"]]
1404− dnbL29 = Position 33 18 ; dnb = [ExpectHoverText [":: ()"], mkR 33 12 33 21]
1258+ dnbL29 = Position 29 18 ; dnb = [ExpectHoverText [":: ()"], mkR 29 12 29 21]
1405− dnbL30 = Position 34 23
1259+ dnbL30 = Position 30 23
1406− lcbL33 = Position 37 26 ; lcb = [ExpectHoverText [":: Char"], mkR 37 26 37 27]
1260+ lcbL33 = Position 33 26 ; lcb = [ExpectHoverText [":: Char"], mkR 33 26 33 27]
1407− lclL33 = Position 37 22
1261+ lclL33 = Position 33 22
1408− mclL36 = Position 40 1 ; mcl = [mkR 40 0 40 14]
1262+ mclL36 = Position 36 1 ; mcl = [mkR 36 0 36 14]
1409− mclL37 = Position 41 1
1263+ mclL37 = Position 37 1
1410− spaceL37 = Position 41 24 ; space = [ExpectNoDefinitions, ExpectHoverText [":: Char"]]
1264+ spaceL37 = Position 37 24 ; space = [ExpectNoDefinitions, ExpectHoverText [":: Char"]]
1411− docL41 = Position 45 1 ; doc = [ExpectHoverText ["Recognizable docs: kpqz"]]
1265+ docL41 = Position 41 1 ; doc = [ExpectHoverText ["Recognizable docs: kpqz"]]
1412 ; constr = [ExpectHoverText ["Monad m"]]
1266 ; constr = [ExpectHoverText ["Monad m"]]
1413− eitL40 = Position 44 28 ; kindE = [ExpectHoverText [":: * -> * -> *\n"]]
1267+ eitL40 = Position 40 28 ; kindE = [ExpectHoverText [":: * -> * -> *\n"]]
1414− intL40 = Position 44 34 ; kindI = [ExpectHoverText [":: *\n"]]
1268+ intL40 = Position 40 34 ; kindI = [ExpectHoverText [":: *\n"]]
1415− tvrL40 = Position 44 37 ; kindV = [ExpectHoverText [":: * -> *\n"]]
1269+ tvrL40 = Position 40 37 ; kindV = [ExpectHoverText [":: * -> *\n"]]
1416− intL41 = Position 45 20 ; litI = [ExpectHoverText ["7518"]]
1270+ intL41 = Position 41 20 ; litI = [ExpectHoverText ["7518"]]
1417− chrL36 = Position 41 24 ; litC = [ExpectHoverText ["'f'"]]
1271+ chrL36 = Position 37 24 ; litC = [ExpectHoverText ["'f'"]]
1418− txtL8 = Position 12 14 ; litT = [ExpectHoverText ["\"dfgy\""]]
1272+ txtL8 = Position 8 14 ; litT = [ExpectHoverText ["\"dfgy\""]]
1419− lstL43 = Position 47 12 ; litL = [ExpectHoverText ["[8391 :: Int, 6268]"]]
1273+ lstL43 = Position 43 12 ; litL = [ExpectHoverText ["[8391 :: Int, 6268]"]]
1420− outL45 = Position 49 3 ; outSig = [ExpectHoverText ["outer", "Bool"], mkR 46 0 46 5]
1274+ outL45 = Position 45 3 ; outSig = [ExpectHoverText ["outer", "Bool"], mkR 46 0 46 5]
1421− innL48 = Position 52 5 ; innSig = [ExpectHoverText ["inner", "Char"], mkR 49 2 49 7]
1275+ innL48 = Position 48 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]
1425 mkFindTests
1277 mkFindTests
1426− -- def hover look expect
1278+ -- def hover look expect
1427− [ test yes yes fffL4 fff "field in record definition"
1279+ [ test yes yes fffL4 fff "field in record definition"
1428− , test broken broken fffL8 fff "field in record construction #71"
1280+ , 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
1281+ , test yes yes fffL14 fff "field name used as accessor" -- 120 in Calculate.hs
1430− , test yes yes aaaL14 aaa "top-level name" -- 120
1282+ , test yes yes aaaL14 aaa "top-level name" -- 120
1431− , test yes yes dcL7 tcDC "data constructor record #247"
1283+ , test yes yes dcL7 tcDC "data constructor record #247"
1432− , test yes yes dcL12 tcDC "data constructor plain" -- 121
1284+ , test yes yes dcL12 tcDC "data constructor plain" -- 121
1433− , test yes yes tcL6 tcData "type constructor #248" -- 147
1285+ , test yes yes tcL6 tcData "type constructor #248" -- 147
1434− , test broken yes xtcL5 xtc "type constructor external #248,249"
1286+ , test broken yes xtcL5 xtc "type constructor external #248,249"
1435− , test broken yes xvL20 xvMsg "value external package #249" -- 120
1287+ , test broken yes xvL20 xvMsg "value external package #249" -- 120
1436− , test yes yes vvL16 vv "plain parameter" -- 120
1288+ , test yes yes vvL16 vv "plain parameter" -- 120
1437− , test yes yes aL18 apmp "pattern match name" -- 120
1289+ , test yes yes aL18 apmp "pattern match name" -- 120
1438− , test yes yes opL16 op "top-level operator" -- 120, 123
1290+ , test yes yes opL16 op "top-level operator" -- 120, 123
1439− , test yes yes opL18 opp "parameter operator" -- 120
1291+ , test yes yes opL18 opp "parameter operator" -- 120
1440− , test yes yes b'L19 bp "name in backticks" -- 120
1292+ , test yes yes b'L19 bp "name in backticks" -- 120
1441− , test yes yes clL23 cls "class in instance declaration #250"
1293+ , test yes yes clL23 cls "class in instance declaration #250"
1442− , test yes yes clL25 cls "class in signature #250" -- 147
1294+ , test yes yes clL25 cls "class in signature #250" -- 147
1443− , test broken yes eclL15 ecls "external class in signature #249,250"
1295+ , test broken yes eclL15 ecls "external class in signature #249,250"
1444− , test yes yes dnbL29 dnb "do-notation bind" -- 137
1296+ , test yes yes dnbL29 dnb "do-notation bind" -- 137
1445− , test yes yes dnbL30 dnb "do-notation lookup"
1297+ , test yes yes dnbL30 dnb "do-notation lookup"
1446− , test yes yes lcbL33 lcb "listcomp bind" -- 137
1298+ , test yes yes lcbL33 lcb "listcomp bind" -- 137
1447− , test yes yes lclL33 lcb "listcomp lookup"
1299+ , test yes yes lclL33 lcb "listcomp lookup"
1448− , test yes yes mclL36 mcl "top-level fn 1st clause"
1300+ , test yes yes mclL36 mcl "top-level fn 1st clause"
1449− , test yes yes mclL37 mcl "top-level fn 2nd clause #246"
1301+ , test yes yes mclL37 mcl "top-level fn 2nd clause #246"
1450− , test yes yes spaceL37 space "top-level fn on space #315"
1302+ , test yes yes spaceL37 space "top-level fn on space #315"
1451− , test no broken docL41 doc "documentation #7"
1303+ , test no broken docL41 doc "documentation #7"
1452− , test no yes eitL40 kindE "kind of Either #273"
1304+ , test no yes eitL40 kindE "kind of Either #273"
1453− , test no yes intL40 kindI "kind of Int #273"
1305+ , test no yes intL40 kindI "kind of Int #273"
1454− , test no broken tvrL40 kindV "kind of (* -> *) type variable #273"
1306+ , test no broken tvrL40 kindV "kind of (* -> *) type variable #273"
1455− , test no yes intL41 litI "literal Int in hover info #274"
1307+ , test no yes intL41 litI "literal Int in hover info #274"
1456− , test no yes chrL36 litC "literal Char in hover info #274"
1308+ , test no yes chrL36 litC "literal Char in hover info #274"
1457− , test no yes txtL8 litT "literal Text in hover info #274"
1309+ , test no yes txtL8 litT "literal Text in hover info #274"
1458− , test no yes lstL43 litL "literal List in hover info #274"
1310+ , test no yes lstL43 litL "literal List in hover info #274"
1459− , test no yes docL41 constr "type constraint in hover info #283"
1311+ , test no yes docL41 constr "type constraint in hover info #283"
1460− , test broken broken outL45 outSig "top-level signature #310"
1312+ , test broken broken outL45 outSig "top-level signature #310"
1461− , test broken broken innL48 innSig "inner signature #310"
1313+ , 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)"
1465 where yes, broken :: (TestTree -> Maybe TestTree)
1315 where yes, broken :: (TestTree -> Maybe TestTree)
1466 yes = Just -- test should run and pass
1316 yes = Just -- test should run and pass
1467 broken = Just . (`xfail` "known broken")
1317 broken = Just . (`xfail` "known broken")
1468 no = const Nothing -- don't run this test at all
1318 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
1320pluginTests :: TestTree
1479−pluginTests = (`xfail8101` "known broken (#556)")
1480− $ testSessionWait "plugins" $ do
1321+pluginTests = testSessionWait "plugins" $ do
1481 let content =
1322 let content =
1482 T.unlines
1323 T.unlines
1483 [ "{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}"
1324 [ "{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}"
@@ -1491,7 +1332,7 @@ pluginTests = (`xfail8101` "known broken (#556)")
1491 , "foo :: Int -> Int -> Int"
1332 , "foo :: Int -> Int -> Int"
1492 , "foo a b = a + c"
1333 , "foo a b = a + c"
1494− _ <- createDoc "Testing.hs" "haskell" content
1335+ _ <- openDoc' "Testing.hs" "haskell" content
1495 expectDiagnostics
1336 expectDiagnostics
1496 [ ( "Testing.hs",
1337 [ ( "Testing.hs",
1497 [(DsError, (8, 14), "Variable not in scope: c")]
1338 [(DsError, (8, 14), "Variable not in scope: c")]
@@ -1518,7 +1359,7 @@ cppTests =
1518 run $ expectError content (2, 1)
1359 run $ expectError content (2, 1)
1520 , testSessionWait "cpp-ghcide" $ do
1361 , testSessionWait "cpp-ghcide" $ do
1521− _ <- createDoc "A.hs" "haskell" $ T.unlines
1362+ _ <- openDoc' "A.hs" "haskell" $ T.unlines
1522 ["{-# LANGUAGE CPP #-}"
1363 ["{-# LANGUAGE CPP #-}"
1523 ,"main ="
1364 ,"main ="
1524 ,"#ifdef __GHCIDE__"
1365 ,"#ifdef __GHCIDE__"
@@ -1532,7 +1373,7 @@ cppTests =
1533 expectError :: T.Text -> Cursor -> Session ()
1374 expectError :: T.Text -> Cursor -> Session ()
1534 expectError content cursor = do
1375 expectError content cursor = do
1535− _ <- createDoc "Testing.hs" "haskell" content
1376+ _ <- openDoc' "Testing.hs" "haskell" content
1536 expectDiagnostics
1377 expectDiagnostics
1537 [ ( "Testing.hs",
1378 [ ( "Testing.hs",
1538 [(DsError, cursor, "error: unterminated")]
1379 [(DsError, cursor, "error: unterminated")]
@@ -1548,43 +1389,13 @@ preprocessorTests = testSessionWait "preprocessor" $ do
1548 , "module Testing where"
1389 , "module Testing where"
1549 , "y = x + z" -- plugin replaces x with y, making this have only one diagnostic
1390 , "y = x + z" -- plugin replaces x with y, making this have only one diagnostic
1551− _ <- createDoc "Testing.hs" "haskell" content
1392+ _ <- openDoc' "Testing.hs" "haskell" content
1552 expectDiagnostics
1393 expectDiagnostics
1553 [ ( "Testing.hs",
1394 [ ( "Testing.hs",
1554 [(DsError, (2, 8), "Variable not in scope: z")]
1395 [(DsError, (2, 8), "Variable not in scope: z")]
1559−safeTests :: TestTree
1563− [ -- Test for https://github.com/digital-asset/ghcide/issues/424
1564− testSessionWait "load" $ do
1567− ["{-# LANGUAGE Trustworthy #-}"
1569− ,"import System.IO.Unsafe"
1570− ,"import System.IO"
1571− ,"trustWorthyId :: a -> a"
1572− ,"trustWorthyId i = unsafePerformIO $ do"
1573− ," putStrLn \"I'm safe\""
1577− ["{-# LANGUAGE Safe #-}"
1580− ,"safeId :: a -> a"
1581− ,"safeId = trustWorthyId"
1584− _ <- createDoc "A.hs" "haskell" sourceA
1585− _ <- createDoc "B.hs" "haskell" sourceB
1586− expectNoMoreDiagnostics 1 ]
1588thTests :: TestTree
1399thTests :: TestTree
1589thTests =
1400thTests =
1590 testGroup
1401 testGroup
@@ -1610,8 +1421,8 @@ thTests =
1610 "b :: Integer",
1421 "b :: Integer",
1611 "b = $(litE $ IntegerL $ a) + n"
1422 "b = $(litE $ IntegerL $ a) + n"
1613− _ <- createDoc "A.hs" "haskell" sourceA
1424+ _ <- openDoc' "A.hs" "haskell" sourceA
1614− _ <- createDoc "B.hs" "haskell" sourceB
1425+ _ <- openDoc' "B.hs" "haskell" sourceB
1615 expectDiagnostics [ ( "B.hs", [(DsError, (6, 29), "Variable not in scope: n")] ) ]
1426 expectDiagnostics [ ( "B.hs", [(DsError, (6, 29), "Variable not in scope: n")] ) ]
1616 , testSessionWait "newtype-closure" $ do
1427 , testSessionWait "newtype-closure" $ do
1617 let sourceA =
1428 let sourceA =
@@ -1631,8 +1442,8 @@ thTests =
1631 ,"import A"
1442 ,"import A"
1632 ,"b :: Int"
1443 ,"b :: Int"
1633 ,"b = $( a )" ]
1444 ,"b = $( a )" ]
1634− _ <- createDoc "A.hs" "haskell" sourceA
1445+ _ <- openDoc' "A.hs" "haskell" sourceA
1635− _ <- createDoc "B.hs" "haskell" sourceB
1446+ _ <- openDoc' "B.hs" "haskell" sourceB
1636 return ()
1447 return ()
@@ -1641,7 +1452,7 @@ completionTests
1641 = testGroup "completion"
1452 = testGroup "completion"
1642 [ testSessionWait "variable" $ do
1453 [ testSessionWait "variable" $ do
1643 let source = T.unlines ["module A where", "f = hea"]
1454 let source = T.unlines ["module A where", "f = hea"]
1644− docId <- createDoc "A.hs" "haskell" source
1455+ docId <- openDoc' "A.hs" "haskell" source
1645 compls <- getCompletions docId (Position 1 7)
1456 compls <- getCompletions docId (Position 1 7)
1646 liftIO $ map dropDocs compls @?=
1457 liftIO $ map dropDocs compls @?=
1647 [complItem "head" (Just CiFunction) (Just "[a] -> a")]
1458 [complItem "head" (Just CiFunction) (Just "[a] -> a")]
@@ -1653,7 +1464,7 @@ completionTests
1654 , testSessionWait "constructor" $ do
1465 , testSessionWait "constructor" $ do
1655 let source = T.unlines ["module A where", "f = Tru"]
1466 let source = T.unlines ["module A where", "f = Tru"]
1656− docId <- createDoc "A.hs" "haskell" source
1467+ docId <- openDoc' "A.hs" "haskell" source
1657 compls <- getCompletions docId (Position 1 7)
1468 compls <- getCompletions docId (Position 1 7)
1658 liftIO $ map dropDocs compls @?=
1469 liftIO $ map dropDocs compls @?=
1659 [ complItem "True" (Just CiConstructor) (Just "Bool")
1470 [ complItem "True" (Just CiConstructor) (Just "Bool")
@@ -1665,7 +1476,7 @@ completionTests
1666 , testSessionWait "type" $ do
1477 , testSessionWait "type" $ do
1667 let source = T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: ()", "f = ()"]
1478 let source = T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: ()", "f = ()"]
1668− docId <- createDoc "A.hs" "haskell" source
1479+ docId <- openDoc' "A.hs" "haskell" source
1669 expectDiagnostics [ ("A.hs", [(DsWarning, (3,0), "not used")]) ]
1480 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"]]
1481 changeDoc docId [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: Bo", "f = True"]]
1671 compls <- getCompletions docId (Position 2 7)
1482 compls <- getCompletions docId (Position 2 7)
@@ -1682,7 +1493,7 @@ completionTests
1682 checkDocText "Bool" boolDocs [ "Defined in 'Prelude'" ]
1493 checkDocText "Bool" boolDocs [ "Defined in 'Prelude'" ]
1683 , testSessionWait "qualified" $ do
1494 , testSessionWait "qualified" $ do
1684 let source = T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = ()"]
1495 let source = T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = ()"]
1685− docId <- createDoc "A.hs" "haskell" source
1496+ docId <- openDoc' "A.hs" "haskell" source
1686 expectDiagnostics [ ("A.hs", [(DsWarning, (2, 0), "not used")]) ]
1497 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"]]
1498 changeDoc docId [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = Prelude.hea"]]
1688 compls <- getCompletions docId (Position 2 15)
1499 compls <- getCompletions docId (Position 2 15)
@@ -1696,30 +1507,9 @@ completionTests
1697 , testSessionWait "keyword" $ do
1508 , testSessionWait "keyword" $ do
1698 let source = T.unlines ["module A where", "f = newty"]
1509 let source = T.unlines ["module A where", "f = newty"]
1699− docId <- createDoc "A.hs" "haskell" source
1510+ docId <- openDoc' "A.hs" "haskell" source
1700 compls <- getCompletions docId (Position 1 9)
1511 compls <- getCompletions docId (Position 1 9)
1701 liftIO $ compls @?= [keywordItem "newtype"]
1512 liftIO $ compls @?= [keywordItem "newtype"]
1702− , testSessionWait "type context" $ do
1703− let source = T.unlines
1704− [ "{-# OPTIONS_GHC -Wunused-binds #-}"
1705− , "module A () where"
1708− docId <- createDoc "A.hs" "haskell" source
1709− expectDiagnostics [("A.hs", [(DsWarning, (2, 0), "not used")])]
1711− [ TextDocumentContentChangeEvent Nothing Nothing $ T.unlines
1712− [ "{-# OPTIONS_GHC -Wunused-binds #-}"
1713− , "module A () where"
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 "*")]
1725 dropDocs :: CompletionItem -> CompletionItem
1515 dropDocs :: CompletionItem -> CompletionItem
@@ -1727,7 +1517,6 @@ completionTests
1727 complItem label kind ty = CompletionItem
1517 complItem label kind ty = CompletionItem
1728 { _label = label
1518 { _label = label
1729 , _kind = kind
1519 , _kind = kind
1731 , _detail = (":: " <>) <$> ty
1520 , _detail = (":: " <>) <$> ty
1732 , _documentation = Nothing
1521 , _documentation = Nothing
1733 , _deprecated = Nothing
1522 , _deprecated = Nothing
@@ -1745,7 +1534,6 @@ completionTests
1745 keywordItem label = CompletionItem
1534 keywordItem label = CompletionItem
1746 { _label = label
1535 { _label = label
1747 , _kind = Just CiKeyword
1536 , _kind = Just CiKeyword
1749 , _detail = Nothing
1537 , _detail = Nothing
1750 , _documentation = Nothing
1538 , _documentation = Nothing
1751 , _deprecated = Nothing
1539 , _deprecated = Nothing
@@ -1773,7 +1561,7 @@ outlineTests = testGroup
1773 "outline"
1561 "outline"
1774 [ testSessionWait "type class" $ do
1562 [ testSessionWait "type class" $ do
1775 let source = T.unlines ["module A where", "class A a where a :: a -> Bool"]
1563 let source = T.unlines ["module A where", "class A a where a :: a -> Bool"]
1776− docId <- createDoc "A.hs" "haskell" source
1564+ docId <- openDoc' "A.hs" "haskell" source
1777 symbols <- getDocumentSymbols docId
1565 symbols <- getDocumentSymbols docId
1778 liftIO $ symbols @?= Left
1566 liftIO $ symbols @?= Left
1779 [ moduleSymbol
1567 [ moduleSymbol
@@ -1786,7 +1574,7 @@ outlineTests = testGroup
1787 , testSessionWait "type class instance " $ do
1575 , testSessionWait "type class instance " $ do
1788 let source = T.unlines ["class A a where", "instance A () where"]
1576 let source = T.unlines ["class A a where", "instance A () where"]
1789− docId <- createDoc "A.hs" "haskell" source
1577+ docId <- openDoc' "A.hs" "haskell" source
1790 symbols <- getDocumentSymbols docId
1578 symbols <- getDocumentSymbols docId
1791 liftIO $ symbols @?= Left
1579 liftIO $ symbols @?= Left
1792 [ classSymbol "A a" (R 0 0 0 15) []
1580 [ classSymbol "A a" (R 0 0 0 15) []
@@ -1794,7 +1582,7 @@ outlineTests = testGroup
1795 , testSessionWait "type family" $ do
1583 , testSessionWait "type family" $ do
1796 let source = T.unlines ["{-# language TypeFamilies #-}", "type family A"]
1584 let source = T.unlines ["{-# language TypeFamilies #-}", "type family A"]
1797− docId <- createDoc "A.hs" "haskell" source
1585+ docId <- openDoc' "A.hs" "haskell" source
1798 symbols <- getDocumentSymbols docId
1586 symbols <- getDocumentSymbols docId
1799 liftIO $ symbols @?= Left [docSymbolD "A" "type family" SkClass (R 1 0 1 13)]
1587 liftIO $ symbols @?= Left [docSymbolD "A" "type family" SkClass (R 1 0 1 13)]
1800 , testSessionWait "type family instance " $ do
1588 , testSessionWait "type family instance " $ do
@@ -1803,7 +1591,7 @@ outlineTests = testGroup
1803 , "type family A a"
1591 , "type family A a"
1804 , "type instance A () = ()"
1592 , "type instance A () = ()"
1806− docId <- createDoc "A.hs" "haskell" source
1594+ docId <- openDoc' "A.hs" "haskell" source
1807 symbols <- getDocumentSymbols docId
1595 symbols <- getDocumentSymbols docId
1808 liftIO $ symbols @?= Left
1596 liftIO $ symbols @?= Left
1809 [ docSymbolD "A a" "type family" SkClass (R 1 0 1 15)
1597 [ docSymbolD "A a" "type family" SkClass (R 1 0 1 15)
@@ -1811,7 +1599,7 @@ outlineTests = testGroup
1812 , testSessionWait "data family" $ do
1600 , testSessionWait "data family" $ do
1813 let source = T.unlines ["{-# language TypeFamilies #-}", "data family A"]
1601 let source = T.unlines ["{-# language TypeFamilies #-}", "data family A"]
1814− docId <- createDoc "A.hs" "haskell" source
1602+ docId <- openDoc' "A.hs" "haskell" source
1815 symbols <- getDocumentSymbols docId
1603 symbols <- getDocumentSymbols docId
1816 liftIO $ symbols @?= Left [docSymbolD "A" "data family" SkClass (R 1 0 1 11)]
1604 liftIO $ symbols @?= Left [docSymbolD "A" "data family" SkClass (R 1 0 1 11)]
1817 , testSessionWait "data family instance " $ do
1605 , testSessionWait "data family instance " $ do
@@ -1820,7 +1608,7 @@ outlineTests = testGroup
1820 , "data family A a"
1608 , "data family A a"
1821 , "data instance A () = A ()"
1609 , "data instance A () = A ()"
1823− docId <- createDoc "A.hs" "haskell" source
1611+ docId <- openDoc' "A.hs" "haskell" source
1824 symbols <- getDocumentSymbols docId
1612 symbols <- getDocumentSymbols docId
1825 liftIO $ symbols @?= Left
1613 liftIO $ symbols @?= Left
1826 [ docSymbolD "A a" "data family" SkClass (R 1 0 1 11)
1614 [ docSymbolD "A a" "data family" SkClass (R 1 0 1 11)
@@ -1828,36 +1616,36 @@ outlineTests = testGroup
1829 , testSessionWait "constant" $ do
1617 , testSessionWait "constant" $ do
1830 let source = T.unlines ["a = ()"]
1618 let source = T.unlines ["a = ()"]
1831− docId <- createDoc "A.hs" "haskell" source
1619+ docId <- openDoc' "A.hs" "haskell" source
1832 symbols <- getDocumentSymbols docId
1620 symbols <- getDocumentSymbols docId
1833 liftIO $ symbols @?= Left
1621 liftIO $ symbols @?= Left
1834 [docSymbol "a" SkFunction (R 0 0 0 6)]
1622 [docSymbol "a" SkFunction (R 0 0 0 6)]
1835 , testSessionWait "pattern" $ do
1623 , testSessionWait "pattern" $ do
1836 let source = T.unlines ["Just foo = Just 21"]
1624 let source = T.unlines ["Just foo = Just 21"]
1837− docId <- createDoc "A.hs" "haskell" source
1625+ docId <- openDoc' "A.hs" "haskell" source
1838 symbols <- getDocumentSymbols docId
1626 symbols <- getDocumentSymbols docId
1839 liftIO $ symbols @?= Left
1627 liftIO $ symbols @?= Left
1840 [docSymbol "Just foo" SkFunction (R 0 0 0 18)]
1628 [docSymbol "Just foo" SkFunction (R 0 0 0 18)]
1841 , testSessionWait "pattern with type signature" $ do
1629 , testSessionWait "pattern with type signature" $ do
1842 let source = T.unlines ["{-# language ScopedTypeVariables #-}", "a :: () = ()"]
1630 let source = T.unlines ["{-# language ScopedTypeVariables #-}", "a :: () = ()"]
1843− docId <- createDoc "A.hs" "haskell" source
1631+ docId <- openDoc' "A.hs" "haskell" source
1844 symbols <- getDocumentSymbols docId
1632 symbols <- getDocumentSymbols docId
1845 liftIO $ symbols @?= Left
1633 liftIO $ symbols @?= Left
1846 [docSymbol "a :: ()" SkFunction (R 1 0 1 12)]
1634 [docSymbol "a :: ()" SkFunction (R 1 0 1 12)]
1847 , testSessionWait "function" $ do
1635 , testSessionWait "function" $ do
1848 let source = T.unlines ["a x = ()"]
1636 let source = T.unlines ["a x = ()"]
1849− docId <- createDoc "A.hs" "haskell" source
1637+ docId <- openDoc' "A.hs" "haskell" source
1850 symbols <- getDocumentSymbols docId
1638 symbols <- getDocumentSymbols docId
1851 liftIO $ symbols @?= Left [docSymbol "a" SkFunction (R 0 0 0 8)]
1639 liftIO $ symbols @?= Left [docSymbol "a" SkFunction (R 0 0 0 8)]
1852 , testSessionWait "type synonym" $ do
1640 , testSessionWait "type synonym" $ do
1853 let source = T.unlines ["type A = Bool"]
1641 let source = T.unlines ["type A = Bool"]
1854− docId <- createDoc "A.hs" "haskell" source
1642+ docId <- openDoc' "A.hs" "haskell" source
1855 symbols <- getDocumentSymbols docId
1643 symbols <- getDocumentSymbols docId
1856 liftIO $ symbols @?= Left
1644 liftIO $ symbols @?= Left
1857 [docSymbol' "A" SkTypeParameter (R 0 0 0 13) (R 0 5 0 6)]
1645 [docSymbol' "A" SkTypeParameter (R 0 0 0 13) (R 0 5 0 6)]
1858 , testSessionWait "datatype" $ do
1646 , testSessionWait "datatype" $ do
1859 let source = T.unlines ["data A = C"]
1647 let source = T.unlines ["data A = C"]
1860− docId <- createDoc "A.hs" "haskell" source
1648+ docId <- openDoc' "A.hs" "haskell" source
1861 symbols <- getDocumentSymbols docId
1649 symbols <- getDocumentSymbols docId
1862 liftIO $ symbols @?= Left
1650 liftIO $ symbols @?= Left
1863 [ docSymbolWithChildren "A"
1651 [ docSymbolWithChildren "A"
@@ -1865,47 +1653,18 @@ outlineTests = testGroup
1865 (R 0 0 0 10)
1653 (R 0 0 0 10)
1866 [docSymbol "C" SkConstructor (R 0 9 0 10)]
1654 [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
1656 , testSessionWait "import" $ do
1881 let source = T.unlines ["import Data.Maybe"]
1657 let source = T.unlines ["import Data.Maybe"]
1882− docId <- createDoc "A.hs" "haskell" source
1658+ docId <- openDoc' "A.hs" "haskell" source
1883 symbols <- getDocumentSymbols docId
1659 symbols <- getDocumentSymbols docId
1884 liftIO $ symbols @?= Left
1660 liftIO $ symbols @?= Left
1885− [docSymbolWithChildren "imports"
1888− [ docSymbol "import Data.Maybe" SkModule (R 0 0 0 17)
1661+ [docSymbol "import Data.Maybe" SkModule (R 0 0 0 17)]
1891− , testSessionWait "multiple import" $ do
1892− let source = T.unlines ["", "import Data.Maybe", "", "import Control.Exception", ""]
1893− docId <- createDoc "A.hs" "haskell" source
1894− symbols <- getDocumentSymbols docId
1895− liftIO $ symbols @?= Left
1896− [docSymbolWithChildren "imports"
1899− [ docSymbol "import Data.Maybe" SkModule (R 1 0 1 17)
1900− , docSymbol "import Control.Exception" SkModule (R 3 0 3 24)
1903 , testSessionWait "foreign import" $ do
1662 , testSessionWait "foreign import" $ do
1904 let source = T.unlines
1663 let source = T.unlines
1905 [ "{-# language ForeignFunctionInterface #-}"
1664 [ "{-# language ForeignFunctionInterface #-}"
1906 , "foreign import ccall \"a\" a :: Int"
1665 , "foreign import ccall \"a\" a :: Int"
1908− docId <- createDoc "A.hs" "haskell" source
1667+ docId <- openDoc' "A.hs" "haskell" source
1909 symbols <- getDocumentSymbols docId
1668 symbols <- getDocumentSymbols docId
1910 liftIO $ symbols @?= Left [docSymbolD "a" "import" SkObject (R 1 0 1 33)]
1669 liftIO $ symbols @?= Left [docSymbolD "a" "import" SkObject (R 1 0 1 33)]
1911 , testSessionWait "foreign export" $ do
1670 , testSessionWait "foreign export" $ do
@@ -1913,7 +1672,7 @@ outlineTests = testGroup
1913 [ "{-# language ForeignFunctionInterface #-}"
1672 [ "{-# language ForeignFunctionInterface #-}"
1914 , "foreign export ccall odd :: Int -> Bool"
1673 , "foreign export ccall odd :: Int -> Bool"
1916− docId <- createDoc "A.hs" "haskell" source
1675+ docId <- openDoc' "A.hs" "haskell" source
1917 symbols <- getDocumentSymbols docId
1676 symbols <- getDocumentSymbols docId
1918 liftIO $ symbols @?= Left [docSymbolD "odd" "export" SkObject (R 1 0 1 39)]
1677 liftIO $ symbols @?= Left [docSymbolD "odd" "export" SkObject (R 1 0 1 39)]
@@ -1926,8 +1685,6 @@ outlineTests = testGroup
1926 DocumentSymbol name (Just detail) kind Nothing loc loc Nothing
1685 DocumentSymbol name (Just detail) kind Nothing loc loc Nothing
1927 docSymbolWithChildren name kind loc cc =
1686 docSymbolWithChildren name kind loc cc =
1928 DocumentSymbol name Nothing kind Nothing loc loc (Just $ List cc)
1687 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
1688 moduleSymbol name loc cc = DocumentSymbol name
@@ -1949,16 +1706,8 @@ pattern R x y x' y' = Range (Position x y) (Position x' y')
1949xfail :: TestTree -> String -> TestTree
1706xfail :: TestTree -> String -> TestTree
1950xfail = flip expectFailBecause
1707xfail = flip expectFailBecause
1952−xfail8101 :: TestTree -> String -> TestTree
1953−#if MIN_GHC_API_VERSION(8,10,0)
1954−xfail8101 = flip expectFailBecause
1959data Expect
1709data Expect
1960 = ExpectRange Range -- Both gotoDef and hover should report this range
1710 = ExpectRange Range -- Both gotoDef and hover should report this range
1961− | ExpectLocation Location
1962-- | ExpectDefRange Range -- Only gotoDef should report this range
1711-- | ExpectDefRange Range -- Only gotoDef should report this range
1963 | ExpectHoverRange Range -- Only hover should report this range
1712 | ExpectHoverRange Range -- Only hover should report this range
1964 | ExpectHoverText [T.Text] -- the hover message must contain these snippets
1713 | ExpectHoverText [T.Text] -- the hover message must contain these snippets
@@ -1971,9 +1720,6 @@ data Expect
1971mkR :: Int -> Int -> Int -> Int -> Expect
1720mkR :: Int -> Int -> Int -> Int -> Expect
1972mkR startLine startColumn endLine endColumn = ExpectRange $ mkRange startLine startColumn endLine endColumn
1721mkR startLine startColumn endLine endColumn = ExpectRange $ mkRange startLine startColumn endLine endColumn
1974−mkL :: Uri -> Int -> Int -> Int -> Int -> Expect
1975−mkL uri startLine startColumn endLine endColumn = ExpectLocation $ Location uri $ mkRange startLine startColumn endLine endColumn
1977haddockTests :: TestTree
1723haddockTests :: TestTree
1978haddockTests
1724haddockTests
1979 = testGroup "haddock"
1725 = testGroup "haddock"
@@ -2029,129 +1775,6 @@ haddockTests
2030 checkHaddock s txt = spanDocToMarkdownForTest s @?= txt
1776 checkHaddock s txt = spanDocToMarkdownForTest s @?= txt
2032−cradleTests :: TestTree
2033−cradleTests = testGroup "cradle"
2034− [testGroup "dependencies" [sessionDepsArePickedUp]
2035− ,testGroup "loading" [loadCradleOnlyonce]
2036− ,testGroup "multi" [simpleMultiTest, simpleMultiTest2]
2039−loadCradleOnlyonce :: TestTree
2040−loadCradleOnlyonce = testGroup "load cradle only once"
2041− [ testSession' "implicit" implicit
2042− , testSession' "direct" direct
2046− liftIO $ writeFileUTF8 (dir </> "hie.yaml")
2047− "cradle: {direct: {arguments: []}}"
2049− implicit dir = test dir
2051− doc <- createDoc "B.hs" "haskell" "module B where\nimport Data.Foo"
2052− msgs <- someTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))
2053− liftIO $ length msgs @?= 1
2054− changeDoc doc [TextDocumentContentChangeEvent Nothing Nothing "module B where\nimport Data.Maybe"]
2055− msgs <- manyTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))
2056− liftIO $ length msgs @?= 0
2057− _ <- createDoc "A.hs" "haskell" "module A where\nimport LoadCradleBar"
2058− msgs <- manyTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))
2059− 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", [])]
2098−cradleLoadedMessage :: Session FromServerMessage
2099−cradleLoadedMessage = satisfy $ \case
2100− NotCustomServer (NotificationMessage _ (CustomServerMethod m) _) -> m == cradleLoadedMethod
2103−cradleLoadedMethod :: T.Text
2104−cradleLoadedMethod = "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
1779sessionDepsArePickedUp :: TestTree
2157sessionDepsArePickedUp = testSession'
1780sessionDepsArePickedUp = testSession'
@@ -2162,7 +1785,7 @@ sessionDepsArePickedUp = testSession'
2162 (dir </> "hie.yaml")
1785 (dir </> "hie.yaml")
2163 "cradle: {direct: {arguments: []}}"
1786 "cradle: {direct: {arguments: []}}"
2164 -- Open without OverloadedStrings and expect an error.
1787 -- Open without OverloadedStrings and expect an error.
2165− doc <- createDoc "Foo.hs" "haskell" fooContent
1788+ doc <- openDoc' "Foo.hs" "haskell" fooContent
2166 expectDiagnostics
1789 expectDiagnostics
2167 [("Foo.hs", [(DsError, (3, 6), "Couldn't match expected type")])]
1790 [("Foo.hs", [(DsError, (3, 6), "Couldn't match expected type")])]
2168 -- Update hie.yaml to enable OverloadedStrings.
1791 -- Update hie.yaml to enable OverloadedStrings.
@@ -2197,9 +1820,6 @@ sessionDepsArePickedUp = testSession'
2197testSession :: String -> Session () -> TestTree
1820testSession :: String -> Session () -> TestTree
2198testSession name = testCase name . run
1821testSession name = testCase name . run
2200−testSessionWithExtraFiles :: FilePath -> String -> (FilePath -> Session ()) -> TestTree
2201−testSessionWithExtraFiles prefix name = testCase name . runWithExtraFiles prefix
2203testSession' :: String -> (FilePath -> Session ()) -> TestTree
1823testSession' :: String -> (FilePath -> Session ()) -> TestTree
2204testSession' name = testCase name . run'
1824testSession' name = testCase name . run'
@@ -2213,20 +1833,11 @@ testSessionWait name = testSession name .
2213 -- Experimentally, 0.5s seems to be long enough to wait for any final diagnostics to appear.
1833 -- Experimentally, 0.5s seems to be long enough to wait for any final diagnostics to appear.
2214 ( >> expectNoMoreDiagnostics 0.5)
1834 ( >> expectNoMoreDiagnostics 0.5)
2216−pickActionWithTitle :: T.Text -> [CAResult] -> IO CodeAction
1836+pickActionWithTitle :: T.Text -> [CAResult] -> CodeAction
2217−pickActionWithTitle title actions = do
1837+pickActionWithTitle title actions = head
2218− assertBool ("Found no matching actions: " <> show titles) (not $ null matches)
2219− return $ head matches
2223− | CACodeAction CodeAction { _title = actionTitle } <- actions
2226− [ action
1838+ [ action
2227− | CACodeAction action@CodeAction { _title = actionTitle } <- actions
1839+ | CACodeAction action@CodeAction{ _title = actionTitle } <- actions
2228− , title == actionTitle
1840+ , title == actionTitle ]
2231mkRange :: Int -> Int -> Int -> Int -> Range
1842mkRange :: Int -> Int -> Int -> Int -> Range
2232mkRange a b c d = Range (Position a b) (Position c d)
1843mkRange a b c d = Range (Position a b) (Position c d)
@@ -2234,19 +1845,6 @@ mkRange a b c d = Range (Position a b) (Position c d)
2234run :: Session a -> IO a
1845run :: Session a -> IO a
2235run s = withTempDir $ \dir -> runInDir dir s
1846run 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
1848run' :: (FilePath -> Session a) -> IO a
2251run' s = withTempDir $ \dir -> runInDir dir (s dir)
1849run' s = withTempDir $ \dir -> runInDir dir (s dir)
@@ -2258,8 +1856,7 @@ runInDir dir s = do
2258 -- since the package import test creates "Data/List.hs", which otherwise has no physical home
1856 -- since the package import test creates "Data/List.hs", which otherwise has no physical home
2259 createDirectoryIfMissing True $ dir ++ "/Data"
1857 createDirectoryIfMissing True $ dir ++ "/Data"
2262− let cmd = unwords [ghcideExe, "--lsp", "--test", "--cwd", dir]
1859+ let cmd = unwords [ghcideExe, "--lsp", "--cwd", dir]
2263 -- HIE calls getXgdDirectory which assumes that HOME is set.
1860 -- HIE calls getXgdDirectory which assumes that HOME is set.
2264 -- Only sets HOME if it wasn't already set.
1861 -- Only sets HOME if it wasn't already set.
2265 setEnv "HOME" "/homeless-shelter" False
1862 setEnv "HOME" "/homeless-shelter" False
@@ -2276,7 +1873,7 @@ runInDir dir s = do
2276openTestDataDoc :: FilePath -> Session TextDocumentIdentifier
1873openTestDataDoc :: FilePath -> Session TextDocumentIdentifier
2277openTestDataDoc path = do
1874openTestDataDoc path = do
2278 source <- liftIO $ readFileUtf8 $ "test/data" </> path
1875 source <- liftIO $ readFileUtf8 $ "test/data" </> path
2279− createDoc path "haskell" source
1876+ openDoc' path "haskell" source
2281findCodeActions :: TextDocumentIdentifier -> Range -> [T.Text] -> Session [CodeAction]
1878findCodeActions :: TextDocumentIdentifier -> Range -> [T.Text] -> Session [CodeAction]
2282findCodeActions doc range expectedTitles = do
1879findCodeActions doc range expectedTitles = do
@@ -2291,7 +1888,7 @@ findCodeActions doc range expectedTitles = do
2291 [ actionTitle
1888 [ actionTitle
2292 | CACodeAction CodeAction { _title = actionTitle } <- actions
1889 | CACodeAction CodeAction { _title = actionTitle } <- actions
2294− ++ " is not a superset of "
1891+ ++ "is not a superset of "
2295 ++ show expectedTitles
1892 ++ show expectedTitles
2296 liftIO $ case matches of
1893 liftIO $ case matches of
2297 Nothing -> assertFailure msg
1894 Nothing -> assertFailure msg
@@ -2304,19 +1901,24 @@ findCodeAction doc range t = head <$> findCodeActions doc range [t]
2304unitTests :: TestTree
1901unitTests :: TestTree
2305unitTests = do
1902unitTests = do
2306 testGroup "Unit"
1903 testGroup "Unit"
2307− [ testCase "empty file path does NOT work with the empty String literal" $
1904+ [ testCase "empty file path" $
2308− uriToFilePath' (fromNormalizedUri $ filePathToUri' "") @?= Just "."
1905+ 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:"
2315− , testCase "from empty path URI" $ do
2316− let uri = Uri "file://"
2317− uriToFilePath' uri @?= Just ""
1908+-- | Wrapper around 'LSPTest.openDoc'' that sends file creation events
1909+openDoc' :: FilePath -> String -> T.Text -> Session TextDocumentIdentifier
1910+openDoc' fp name contents = do
1911+ res@(TextDocumentIdentifier uri) <- LSPTest.openDoc' fp name contents
1912+ -- Needed as ghcide sets up and relies on WatchedFiles but lsp-test does not track them
1913+ sendNotification WorkspaceDidChangeWatchedFiles (DidChangeWatchedFilesParams $ List [FileEvent uri FcCreated])
1916+-- | Version of 'LSPTest.openDoc'' that does not send WatchedFiles events for files outside the workspace
1917+openDoc'' :: FilePath -> String -> T.Text -> Session TextDocumentIdentifier
1918+-- At the moment this is just LSPTest.openDoc' but it may change in the future
1919+-- when/if lsp-test implements WatchedFiles
1920+openDoc'' = LSPTest.openDoc'
2320positionMappingTests :: TestTree
1922positionMappingTests :: TestTree
2321positionMappingTests =
1923positionMappingTests =
2322 testGroup "position mapping"
1924 testGroup "position mapping"
@@ -2485,12 +2087,3 @@ nthLine i r
2485 | i == 0 && Rope.rows r == 0 = r
2087 | i == 0 && Rope.rows r == 0 = r
2486 | i >= Rope.rows r = error $ "Row number out of bounds: " <> show i <> "/" <> show (Rope.rows r)
2088 | 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
2089 | 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]
2490−getWatchedFilesSubscriptionsUntil = do
2491− msgs <- manyTill (Just <$> message @RegisterCapabilityRequest <|> Nothing <$ anyMessage) (message @end)
2494− | Just RequestMessage{_params = RegistrationParams (List regs)} <- msgs
2495− , Registration _id WorkspaceDidChangeWatchedFiles args <- regs