@@ -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,74 +9,51 @@
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
20−import Data.Rope.UTF16 (Rope)
21−import qualified Data.Rope.UTF16 as Rope
22−import Development.IDE.Core.PositionMapping (fromCurrent, toCurrent)
23import Development.IDE.GHC.Util
18import Development.IDE.GHC.Util
24import qualified Data.Text as T
19import qualified Data.Text as T
26−import Development.IDE.Spans.Common
27import Development.IDE.Test
20import Development.IDE.Test
28import Development.IDE.Test.Runfiles
21import Development.IDE.Test.Runfiles
29import Development.IDE.Types.Location
22import Development.IDE.Types.Location
30−import Development.Shake (getDirectoryFilesIO)
23+import qualified Language.Haskell.LSP.Test as LSPTest
31−import Language.Haskell.LSP.Test
24+import Language.Haskell.LSP.Test hiding (openDoc')
32−import Language.Haskell.LSP.Messages
33import Language.Haskell.LSP.Types
25import Language.Haskell.LSP.Types
34import Language.Haskell.LSP.Types.Capabilities
26import Language.Haskell.LSP.Types.Capabilities
35−import qualified Language.Haskell.LSP.Types.Lens as Lsp (diagnostics, params, message)
36−import Language.Haskell.LSP.VFS (applyChange)
38−import System.Environment.Blank (getEnv, setEnv, unsetEnv)
27+import System.Environment.Blank (setEnv)
39import System.FilePath
28import System.FilePath
40import System.IO.Extra
29import System.IO.Extra
41import System.Directory
30import System.Directory
42−import Test.QuickCheck
43−import Test.QuickCheck.Instances ()
44import Test.Tasty
31import Test.Tasty
45−import Test.Tasty.ExpectedFailure
46−import Test.Tasty.Ingredients.Rerun
47import Test.Tasty.HUnit
32import Test.Tasty.HUnit
48−import Test.Tasty.QuickCheck
33+import Test.Tasty.ExpectedFailure
49import Data.Maybe
34import Data.Maybe
51main :: IO ()
36main :: IO ()
53− -- We mess with env vars so run single-threaded.
54− setEnv "TASTY_NUM_THREADS" "1" True
55− defaultMainWithRerun $ testGroup "HIE"
37+main = defaultMain $ testGroup "HIE"
56− [ testSession "open close" $ do
38+ [ testSession "open close" $ do
57− doc <- createDoc "Testing.hs" "haskell" ""
39+ doc <- openDoc' "Testing.hs" "haskell" ""
58− void (skipManyTill anyMessage message :: Session WorkDoneProgressCreateRequest)
40+ void (message :: Session WorkDoneProgressCreateRequest)
59− void (skipManyTill anyMessage message :: Session WorkDoneProgressBeginNotification)
41+ void (message :: Session WorkDoneProgressBeginNotification)
60− closeDoc doc
42+ closeDoc doc
61− void (skipManyTill anyMessage message :: Session WorkDoneProgressEndNotification)
43+ void (message :: Session WorkDoneProgressEndNotification)
62− , initializeResponseTests
44+ , initializeResponseTests
63− , completionTests
45+ , completionTests
64− , cppTests
46+ , cppTests
65− , diagnosticTests
47+ , diagnosticTests
66− , codeActionTests
48+ , codeActionTests
67− , codeLensesTests
49+ , codeLensesTests
68− , outlineTests
50+ , outlineTests
69− , findDefinitionAndHoverTests
51+ , findDefinitionAndHoverTests
70− , pluginTests
52+ , pluginTests
71− , preprocessorTests
53+ , preprocessorTests
72− , thTests
54+ , thTests
74− , unitTests
55+ , unitTests
76− , positionMappingTests
82initializeResponseTests :: TestTree
58initializeResponseTests :: TestTree
83initializeResponseTests = withResource acquire release tests where
59initializeResponseTests = withResource acquire release tests where
@@ -112,8 +88,8 @@ initializeResponseTests = withResource acquire release tests where
112 , chk "NO doc link" _documentLinkProvider Nothing
88 , chk "NO doc link" _documentLinkProvider Nothing
113 , chk "NO color" _colorProvider (Just $ ColorOptionsStatic False)
89 , chk "NO color" _colorProvider (Just $ ColorOptionsStatic False)
114 , chk "NO folding range" _foldingRangeProvider (Just $ FoldingRangeOptionsStatic False)
90 , chk "NO folding range" _foldingRangeProvider (Just $ FoldingRangeOptionsStatic False)
115− , che " execute command" _executeCommandProvider (Just $ ExecuteCommandOptions $ List ["typesignature.add"])
91+ , chk " execute command" _executeCommandProvider (Just $ ExecuteCommandOptions $ List ["typesignature.add"])
116− , chk " workspace" _workspace (Just $ WorkspaceOptions (Just WorkspaceFolderOptions{_supported = Just True, _changeNotifications = Just ( WorkspaceFolderChangeNotificationsBool True )}))
92+ , chk "NO workspace" _workspace nothingWorkspace
117 , chk "NO experimental" _experimental Nothing
93 , chk "NO experimental" _experimental Nothing
@@ -124,21 +100,14 @@ initializeResponseTests = withResource acquire release tests where
124 , _willSaveWaitUntil = Nothing
100 , _willSaveWaitUntil = Nothing
125 , _save = Just (SaveOptions {_includeText = Nothing})}))
101 , _save = Just (SaveOptions {_includeText = Nothing})}))
103+ nothingWorkspace = Just (WorkspaceOptions {_workspaceFolders = Nothing})
127 chk :: (Eq a, Show a) => TestName -> (InitializeResponseCapabilitiesInner -> a) -> a -> TestTree
105 chk :: (Eq a, Show a) => TestName -> (InitializeResponseCapabilitiesInner -> a) -> a -> TestTree
128 chk title getActual expected =
106 chk title getActual expected =
129 testCase title $ getInitializeResponse >>= \ir -> expected @=? (getActual . innerCaps) ir
107 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
109 innerCaps :: InitializeResponse -> InitializeResponseCapabilitiesInner
141− innerCaps (ResponseMessage _ _ (Right (InitializeResponseCapabilities c))) = c
110+ innerCaps (ResponseMessage _ _ (Just (InitializeResponseCapabilities c)) _) = c
142 innerCaps _ = error "this test only expects inner capabilities"
111 innerCaps _ = error "this test only expects inner capabilities"
144 acquire :: IO InitializeResponse
113 acquire :: IO InitializeResponse
@@ -152,7 +121,7 @@ diagnosticTests :: TestTree
152diagnosticTests = testGroup "diagnostics"
121diagnosticTests = testGroup "diagnostics"
153 [ testSessionWait "fix syntax error" $ do
122 [ testSessionWait "fix syntax error" $ do
154 let content = T.unlines [ "module Testing wher" ]
123 let content = T.unlines [ "module Testing wher" ]
155− doc <- createDoc "Testing.hs" "haskell" content
124+ doc <- openDoc' "Testing.hs" "haskell" content
156 expectDiagnostics [("Testing.hs", [(DsError, (0, 15), "parse error")])]
125 expectDiagnostics [("Testing.hs", [(DsError, (0, 15), "parse error")])]
157 let change = TextDocumentContentChangeEvent
126 let change = TextDocumentContentChangeEvent
158 { _range = Just (Range (Position 0 15) (Position 0 19))
127 { _range = Just (Range (Position 0 15) (Position 0 19))
@@ -163,9 +132,9 @@ diagnosticTests = testGroup "diagnostics"
163 expectDiagnostics [("Testing.hs", [])]
132 expectDiagnostics [("Testing.hs", [])]
164 , testSessionWait "introduce syntax error" $ do
133 , testSessionWait "introduce syntax error" $ do
165 let content = T.unlines [ "module Testing where" ]
134 let content = T.unlines [ "module Testing where" ]
166− doc <- createDoc "Testing.hs" "haskell" content
135+ doc <- openDoc' "Testing.hs" "haskell" content
167− void $ skipManyTill anyMessage (message :: Session WorkDoneProgressCreateRequest)
136+ void (message :: Session WorkDoneProgressCreateRequest)
168− void $ skipManyTill anyMessage (message :: Session WorkDoneProgressBeginNotification)
137+ void (message :: Session WorkDoneProgressBeginNotification)
169 let change = TextDocumentContentChangeEvent
138 let change = TextDocumentContentChangeEvent
170 { _range = Just (Range (Position 0 15) (Position 0 18))
139 { _range = Just (Range (Position 0 15) (Position 0 18))
171 , _rangeLength = Nothing
140 , _rangeLength = Nothing
@@ -181,7 +150,7 @@ diagnosticTests = testGroup "diagnostics"
181 , "bar :: Int -> Int -> Int"
150 , "bar :: Int -> Int -> Int"
182 , "bar a b = cd + b"
151 , "bar a b = cd + b"
184− _ <- createDoc "Testing.hs" "haskell" content
153+ _ <- openDoc' "Testing.hs" "haskell" content
185 expectDiagnostics
154 expectDiagnostics
186 [ ( "Testing.hs"
155 [ ( "Testing.hs"
187 , [ (DsError, (2, 14), "Variable not in scope: ab")
156 , [ (DsError, (2, 14), "Variable not in scope: ab")
@@ -195,7 +164,7 @@ diagnosticTests = testGroup "diagnostics"
195 , "foo :: Int -> String -> Int"
164 , "foo :: Int -> String -> Int"
196 , "foo a b = a + b"
165 , "foo a b = a + b"
198− _ <- createDoc "Testing.hs" "haskell" content
167+ _ <- openDoc' "Testing.hs" "haskell" content
199 expectDiagnostics
168 expectDiagnostics
200 [ ( "Testing.hs"
169 [ ( "Testing.hs"
201 , [(DsError, (2, 14), "Couldn't match type '[Char]' with 'Int'")]
170 , [(DsError, (2, 14), "Couldn't match type '[Char]' with 'Int'")]
@@ -207,7 +176,7 @@ diagnosticTests = testGroup "diagnostics"
207 , "foo :: Int -> String"
176 , "foo :: Int -> String"
208 , "foo a = _ a"
177 , "foo a = _ a"
210− _ <- createDoc "Testing.hs" "haskell" content
179+ _ <- openDoc' "Testing.hs" "haskell" content
211 expectDiagnostics
180 expectDiagnostics
212 [ ( "Testing.hs"
181 [ ( "Testing.hs"
213 , [(DsError, (2, 8), "Found hole: _ :: Int -> String")]
182 , [(DsError, (2, 8), "Found hole: _ :: Int -> String")]
@@ -229,23 +198,24 @@ diagnosticTests = testGroup "diagnostics"
229 [ ("A.hs", [(DsError, (2,4), aMessage)])
198 [ ("A.hs", [(DsError, (2,4), aMessage)])
230 , ("B.hs", [(DsError, (3,4), bMessage)])]
199 , ("B.hs", [(DsError, (3,4), bMessage)])]
231 deferralTest title binding msg = testSessionWait title $ do
200 deferralTest title binding msg = testSessionWait title $ do
232− _ <- createDoc "A.hs" "haskell" $ sourceA binding
201+ _ <- openDoc' "A.hs" "haskell" $ sourceA binding
233− _ <- createDoc "B.hs" "haskell" sourceB
202+ _ <- openDoc' "B.hs" "haskell" sourceB
234 expectDiagnostics $ expectedDs msg
203 expectDiagnostics $ expectedDs msg
236 [ deferralTest "type error" "True" "Couldn't match expected type"
205 [ deferralTest "type error" "True" "Couldn't match expected type"
237 , deferralTest "typed hole" "_" "Found hole"
206 , deferralTest "typed hole" "_" "Found hole"
238 , deferralTest "out of scope var" "unbound" "Variable not in scope"
207 , deferralTest "out of scope var" "unbound" "Variable not in scope"
208+ , deferralTest "message shows error" "True" "A.hs:3:5: error:"
241 , testSessionWait "remove required module" $ do
211 , testSessionWait "remove required module" $ do
242 let contentA = T.unlines [ "module ModuleA where" ]
212 let contentA = T.unlines [ "module ModuleA where" ]
243− docA <- createDoc "ModuleA.hs" "haskell" contentA
213+ docA <- openDoc' "ModuleA.hs" "haskell" contentA
244 let contentB = T.unlines
214 let contentB = T.unlines
245 [ "module ModuleB where"
215 [ "module ModuleB where"
246 , "import ModuleA"
216 , "import ModuleA"
248− _ <- createDoc "ModuleB.hs" "haskell" contentB
218+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
249 let change = TextDocumentContentChangeEvent
219 let change = TextDocumentContentChangeEvent
250 { _range = Just (Range (Position 0 0) (Position 0 20))
220 { _range = Just (Range (Position 0 0) (Position 0 20))
251 , _rangeLength = Nothing
221 , _rangeLength = Nothing
@@ -258,21 +228,11 @@ diagnosticTests = testGroup "diagnostics"
258 [ "module ModuleB where"
228 [ "module ModuleB where"
259 , "import ModuleA"
229 , "import ModuleA"
261− _ <- createDoc "ModuleB.hs" "haskell" contentB
231+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
262 expectDiagnostics [("ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]
232 expectDiagnostics [("ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]
263 let contentA = T.unlines [ "module ModuleA where" ]
233 let contentA = T.unlines [ "module ModuleA where" ]
264− _ <- createDoc "ModuleA.hs" "haskell" contentA
234+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
265 expectDiagnostics [("ModuleB.hs", [])]
235 expectDiagnostics [("ModuleB.hs", [])]
266− , testSessionWait "add missing module (non workspace)" $ do
267− let contentB = T.unlines
268− [ "module ModuleB where"
271− _ <- createDoc "/tmp/ModuleB.hs" "haskell" contentB
272− expectDiagnostics [("/tmp/ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]
273− let contentA = T.unlines [ "module ModuleA where" ]
274− _ <- createDoc "/tmp/ModuleA.hs" "haskell" contentA
275− expectDiagnostics [("/tmp/ModuleB.hs", [])]
276 , testSessionWait "cyclic module dependency" $ do
236 , testSessionWait "cyclic module dependency" $ do
277 let contentA = T.unlines
237 let contentA = T.unlines
278 [ "module ModuleA where"
238 [ "module ModuleA where"
@@ -282,8 +242,8 @@ diagnosticTests = testGroup "diagnostics"
282 [ "module ModuleB where"
242 [ "module ModuleB where"
283 , "import ModuleA"
243 , "import ModuleA"
285− _ <- createDoc "ModuleA.hs" "haskell" contentA
245+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
286− _ <- createDoc "ModuleB.hs" "haskell" contentB
246+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
287 expectDiagnostics
247 expectDiagnostics
288 [ ( "ModuleA.hs"
248 [ ( "ModuleA.hs"
289 , [(DsError, (1, 7), "Cyclic module dependency between ModuleA, ModuleB")]
249 , [(DsError, (1, 7), "Cyclic module dependency between ModuleA, ModuleB")]
@@ -304,9 +264,9 @@ diagnosticTests = testGroup "diagnostics"
304 let contentBboot = T.unlines
264 let contentBboot = T.unlines
305 [ "module ModuleB where"
265 [ "module ModuleB where"
307− _ <- createDoc "ModuleA.hs" "haskell" contentA
267+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
308− _ <- createDoc "ModuleB.hs" "haskell" contentB
268+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
309− _ <- createDoc "ModuleB.hs-boot" "haskell" contentBboot
269+ _ <- openDoc' "ModuleB.hs-boot" "haskell" contentBboot
310 expectDiagnostics []
270 expectDiagnostics []
311 , testSessionWait "correct reference used with hs-boot" $ do
271 , testSessionWait "correct reference used with hs-boot" $ do
312 let contentB = T.unlines
272 let contentB = T.unlines
@@ -328,10 +288,10 @@ diagnosticTests = testGroup "diagnostics"
328 -- resolved to the hs-boot file
288 -- resolved to the hs-boot file
329 , "y = x"
289 , "y = x"
331− _ <- createDoc "ModuleB.hs" "haskell" contentB
291+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
332− _ <- createDoc "ModuleA.hs" "haskell" contentA
292+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
333− _ <- createDoc "ModuleA.hs-boot" "haskell" contentAboot
293+ _ <- openDoc' "ModuleA.hs-boot" "haskell" contentAboot
334− _ <- createDoc "ModuleC.hs" "haskell" contentC
294+ _ <- openDoc' "ModuleC.hs" "haskell" contentC
335 expectDiagnostics []
295 expectDiagnostics []
336 , testSessionWait "redundant import" $ do
296 , testSessionWait "redundant import" $ do
337 let contentA = T.unlines ["module ModuleA where"]
297 let contentA = T.unlines ["module ModuleA where"]
@@ -340,8 +300,8 @@ diagnosticTests = testGroup "diagnostics"
340 , "module ModuleB where"
300 , "module ModuleB where"
341 , "import ModuleA"
301 , "import ModuleA"
343− _ <- createDoc "ModuleA.hs" "haskell" contentA
303+ _ <- openDoc' "ModuleA.hs" "haskell" contentA
344− _ <- createDoc "ModuleB.hs" "haskell" contentB
304+ _ <- openDoc' "ModuleB.hs" "haskell" contentB
345 expectDiagnostics
305 expectDiagnostics
346 [ ( "ModuleB.hs"
306 [ ( "ModuleB.hs"
347 , [(DsWarning, (2, 0), "The import of 'ModuleA' is redundant")]
307 , [(DsWarning, (2, 0), "The import of 'ModuleA' is redundant")]
@@ -363,8 +323,8 @@ diagnosticTests = testGroup "diagnostics"
363 , "wrong1 = ThisList.map"
323 , "wrong1 = ThisList.map"
364 , "wrong2 = BaseList.x"
324 , "wrong2 = BaseList.x"
366− _ <- createDoc "Data/List.hs" "haskell" thisDataListContent
326+ _ <- openDoc' "Data/List.hs" "haskell" thisDataListContent
367− _ <- createDoc "Main.hs" "haskell" mainContent
327+ _ <- openDoc' "Main.hs" "haskell" mainContent
368 expectDiagnostics
328 expectDiagnostics
369 [ ( "Main.hs"
329 [ ( "Main.hs"
370 , [(DsError, (6, 9), "Not in scope: \8216ThisList.map\8217")
330 , [(DsError, (6, 9), "Not in scope: \8216ThisList.map\8217")
@@ -379,7 +339,7 @@ diagnosticTests = testGroup "diagnostics"
379 , "foo :: Ord a => a -> Int"
339 , "foo :: Ord a => a -> Int"
380 , "foo a = 1"
340 , "foo a = 1"
382− _ <- createDoc "Foo.hs" "haskell" fooContent
342+ _ <- openDoc' "Foo.hs" "haskell" fooContent
383 expectDiagnostics
343 expectDiagnostics
384 [ ( "Foo.hs"
344 [ ( "Foo.hs"
385 -- The test is to make sure that warnings contain unqualified names
345 -- The test is to make sure that warnings contain unqualified names
@@ -404,18 +364,18 @@ diagnosticTests = testGroup "diagnostics"
404 Just pathB <- pure $ uriToFilePath uriB
364 Just pathB <- pure $ uriToFilePath uriB
405 uriB <- pure $
365 uriB <- pure $
406 let (drive, suffix) = splitDrive pathB
366 let (drive, suffix) = splitDrive pathB
407− in filePathToUri (joinDrive (lower drive) suffix)
367+ in filePathToUri (joinDrive (map toLower drive ) suffix)
408 liftIO $ createDirectoryIfMissing True (takeDirectory pathB)
368 liftIO $ createDirectoryIfMissing True (takeDirectory pathB)
409 liftIO $ writeFileUTF8 pathB $ T.unpack bContent
369 liftIO $ writeFileUTF8 pathB $ T.unpack bContent
410 uriA <- getDocUri "A/A.hs"
370 uriA <- getDocUri "A/A.hs"
411 Just pathA <- pure $ uriToFilePath uriA
371 Just pathA <- pure $ uriToFilePath uriA
412 uriA <- pure $
372 uriA <- pure $
413 let (drive, suffix) = splitDrive pathA
373 let (drive, suffix) = splitDrive pathA
414− in filePathToUri (joinDrive (lower drive) suffix)
374+ in filePathToUri (joinDrive (map toLower drive ) suffix)
415 let itemA = TextDocumentItem uriA "haskell" 0 aContent
375 let itemA = TextDocumentItem uriA "haskell" 0 aContent
416 let a = TextDocumentIdentifier uriA
376 let a = TextDocumentIdentifier uriA
417 sendNotification TextDocumentDidOpen (DidOpenTextDocumentParams itemA)
377 sendNotification TextDocumentDidOpen (DidOpenTextDocumentParams itemA)
418− diagsNot <- skipManyTill anyMessage diagnostic
378+ diagsNot <- skipManyTill anyMessage message :: Session PublishDiagnosticsNotification
419 let PublishDiagnosticsParams fileUri diags = _params (diagsNot :: PublishDiagnosticsNotification)
379 let PublishDiagnosticsParams fileUri diags = _params (diagsNot :: PublishDiagnosticsNotification)
420 -- Check that if we put a lower-case drive in for A.A
380 -- Check that if we put a lower-case drive in for A.A
421 -- the diagnostics for A.B will also be lower-case.
381 -- the diagnostics for A.B will also be lower-case.
@@ -424,38 +384,6 @@ diagnosticTests = testGroup "diagnostics"
424 liftIO $ unless ("redundant" `T.isInfixOf` msg) $
384 liftIO $ unless ("redundant" `T.isInfixOf` msg) $
425 assertFailure ("Expected redundant import but got " <> T.unpack msg)
385 assertFailure ("Expected redundant import but got " <> T.unpack msg)
426 closeDoc a
386 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
389codeActionTests :: TestTree
@@ -464,8 +392,6 @@ codeActionTests = testGroup "code actions"
464 , typeWildCardActionTests
392 , typeWildCardActionTests
465 , removeImportTests
393 , removeImportTests
466 , extendImportTests
394 , extendImportTests
467− , suggestImportTests
469 , fixConstructorImportTests
395 , fixConstructorImportTests
470 , importRenameActionTests
396 , importRenameActionTests
471 , fillTypedHoleTests
397 , fillTypedHoleTests
@@ -478,33 +404,6 @@ codeLensesTests = testGroup "code lenses"
478 [ addSigLensesTests
404 [ addSigLensesTests
481−watchedFilesTests :: TestTree
482−watchedFilesTests = testGroup "watched files"
483− [ testSession' "workspace files" $ \sessionDir -> do
484− liftIO $ writeFile (sessionDir </> "hie.yaml") "cradle: {direct: {arguments: [\"-isrc\"]}}"
485− _doc <- createDoc "A.hs" "haskell" "{-#LANGUAGE NoImplicitPrelude #-}\nmodule A where\nimport WatchedFilesMissingModule"
486− watchedFileRegs <- getWatchedFilesSubscriptionsUntil @PublishDiagnosticsNotification
488− -- Expect 4 subscriptions (A does not get any because it's VFS):
489− -- - /path-to-workspace/WatchedFilesMissingModule.hs
490− -- - /path-to-workspace/WatchedFilesMissingModule.lhs
491− -- - /path-to-workspace/src/WatchedFilesMissingModule.hs
492− -- - /path-to-workspace/src/WatchedFilesMissingModule.lhs
493− liftIO $ length watchedFileRegs @?= 4
495− , testSession' "non workspace file" $ \sessionDir -> do
496− liftIO $ writeFile (sessionDir </> "hie.yaml") "cradle: {direct: {arguments: [\"-i/tmp\"]}}"
497− _doc <- createDoc "A.hs" "haskell" "{-# LANGUAGE NoImplicitPrelude#-}\nmodule A where\nimport WatchedFilesMissingModule"
498− watchedFileRegs <- getWatchedFilesSubscriptionsUntil @PublishDiagnosticsNotification
500− -- Expect 2 subscriptions (/tmp does not get any as it is out of the workspace):
501− -- - /path-to-workspace/WatchedFilesMissingModule.hs
502− -- - /path-to-workspace/WatchedFilesMissingModule.lhs
503− liftIO $ length watchedFileRegs @?= 2
505− -- TODO add a test for didChangeWorkspaceFolder
508renameActionTests :: TestTree
407renameActionTests :: TestTree
509renameActionTests = testGroup "rename actions"
408renameActionTests = testGroup "rename actions"
510 [ testSession "change to local variable name" $ do
409 [ testSession "change to local variable name" $ do
@@ -513,7 +412,7 @@ renameActionTests = testGroup "rename actions"
513 , "foo :: Int -> Int"
412 , "foo :: Int -> Int"
514 , "foo argName = argNme"
413 , "foo argName = argNme"
516− doc <- createDoc "Testing.hs" "haskell" content
415+ doc <- openDoc' "Testing.hs" "haskell" content
517 _ <- waitForDiagnostics
416 _ <- waitForDiagnostics
518 action <- findCodeAction doc (Range (Position 2 14) (Position 2 20)) "Replace with ‘argName’"
417 action <- findCodeAction doc (Range (Position 2 14) (Position 2 20)) "Replace with ‘argName’"
519 executeCodeAction action
418 executeCodeAction action
@@ -531,7 +430,7 @@ renameActionTests = testGroup "rename actions"
531 , "foo :: Maybe a -> [a]"
430 , "foo :: Maybe a -> [a]"
532 , "foo = maybToList"
431 , "foo = maybToList"
534− doc <- createDoc "Testing.hs" "haskell" content
433+ doc <- openDoc' "Testing.hs" "haskell" content
535 _ <- waitForDiagnostics
434 _ <- waitForDiagnostics
536 action <- findCodeAction doc (Range (Position 3 6) (Position 3 16)) "Replace with ‘maybeToList’"
435 action <- findCodeAction doc (Range (Position 3 6) (Position 3 16)) "Replace with ‘maybeToList’"
537 executeCodeAction action
436 executeCodeAction action
@@ -549,7 +448,7 @@ renameActionTests = testGroup "rename actions"
549 , "foo :: Char -> Char -> Char -> Char"
448 , "foo :: Char -> Char -> Char -> Char"
550 , "foo argument1 argument2 argument3 = argumentX"
449 , "foo argument1 argument2 argument3 = argumentX"
552− doc <- createDoc "Testing.hs" "haskell" content
451+ doc <- openDoc' "Testing.hs" "haskell" content
553 _ <- waitForDiagnostics
452 _ <- waitForDiagnostics
554 _ <- findCodeActions doc (Range (Position 2 36) (Position 2 45))
453 _ <- findCodeActions doc (Range (Position 2 36) (Position 2 45))
555 ["Replace with ‘argument1’", "Replace with ‘argument2’", "Replace with ‘argument3’"]
454 ["Replace with ‘argument1’", "Replace with ‘argument2’", "Replace with ‘argument3’"]
@@ -561,7 +460,7 @@ renameActionTests = testGroup "rename actions"
561 , "monus x y = max 0 (x - y)"
460 , "monus x y = max 0 (x - y)"
562 , "foo x y = x `monnus` y"
461 , "foo x y = x `monnus` y"
564− doc <- createDoc "Testing.hs" "haskell" content
463+ doc <- openDoc' "Testing.hs" "haskell" content
565 _ <- waitForDiagnostics
464 _ <- waitForDiagnostics
566 actionsOrCommands <- getCodeActions doc (Range (Position 3 12) (Position 3 20))
465 actionsOrCommands <- getCodeActions doc (Range (Position 3 12) (Position 3 20))
567 [fixTypo] <- pure [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, "monus" `T.isInfixOf` actionTitle ]
466 [fixTypo] <- pure [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, "monus" `T.isInfixOf` actionTitle ]
@@ -584,7 +483,7 @@ typeWildCardActionTests = testGroup "type wildcard actions"
584 , "func :: _"
483 , "func :: _"
585 , "func x = x"
484 , "func x = x"
587− doc <- createDoc "Testing.hs" "haskell" content
486+ doc <- openDoc' "Testing.hs" "haskell" content
588 _ <- waitForDiagnostics
487 _ <- waitForDiagnostics
589 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
488 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
590 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
489 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
@@ -604,7 +503,7 @@ typeWildCardActionTests = testGroup "type wildcard actions"
604 , "func :: _"
503 , "func :: _"
605 , "func x y = x + y"
504 , "func x y = x + y"
607− doc <- createDoc "Testing.hs" "haskell" content
506+ doc <- openDoc' "Testing.hs" "haskell" content
608 _ <- waitForDiagnostics
507 _ <- waitForDiagnostics
609 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
508 actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))
610 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
509 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
@@ -627,7 +526,7 @@ typeWildCardActionTests = testGroup "type wildcard actions"
627 , " y = x * 2"
526 , " y = x * 2"
628 , " in y"
527 , " in y"
630− doc <- createDoc "Testing.hs" "haskell" content
529+ doc <- openDoc' "Testing.hs" "haskell" content
631 _ <- waitForDiagnostics
530 _ <- waitForDiagnostics
632 actionsOrCommands <- getCodeActions doc (Range (Position 4 1) (Position 4 10))
531 actionsOrCommands <- getCodeActions doc (Range (Position 4 1) (Position 4 10))
633 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
532 let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands
@@ -652,7 +551,7 @@ removeImportTests = testGroup "remove import actions"
652 let contentA = T.unlines
551 let contentA = T.unlines
653 [ "module ModuleA where"
552 [ "module ModuleA where"
655− _docA <- createDoc "ModuleA.hs" "haskell" contentA
554+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
656 let contentB = T.unlines
555 let contentB = T.unlines
657 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
556 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
658 , "module ModuleB where"
557 , "module ModuleB where"
@@ -660,7 +559,7 @@ removeImportTests = testGroup "remove import actions"
660 , "stuffB :: Integer"
559 , "stuffB :: Integer"
661 , "stuffB = 123"
560 , "stuffB = 123"
663− docB <- createDoc "ModuleB.hs" "haskell" contentB
562+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
664 _ <- waitForDiagnostics
563 _ <- waitForDiagnostics
665 [CACodeAction action@CodeAction { _title = actionTitle }]
564 [CACodeAction action@CodeAction { _title = actionTitle }]
666 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
565 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -678,7 +577,7 @@ removeImportTests = testGroup "remove import actions"
678 let contentA = T.unlines
577 let contentA = T.unlines
679 [ "module ModuleA where"
578 [ "module ModuleA where"
681− _docA <- createDoc "ModuleA.hs" "haskell" contentA
580+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
682 let contentB = T.unlines
581 let contentB = T.unlines
683 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
582 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
684 , "module ModuleB where"
583 , "module ModuleB where"
@@ -686,7 +585,7 @@ removeImportTests = testGroup "remove import actions"
686 , "stuffB :: Integer"
585 , "stuffB :: Integer"
687 , "stuffB = 123"
586 , "stuffB = 123"
689− docB <- createDoc "ModuleB.hs" "haskell" contentB
588+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
690 _ <- waitForDiagnostics
589 _ <- waitForDiagnostics
691 [CACodeAction action@CodeAction { _title = actionTitle }]
590 [CACodeAction action@CodeAction { _title = actionTitle }]
692 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
591 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -708,14 +607,14 @@ removeImportTests = testGroup "remove import actions"
708 , "stuffB = 123"
607 , "stuffB = 123"
709 , "stuffC = ()"
608 , "stuffC = ()"
711− _docA <- createDoc "ModuleA.hs" "haskell" contentA
610+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
712 let contentB = T.unlines
611 let contentB = T.unlines
713 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
612 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
714 , "module ModuleB where"
613 , "module ModuleB where"
715 , "import ModuleA (stuffA, stuffB, stuffC, stuffA)"
614 , "import ModuleA (stuffA, stuffB, stuffC, stuffA)"
716 , "main = print stuffB"
615 , "main = print stuffB"
718− docB <- createDoc "ModuleB.hs" "haskell" contentB
617+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
719 _ <- waitForDiagnostics
618 _ <- waitForDiagnostics
720 [CACodeAction action@CodeAction { _title = actionTitle }]
619 [CACodeAction action@CodeAction { _title = actionTitle }]
721 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
620 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -729,26 +628,29 @@ removeImportTests = testGroup "remove import actions"
729 , "main = print stuffB"
628 , "main = print stuffB"
731 liftIO $ expectedContentAfterAction @=? contentAfterAction
630 liftIO $ expectedContentAfterAction @=? contentAfterAction
732− , testSession "redundant operator" $ do
631+ , testSession "redundant symbol binding" $ do
733 let contentA = T.unlines
632 let contentA = T.unlines
734 [ "module ModuleA where"
633 [ "module ModuleA where"
735 , "a !! b = a"
634 , "a !! b = a"
737 , "stuffB :: Integer"
635 , "stuffB :: Integer"
738 , "stuffB = 123"
636 , "stuffB = 123"
740− _docA <- createDoc "ModuleA.hs" "haskell" contentA
638+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
741 let contentB = T.unlines
639 let contentB = T.unlines
742 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
640 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
743 , "module ModuleB where"
641 , "module ModuleB where"
744− , "import qualified ModuleA as A ((<?>), stuffB, (!!))"
642+ , "import qualified ModuleA as A ((!!), stuffB, (!!))"
745 , "main = print A.stuffB"
643 , "main = print A.stuffB"
747− docB <- createDoc "ModuleB.hs" "haskell" contentB
645+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
748 _ <- waitForDiagnostics
646 _ <- waitForDiagnostics
749 [CACodeAction action@CodeAction { _title = actionTitle }]
647 [CACodeAction action@CodeAction { _title = actionTitle }]
750 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
648 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
649+#if MIN_GHC_API_VERSION(8,6,0)
650+ liftIO $ "Remove !! from import" @=? actionTitle
751− liftIO $ "Remove !!, <?> from import" @=? actionTitle
652+ liftIO $ "Remove A.!! from import" @=? actionTitle
752 executeCodeAction action
654 executeCodeAction action
753 contentAfterAction <- documentContents docB
655 contentAfterAction <- documentContents docB
754 let expectedContentAfterAction = T.unlines
656 let expectedContentAfterAction = T.unlines
@@ -758,21 +660,21 @@ removeImportTests = testGroup "remove import actions"
758 , "main = print A.stuffB"
660 , "main = print A.stuffB"
760 liftIO $ expectedContentAfterAction @=? contentAfterAction
662 liftIO $ expectedContentAfterAction @=? contentAfterAction
761− , testSession "redundant all import" $ do
663+ , (`xfail` "known broken (#299)") $ testSession "redundant hierarchical import" $ do
762 let contentA = T.unlines
664 let contentA = T.unlines
763 [ "module ModuleA where"
665 [ "module ModuleA where"
764 , "data A = A"
666 , "data A = A"
765 , "stuffB :: Integer"
667 , "stuffB :: Integer"
766 , "stuffB = 123"
668 , "stuffB = 123"
768− _docA <- createDoc "ModuleA.hs" "haskell" contentA
670+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
769 let contentB = T.unlines
671 let contentB = T.unlines
770 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
672 [ "{-# OPTIONS_GHC -Wunused-imports #-}"
771 , "module ModuleB where"
673 , "module ModuleB where"
772 , "import ModuleA (A(..), stuffB)"
674 , "import ModuleA (A(..), stuffB)"
773 , "main = print stuffB"
675 , "main = print stuffB"
775− docB <- createDoc "ModuleB.hs" "haskell" contentB
677+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
776 _ <- waitForDiagnostics
678 _ <- waitForDiagnostics
777 [CACodeAction action@CodeAction { _title = actionTitle }]
679 [CACodeAction action@CodeAction { _title = actionTitle }]
778 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
680 <- getCodeActions docB (Range (Position 2 0) (Position 2 5))
@@ -786,33 +688,6 @@ removeImportTests = testGroup "remove import actions"
786 , "main = print stuffB"
688 , "main = print stuffB"
788 liftIO $ expectedContentAfterAction @=? contentAfterAction
690 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
693extendImportTests :: TestTree
@@ -837,26 +712,6 @@ extendImportTests = testGroup "extend import actions"
837 , "import ModuleA as A (stuffA, stuffB)"
712 , "import ModuleA as A (stuffA, stuffB)"
838 , "main = print (stuffA, stuffB)"
713 , "main = print (stuffA, stuffB)"
840− , testSession "extend single line import with operator" $ template
842− [ "module ModuleA where"
843− , "(.*) :: Integer -> Integer -> Integer"
845− , "stuffB :: Integer"
849− [ "module ModuleB where"
850− , "import ModuleA as A (stuffB)"
851− , "main = print (stuffB .* stuffB)"
853− (Range (Position 3 17) (Position 3 18))
854− "Add .* to the import list of ModuleA"
856− [ "module ModuleB where"
857− , "import ModuleA as A ((.*), stuffB)"
858− , "main = print (stuffB .* stuffB)"
860 , testSession "extend single line import with type" $ template
715 , testSession "extend single line import with type" $ template
861 (T.unlines
716 (T.unlines
862 [ "module ModuleA where"
717 [ "module ModuleA where"
@@ -940,8 +795,8 @@ extendImportTests = testGroup "extend import actions"
942 template contentA contentB range expectedAction expectedContentB = do
797 template contentA contentB range expectedAction expectedContentB = do
943− _docA <- createDoc "ModuleA.hs" "haskell" contentA
798+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
944− docB <- createDoc "ModuleB.hs" "haskell" contentB
799+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
945 _ <- waitForDiagnostics
800 _ <- waitForDiagnostics
946 CACodeAction action@CodeAction { _title = actionTitle } : _
801 CACodeAction action@CodeAction { _title = actionTitle } : _
947 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
802 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -951,117 +806,6 @@ extendImportTests = testGroup "extend import actions"
951 contentAfterAction <- documentContents docB
806 contentAfterAction <- documentContents docB
952 liftIO $ expectedContentB @=? contentAfterAction
807 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 ] @?= []
1009−addExtensionTests :: TestTree
1010−addExtensionTests = testGroup "add language extension actions"
1011− [ testSession "add NamedFieldPuns language extension" $ template
1013− [ "module Module where"
1015− , "data A = A { getA :: Bool }"
1018− , "f A { getA } = getA"
1020− (Range (Position 0 0) (Position 0 0))
1021− "Add NamedFieldPuns extension"
1023− [ "{-# LANGUAGE NamedFieldPuns #-}"
1024− , "module Module where"
1026− , "data A = A { getA :: Bool }"
1029− , "f A { getA } = getA"
1031− , testSession "add RecordWildCards language extension" $ template
1033− [ "module Module where"
1035− , "data A = A { getA :: Bool }"
1038− , "f A { .. } = getA"
1040− (Range (Position 0 0) (Position 0 0))
1041− "Add RecordWildCards extension"
1043− [ "{-# LANGUAGE RecordWildCards #-}"
1044− , "module Module where"
1046− , "data A = A { getA :: Bool }"
1049− , "f A { .. } = getA"
1053− template initialContent range expectedAction expectedContents = do
1054− doc <- createDoc "Module.hs" "haskell" initialContent
1055− _ <- waitForDiagnostics
1056− CACodeAction action@CodeAction { _title = actionTitle } : _
1057− <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
1058− getCodeActions doc range
1059− liftIO $ expectedAction @=? actionTitle
1060− executeCodeAction action
1061− contentAfterAction <- documentContents doc
1062− liftIO $ expectedContents @=? contentAfterAction
1065insertNewDefinitionTests :: TestTree
809insertNewDefinitionTests :: TestTree
1066insertNewDefinitionTests = testGroup "insert new definition actions"
810insertNewDefinitionTests = testGroup "insert new definition actions"
1067 [ testSession "insert new function definition" $ do
811 [ testSession "insert new function definition" $ do
@@ -1074,7 +818,7 @@ insertNewDefinitionTests = testGroup "insert new definition actions"
1075 ,"someOtherCode = ()"
819 ,"someOtherCode = ()"
1077− docB <- createDoc "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
821+ docB <- openDoc' "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
1078 _ <- waitForDiagnostics
822 _ <- waitForDiagnostics
1079 CACodeAction action@CodeAction { _title = actionTitle } : _
823 CACodeAction action@CodeAction { _title = actionTitle } : _
1080 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
824 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1098,7 +842,7 @@ insertNewDefinitionTests = testGroup "insert new definition actions"
1099 ,"someOtherCode = ()"
843 ,"someOtherCode = ()"
1101− docB <- createDoc "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
845+ docB <- openDoc' "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')
1102 _ <- waitForDiagnostics
846 _ <- waitForDiagnostics
1103 CACodeAction action@CodeAction { _title = actionTitle } : _
847 CACodeAction action@CodeAction { _title = actionTitle } : _
1104 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
848 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1137,8 +881,8 @@ fixConstructorImportTests = testGroup "fix import actions"
1139 template contentA contentB range expectedAction expectedContentB = do
883 template contentA contentB range expectedAction expectedContentB = do
1140− _docA <- createDoc "ModuleA.hs" "haskell" contentA
884+ _docA <- openDoc' "ModuleA.hs" "haskell" contentA
1141− docB <- createDoc "ModuleB.hs" "haskell" contentB
885+ docB <- openDoc' "ModuleB.hs" "haskell" contentB
1142 _diags <- waitForDiagnostics
886 _diags <- waitForDiagnostics
1143 CACodeAction action@CodeAction { _title = actionTitle } : _
887 CACodeAction action@CodeAction { _title = actionTitle } : _
1144 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
888 <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>
@@ -1157,7 +901,7 @@ importRenameActionTests = testGroup "import rename actions"
1157 [ "module Testing where"
901 [ "module Testing where"
1158 , "import Data.Mape"
902 , "import Data.Mape"
1160− doc <- createDoc "Testing.hs" "haskell" content
904+ doc <- openDoc' "Testing.hs" "haskell" content
1161 _ <- waitForDiagnostics
905 _ <- waitForDiagnostics
1162 actionsOrCommands <- getCodeActions doc (Range (Position 2 8) (Position 2 16))
906 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 ]
907 let [changeToMap] = [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, ("Data." <> modname) `T.isInfixOf` actionTitle ]
@@ -1194,10 +938,10 @@ fillTypedHoleTests = let
1194 newA newB newC = testSession (T.unpack actionTitle) $ do
938 newA newB newC = testSession (T.unpack actionTitle) $ do
1195 let originalCode = sourceCode oldA oldB oldC
939 let originalCode = sourceCode oldA oldB oldC
1196 let expectedCode = sourceCode newA newB newC
940 let expectedCode = sourceCode newA newB newC
1197− doc <- createDoc "Testing.hs" "haskell" originalCode
941+ doc <- openDoc' "Testing.hs" "haskell" originalCode
1198 _ <- waitForDiagnostics
942 _ <- waitForDiagnostics
1199 actionsOrCommands <- getCodeActions doc (Range (Position 9 0) (Position 9 maxBound))
943 actionsOrCommands <- getCodeActions doc (Range (Position 9 0) (Position 9 maxBound))
1200− chosenAction <- liftIO $ pickActionWithTitle actionTitle actionsOrCommands
944+ let chosenAction = pickActionWithTitle actionTitle actionsOrCommands
1201 executeCodeAction chosenAction
945 executeCodeAction chosenAction
1202 modifiedCode <- documentContents doc
946 modifiedCode <- documentContents doc
1203 liftIO $ expectedCode @=? modifiedCode
947 liftIO $ expectedCode @=? modifiedCode
@@ -1234,37 +978,36 @@ fillTypedHoleTests = let
1235addSigActionTests :: TestTree
979addSigActionTests :: TestTree
1236addSigActionTests = let
980addSigActionTests = let
1237− header = "{-# OPTIONS_GHC -Wmissing-signatures -Wmissing-pattern-synonym-signatures #-}"
981+ header = "{-# OPTIONS_GHC -Wmissing-signatures #-}"
1238− moduleH = "{-# LANGUAGE PatternSynonyms #-}\nmodule Sigs where"
982+ moduleH = "module Sigs where"
1239 before def = T.unlines [header, moduleH, def]
983 before def = T.unlines [header, moduleH, def]
1240 after' def sig = T.unlines [header, moduleH, sig, def]
984 after' def sig = T.unlines [header, moduleH, sig, def]
1242 def >:: sig = testSession (T.unpack def) $ do
986 def >:: sig = testSession (T.unpack def) $ do
1243 let originalCode = before def
987 let originalCode = before def
1244 let expectedCode = after' def sig
988 let expectedCode = after' def sig
1245− doc <- createDoc "Sigs.hs" "haskell" originalCode
989+ doc <- openDoc' "Sigs.hs" "haskell" originalCode
1246 _ <- waitForDiagnostics
990 _ <- waitForDiagnostics
1247 actionsOrCommands <- getCodeActions doc (Range (Position 3 1) (Position 3 maxBound))
991 actionsOrCommands <- getCodeActions doc (Range (Position 3 1) (Position 3 maxBound))
1248− chosenAction <- liftIO $ pickActionWithTitle ("add signature: " <> sig) actionsOrCommands
992+ let chosenAction = pickActionWithTitle ("add signature: " <> sig) actionsOrCommands
1249 executeCodeAction chosenAction
993 executeCodeAction chosenAction
1250 modifiedCode <- documentContents doc
994 modifiedCode <- documentContents doc
1251 liftIO $ expectedCode @=? modifiedCode
995 liftIO $ expectedCode @=? modifiedCode
1253 testGroup "add signature"
997 testGroup "add signature"
1254− [ "abc = True" >:: "abc :: Bool"
998+ [ "abc = True" >:: "abc :: Bool"
1255− , "foo a b = a + b" >:: "foo :: Num a => a -> a -> a"
999+ , "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"
1000+ , "bar a b = show $ a + b" >:: "bar :: (Show a, Num a) => a -> a -> String"
1257− , "(!!!) a b = a > b" >:: "(!!!) :: Ord a => a -> a -> Bool"
1001+ , "(!!!) a b = a > b" >:: "(!!!) :: Ord a => a -> a -> Bool"
1258− , "a >>>> b = a + b" >:: "(>>>>) :: Num a => a -> a -> a"
1002+ , "a >>>> b = a + b" >:: "(>>>>) :: Num a => a -> a -> a"
1259− , "a `haha` b = a b" >:: "haha :: (t1 -> t2) -> t1 -> t2"
1003+ , "a `haha` b = a b" >:: "haha :: (t1 -> t2) -> t1 -> t2"
1260− , "pattern Some a = Just a" >:: "pattern Some :: a -> Maybe a"
1263addSigLensesTests :: TestTree
1006addSigLensesTests :: TestTree
1264addSigLensesTests = let
1007addSigLensesTests = let
1265− missing = "{-# OPTIONS_GHC -Wmissing-signatures -Wmissing-pattern-synonym-signatures -Wunused-matches #-}"
1008+ missing = "{-# OPTIONS_GHC -Wmissing-signatures -Wunused-matches #-}"
1266 notMissing = "{-# OPTIONS_GHC -Wunused-matches #-}"
1009 notMissing = "{-# OPTIONS_GHC -Wunused-matches #-}"
1267− moduleH = "{-# LANGUAGE PatternSynonyms #-}\nmodule Sigs where"
1010+ moduleH = "module Sigs where"
1268 other = T.unlines ["f :: Integer -> Integer", "f x = 3"]
1011 other = T.unlines ["f :: Integer -> Integer", "f x = 3"]
1269 before withMissing def
1012 before withMissing def
1270 = T.unlines $ (if withMissing then (missing :) else (notMissing :)) [moduleH, def, other]
1013 = T.unlines $ (if withMissing then (missing :) else (notMissing :)) [moduleH, def, other]
@@ -1274,61 +1017,58 @@ addSigLensesTests = let
1274 sigSession withMissing def sig = testSession (T.unpack def) $ do
1017 sigSession withMissing def sig = testSession (T.unpack def) $ do
1275 let originalCode = before withMissing def
1018 let originalCode = before withMissing def
1276 let expectedCode = after' withMissing def sig
1019 let expectedCode = after' withMissing def sig
1277− doc <- createDoc "Sigs.hs" "haskell" originalCode
1020+ doc <- openDoc' "Sigs.hs" "haskell" originalCode
1278 [CodeLens {_command = Just c}] <- getCodeLenses doc
1021 [CodeLens {_command = Just c}] <- getCodeLenses doc
1279 executeCommand c
1022 executeCommand c
1280 modifiedCode <- getDocumentEdit doc
1023 modifiedCode <- getDocumentEdit doc
1281 liftIO $ expectedCode @=? modifiedCode
1024 liftIO $ expectedCode @=? modifiedCode
1283 testGroup "add signature"
1026 testGroup "add signature"
1284− [ testGroup title
1027+ [ testGroup "with warnings enabled"
1285− [ sigSession enableWarnings "abc = True" "abc :: Bool"
1028+ [ sigSession True "abc = True" "abc :: Bool"
1286− , sigSession enableWarnings "foo a b = a + b" "foo :: Num a => a -> a -> a"
1029+ , 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"
1030+ , 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"
1031+ , sigSession True "(!!!) a b = a > b" "(!!!) :: Ord a => a -> a -> Bool"
1289− , sigSession enableWarnings "a >>>> b = a + b" "(>>>>) :: Num a => a -> a -> a"
1032+ , sigSession True "a >>>> b = a + b" "(>>>>) :: Num a => a -> a -> a"
1290− , sigSession enableWarnings "a `haha` b = a b" "haha :: (t1 -> t2) -> t1 -> t2"
1033+ , 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"
1034+ ]
1035+ , testGroup "with warnings disabled"
1036+ [ sigSession False "abc = True" "abc :: Bool"
1037+ , sigSession False "foo a b = a + b" "foo :: Num a => a -> a -> a"
1038+ , sigSession False "bar a b = show $ a + b" "bar :: (Show a, Num a) => a -> a -> String"
1039+ , sigSession False "(!!!) a b = a > b" "(!!!) :: Ord a => a -> a -> Bool"
1040+ , sigSession False "a >>>> b = a + b" "(>>>>) :: Num a => a -> a -> a"
1041+ , 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
1045findDefinitionAndHoverTests :: TestTree
1321findDefinitionAndHoverTests = let
1046findDefinitionAndHoverTests = let
1323− tst (get, check) pos targetRange title = testSessionWithExtraFiles "hover" title $ \dir -> do
1048+ tst (get, check) pos targetRange title = testSession title $ do
1324− doc <- openTestDataDoc (dir </> sourceFilePath)
1049+ doc <- openTestDataDoc sourceFilePath
1325 found <- get doc pos
1050 found <- get doc pos
1326 check found targetRange
1051 check found targetRange
1053+ checkDefs :: [Location] -> [Expect] -> Session ()
1054+ checkDefs defs expectations = traverse_ check expectations where
1056+ check (ExpectRange expectedRange) = do
1057+ assertNDefinitionsFound 1 defs
1058+ assertRangeCorrect (head defs) expectedRange
1059+ check ExpectNoDefinitions = do
1060+ assertNDefinitionsFound 0 defs
1061+ check ExpectExternFail = liftIO $ assertFailure "Expecting to fail to find in external file"
1062+ check _ = pure () -- all other expectations not relevant to getDefinition
1064+ assertNDefinitionsFound :: Int -> [a] -> Session ()
1065+ assertNDefinitionsFound n defs = liftIO $ assertEqual "number of definitions" n (length defs)
1067+ assertRangeCorrect Location{_range = foundRange} expectedRange =
1068+ liftIO $ expectedRange @=? foundRange
1330− checkHover :: Maybe Hover -> Session [Expect] -> Session ()
1070+ checkHover :: Maybe Hover -> [Expect] -> Session ()
1331− checkHover hover expectations = traverse_ check =<< expectations where
1071+ checkHover hover expectations = traverse_ check expectations where
1333 check expected =
1073 check expected =
1334 case hover of
1074 case hover of
@@ -1371,12 +1111,9 @@ findDefinitionAndHoverTests = let
1372 mkFindTests tests = testGroup "get"
1112 mkFindTests tests = testGroup "get"
1373 [ testGroup "definition" $ mapMaybe fst tests
1113 [ testGroup "definition" $ mapMaybe fst tests
1374− , testGroup "hover" $ mapMaybe snd tests
1114+ , testGroup "hover" $ mapMaybe snd tests ]
1375− , checkFileCompiles sourceFilePath ]
1377− test runDef runHover look expect = testM runDef runHover look (return expect)
1379− testM runDef runHover look expect title =
1116+ test runDef runHover look expect title =
1380 ( runDef $ tst def look expect title
1117 ( runDef $ tst def look expect title
1381 , runHover $ tst hover look expect title ) where
1118 , runHover $ tst hover look expect title ) where
1382 def = (getDefinitions, checkDefs)
1119 def = (getDefinitions, checkDefs)
@@ -1384,100 +1121,87 @@ findDefinitionAndHoverTests = let
1384 --type_ = (getTypeDefinitions, checkTDefs) -- getTypeDefinitions always times out
1121 --type_ = (getTypeDefinitions, checkTDefs) -- getTypeDefinitions always times out
1386 -- search locations expectations on results
1123 -- search locations expectations on results
1387− fffL4 = _start fffR ; fffR = mkRange 8 4 8 7 ; fff = [ExpectRange fffR]
1124+ fffL4 = _start fffR ; fffR = mkRange 4 4 4 7 ; fff = [ExpectRange fffR]
1388− fffL8 = Position 12 4 ;
1125+ fffL8 = Position 8 4 ;
1389− fffL14 = Position 18 7 ;
1126+ fffL14 = Position 14 7 ;
1390− aaaL14 = Position 18 20 ; aaa = [mkR 11 0 11 3]
1127+ aaaL14 = Position 14 20 ; aaa = [mkR 7 0 7 3]
1391− dcL7 = Position 11 11 ; tcDC = [mkR 7 23 9 16]
1128+ dcL7 = Position 7 11 ; tcDC = [mkR 3 23 5 16]
1392− dcL12 = Position 16 11 ;
1129+ dcL12 = Position 12 11 ;
1393− xtcL5 = Position 9 11 ; xtc = [ExpectExternFail, ExpectHoverText ["Int", "Defined in ‘GHC.Types’"]]
1130+ 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"]]
1131+ 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]
1132+ vvL16 = Position 16 12 ; vv = [mkR 16 4 16 6]
1396− opL16 = Position 20 15 ; op = [mkR 21 2 21 4]
1133+ opL16 = Position 16 15 ; op = [mkR 17 2 17 4]
1397− opL18 = Position 22 22 ; opp = [mkR 22 13 22 17]
1134+ opL18 = Position 18 22 ; opp = [mkR 18 13 18 17]
1398− aL18 = Position 22 20 ; apmp = [mkR 22 10 22 11]
1135+ aL18 = Position 18 20 ; apmp = [mkR 18 10 18 11]
1399− b'L19 = Position 23 13 ; bp = [mkR 23 6 23 7]
1136+ b'L19 = Position 19 13 ; bp = [mkR 19 6 19 7]
1400− xvL20 = Position 24 8 ; xvMsg = [ExpectExternFail, ExpectHoverText ["Data.Text.pack", ":: String -> Text"]]
1137+ 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"]]
1138+ clL23 = Position 23 11 ; cls = [mkR 21 0 22 20, ExpectHoverText ["MyClass", "GotoHover.hs:22:1"]]
1402− clL25 = Position 29 9
1139+ clL25 = Position 25 9
1403− eclL15 = Position 19 8 ; ecls = [ExpectExternFail, ExpectHoverText ["Num", "Defined in ‘GHC.Num’"]]
1140+ eclL15 = Position 15 8 ; ecls = [ExpectExternFail, ExpectHoverText ["Num", "Defined in ‘GHC.Num’"]]
1404− dnbL29 = Position 33 18 ; dnb = [ExpectHoverText [":: ()"], mkR 33 12 33 21]
1141+ dnbL29 = Position 29 18 ; dnb = [ExpectHoverText [":: ()"], mkR 29 12 29 21]
1405− dnbL30 = Position 34 23
1142+ dnbL30 = Position 30 23
1406− lcbL33 = Position 37 26 ; lcb = [ExpectHoverText [":: Char"], mkR 37 26 37 27]
1143+ lcbL33 = Position 33 26 ; lcb = [ExpectHoverText [":: Char"], mkR 33 26 33 27]
1407− lclL33 = Position 37 22
1144+ lclL33 = Position 33 22
1408− mclL36 = Position 40 1 ; mcl = [mkR 40 0 40 14]
1145+ mclL36 = Position 36 1 ; mcl = [mkR 36 0 36 14]
1409− mclL37 = Position 41 1
1146+ mclL37 = Position 37 1
1410− spaceL37 = Position 41 24 ; space = [ExpectNoDefinitions, ExpectHoverText [":: Char"]]
1147+ spaceL37 = Position 37 24 ; space = [ExpectNoDefinitions, ExpectHoverText [":: Char"]]
1411− docL41 = Position 45 1 ; doc = [ExpectHoverText ["Recognizable docs: kpqz"]]
1148+ docL41 = Position 41 1 ; doc = [ExpectHoverText ["Recognizable docs: kpqz"]]
1412 ; constr = [ExpectHoverText ["Monad m"]]
1149 ; constr = [ExpectHoverText ["Monad m"]]
1413− eitL40 = Position 44 28 ; kindE = [ExpectHoverText [":: * -> * -> *\n"]]
1150+ eitL40 = Position 40 28 ; kindE = [ExpectHoverText [":: * -> * -> *\n"]]
1414− intL40 = Position 44 34 ; kindI = [ExpectHoverText [":: *\n"]]
1151+ intL40 = Position 40 34 ; kindI = [ExpectHoverText [":: *\n"]]
1415− tvrL40 = Position 44 37 ; kindV = [ExpectHoverText [":: * -> *\n"]]
1152+ tvrL40 = Position 40 37 ; kindV = [ExpectHoverText [":: * -> *\n"]]
1416− intL41 = Position 45 20 ; litI = [ExpectHoverText ["7518"]]
1153+ intL41 = Position 41 20 ; litI = [ExpectHoverText ["7518"]]
1417− chrL36 = Position 41 24 ; litC = [ExpectHoverText ["'f'"]]
1154+ chrL36 = Position 37 24 ; litC = [ExpectHoverText ["'f'"]]
1418− txtL8 = Position 12 14 ; litT = [ExpectHoverText ["\"dfgy\""]]
1155+ txtL8 = Position 8 14 ; litT = [ExpectHoverText ["\"dfgv\""]]
1419− lstL43 = Position 47 12 ; litL = [ExpectHoverText ["[8391 :: Int, 6268]"]]
1156+ lstL43 = Position 43 12 ; litL = [ExpectHoverText ["[ 8391 :: Int, 6268 ]"]]
1420− outL45 = Position 49 3 ; outSig = [ExpectHoverText ["outer", "Bool"], mkR 46 0 46 5]
1157+ 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]
1158+ 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
1160 mkFindTests
1426− -- def hover look expect
1161+ -- def hover look expect
1427− [ test yes yes fffL4 fff "field in record definition"
1162+ [ test yes yes fffL4 fff "field in record definition"
1428− , test broken broken fffL8 fff "field in record construction #71"
1163+ , 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
1164+ , test yes yes fffL14 fff "field name used as accessor" -- 120 in Calculate.hs
1430− , test yes yes aaaL14 aaa "top-level name" -- 120
1165+ , test yes yes aaaL14 aaa "top-level name" -- 120
1431− , test yes yes dcL7 tcDC "data constructor record #247"
1166+ , test yes yes dcL7 tcDC "data constructor record #247"
1432− , test yes yes dcL12 tcDC "data constructor plain" -- 121
1167+ , test yes yes dcL12 tcDC "data constructor plain" -- 121
1433− , test yes yes tcL6 tcData "type constructor #248" -- 147
1168+ , test yes yes tcL6 tcData "type constructor #248" -- 147
1434− , test broken yes xtcL5 xtc "type constructor external #248,249"
1169+ , test broken yes xtcL5 xtc "type constructor external #248,249"
1435− , test broken yes xvL20 xvMsg "value external package #249" -- 120
1170+ , test broken yes xvL20 xvMsg "value external package #249" -- 120
1436− , test yes yes vvL16 vv "plain parameter" -- 120
1171+ , test yes yes vvL16 vv "plain parameter" -- 120
1437− , test yes yes aL18 apmp "pattern match name" -- 120
1172+ , test yes yes aL18 apmp "pattern match name" -- 120
1438− , test yes yes opL16 op "top-level operator" -- 120, 123
1173+ , test yes yes opL16 op "top-level operator" -- 120, 123
1439− , test yes yes opL18 opp "parameter operator" -- 120
1174+ , test yes yes opL18 opp "parameter operator" -- 120
1440− , test yes yes b'L19 bp "name in backticks" -- 120
1175+ , test yes yes b'L19 bp "name in backticks" -- 120
1441− , test yes yes clL23 cls "class in instance declaration #250"
1176+ , test yes yes clL23 cls "class in instance declaration #250"
1442− , test yes yes clL25 cls "class in signature #250" -- 147
1177+ , test yes yes clL25 cls "class in signature #250" -- 147
1443− , test broken yes eclL15 ecls "external class in signature #249,250"
1178+ , test broken yes eclL15 ecls "external class in signature #249,250"
1444− , test yes yes dnbL29 dnb "do-notation bind" -- 137
1179+ , test yes yes dnbL29 dnb "do-notation bind" -- 137
1445− , test yes yes dnbL30 dnb "do-notation lookup"
1180+ , test yes yes dnbL30 dnb "do-notation lookup"
1446− , test yes yes lcbL33 lcb "listcomp bind" -- 137
1181+ , test yes yes lcbL33 lcb "listcomp bind" -- 137
1447− , test yes yes lclL33 lcb "listcomp lookup"
1182+ , test yes yes lclL33 lcb "listcomp lookup"
1448− , test yes yes mclL36 mcl "top-level fn 1st clause"
1183+ , test yes yes mclL36 mcl "top-level fn 1st clause"
1449− , test yes yes mclL37 mcl "top-level fn 2nd clause #246"
1184+ , test yes yes mclL37 mcl "top-level fn 2nd clause #246"
1450− , test yes yes spaceL37 space "top-level fn on space #315"
1185+ , test yes yes spaceL37 space "top-level fn on space #315"
1451− , test no broken docL41 doc "documentation #7"
1186+ , test no broken docL41 doc "documentation #7"
1452− , test no yes eitL40 kindE "kind of Either #273"
1187+ , test no yes eitL40 kindE "kind of Either #273"
1453− , test no yes intL40 kindI "kind of Int #273"
1188+ , test no yes intL40 kindI "kind of Int #273"
1454− , test no broken tvrL40 kindV "kind of (* -> *) type variable #273"
1189+ , test no broken tvrL40 kindV "kind of (* -> *) type variable #273"
1455− , test no yes intL41 litI "literal Int in hover info #274"
1190+ , test no yes intL41 litI "literal Int in hover info #274"
1456− , test no yes chrL36 litC "literal Char in hover info #274"
1191+ , test no yes chrL36 litC "literal Char in hover info #274"
1457− , test no yes txtL8 litT "literal Text in hover info #274"
1192+ , test no broken txtL8 litT "literal Text in hover info #274"
1458− , test no yes lstL43 litL "literal List in hover info #274"
1193+ , test no broken lstL43 litL "literal List in hover info #274"
1459− , test no yes docL41 constr "type constraint in hover info #283"
1194+ , test no yes docL41 constr "type constraint in hover info #283"
1460− , test broken broken outL45 outSig "top-level signature #310"
1195+ , test broken broken outL45 outSig "top-level signature #310"
1461− , test broken broken innL48 innSig "inner signature #310"
1196+ , 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)
1198 where yes, broken :: (TestTree -> Maybe TestTree)
1466 yes = Just -- test should run and pass
1199 yes = Just -- test should run and pass
1467 broken = Just . (`xfail` "known broken")
1200 broken = Just . (`xfail` "known broken")
1468 no = const Nothing -- don't run this test at all
1201 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
1203pluginTests :: TestTree
1479−pluginTests = (`xfail8101` "known broken (#556)")
1480− $ testSessionWait "plugins" $ do
1204+pluginTests = testSessionWait "plugins" $ do
1481 let content =
1205 let content =
1482 T.unlines
1206 T.unlines
1483 [ "{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}"
1207 [ "{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}"
@@ -1491,7 +1215,7 @@ pluginTests = (`xfail8101` "known broken (#556)")
1491 , "foo :: Int -> Int -> Int"
1215 , "foo :: Int -> Int -> Int"
1492 , "foo a b = a + c"
1216 , "foo a b = a + c"
1494− _ <- createDoc "Testing.hs" "haskell" content
1218+ _ <- openDoc' "Testing.hs" "haskell" content
1495 expectDiagnostics
1219 expectDiagnostics
1496 [ ( "Testing.hs",
1220 [ ( "Testing.hs",
1497 [(DsError, (8, 14), "Variable not in scope: c")]
1221 [(DsError, (8, 14), "Variable not in scope: c")]
@@ -1500,39 +1224,26 @@ pluginTests = (`xfail8101` "known broken (#556)")
1501cppTests :: TestTree
1225cppTests :: TestTree
1502cppTests =
1226cppTests =
1504− [ testCase "cpp-error" $ do
1227+ testCase "cpp" $ do
1505− let content =
1228+ let content =
1506− T.unlines
1229+ T.unlines
1507− [ "{-# LANGUAGE CPP #-}",
1230+ [ "{-# LANGUAGE CPP #-}",
1508− "module Testing where",
1231+ "module Testing where",
1509− "#ifdef FOO",
1232+ "#ifdef FOO",
1510− "foo = 42"
1233+ "foo = 42"
1512− -- The error locations differ depending on which C-preprocessor is used.
1235+ -- The error locations differ depending on which C-preprocessor is used.
1513− -- Some give the column number and others don't (hence -1). Assert either
1236+ -- Some give the column number and others don't (hence -1). Assert either
1514− -- of them.
1237+ -- of them.
1515− (run $ expectError content (2, -1))
1238+ (run $ expectError content (2, -1))
1516− `catch` ( \e -> do
1239+ `catch` ( \e -> do
1517− let _ = e :: HUnitFailure
1240+ let _ = e :: HUnitFailure
1518− run $ expectError content (2, 1)
1241+ run $ expectError content (2, 1)
1520− , testSessionWait "cpp-ghcide" $ do
1521− _ <- createDoc "A.hs" "haskell" $ T.unlines
1522− ["{-# LANGUAGE CPP #-}"
1524− ,"#ifdef __GHCIDE__"
1530− expectDiagnostics [("A.hs", [(DsError, (3, 2), "Variable not in scope: worked")])]
1533 expectError :: T.Text -> Cursor -> Session ()
1244 expectError :: T.Text -> Cursor -> Session ()
1534 expectError content cursor = do
1245 expectError content cursor = do
1535− _ <- createDoc "Testing.hs" "haskell" content
1246+ _ <- openDoc' "Testing.hs" "haskell" content
1536 expectDiagnostics
1247 expectDiagnostics
1537 [ ( "Testing.hs",
1248 [ ( "Testing.hs",
1538 [(DsError, cursor, "error: unterminated")]
1249 [(DsError, cursor, "error: unterminated")]
@@ -1548,43 +1259,13 @@ preprocessorTests = testSessionWait "preprocessor" $ do
1548 , "module Testing where"
1259 , "module Testing where"
1549 , "y = x + z" -- plugin replaces x with y, making this have only one diagnostic
1260 , "y = x + z" -- plugin replaces x with y, making this have only one diagnostic
1551− _ <- createDoc "Testing.hs" "haskell" content
1262+ _ <- openDoc' "Testing.hs" "haskell" content
1552 expectDiagnostics
1263 expectDiagnostics
1553 [ ( "Testing.hs",
1264 [ ( "Testing.hs",
1554 [(DsError, (2, 8), "Variable not in scope: z")]
1265 [(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
1269thTests :: TestTree
1589thTests =
1270thTests =
1590 testGroup
1271 testGroup
@@ -1610,30 +1291,9 @@ thTests =
1610 "b :: Integer",
1291 "b :: Integer",
1611 "b = $(litE $ IntegerL $ a) + n"
1292 "b = $(litE $ IntegerL $ a) + n"
1613− _ <- createDoc "A.hs" "haskell" sourceA
1294+ _ <- openDoc' "A.hs" "haskell" sourceA
1614− _ <- createDoc "B.hs" "haskell" sourceB
1295+ _ <- openDoc' "B.hs" "haskell" sourceB
1615 expectDiagnostics [ ( "B.hs", [(DsError, (6, 29), "Variable not in scope: n")] ) ]
1296 expectDiagnostics [ ( "B.hs", [(DsError, (6, 29), "Variable not in scope: n")] ) ]
1616− , testSessionWait "newtype-closure" $ do
1619− [ "{-# LANGUAGE DeriveDataTypeable #-}"
1620− ,"{-# LANGUAGE TemplateHaskell #-}"
1621− ,"module A (a) where"
1622− ,"import Data.Data"
1623− ,"import Language.Haskell.TH"
1624− ,"newtype A = A () deriving (Data)"
1629− [ "{-# LANGUAGE TemplateHaskell #-}"
1634− _ <- createDoc "A.hs" "haskell" sourceA
1635− _ <- createDoc "B.hs" "haskell" sourceB
1639completionTests :: TestTree
1299completionTests :: TestTree
@@ -1641,31 +1301,31 @@ completionTests
1641 = testGroup "completion"
1301 = testGroup "completion"
1642 [ testSessionWait "variable" $ do
1302 [ testSessionWait "variable" $ do
1643 let source = T.unlines ["module A where", "f = hea"]
1303 let source = T.unlines ["module A where", "f = hea"]
1644− docId <- createDoc "A.hs" "haskell" source
1304+ docId <- openDoc' "A.hs" "haskell" source
1645 compls <- getCompletions docId (Position 1 7)
1305 compls <- getCompletions docId (Position 1 7)
1646− liftIO $ map dropDocs compls @?=
1306+ liftIO $ map dropDocs compls @?=
1647 [complItem "head" (Just CiFunction) (Just "[a] -> a")]
1307 [complItem "head" (Just CiFunction) (Just "[a] -> a")]
1648 let [CompletionItem { _documentation = headDocs}] = compls
1308 let [CompletionItem { _documentation = headDocs}] = compls
1649 checkDocText "head" headDocs [ "Defined in 'Prelude'"
1309 checkDocText "head" headDocs [ "Defined in 'Prelude'"
1650−#if MIN_GHC_API_VERSION(8,6,5)
1310+#if MIN_GHC_API_VERSION(8,6,0)
1651 , "Extract the first element of a list"
1311 , "Extract the first element of a list"
1654 , testSessionWait "constructor" $ do
1314 , testSessionWait "constructor" $ do
1655 let source = T.unlines ["module A where", "f = Tru"]
1315 let source = T.unlines ["module A where", "f = Tru"]
1656− docId <- createDoc "A.hs" "haskell" source
1316+ docId <- openDoc' "A.hs" "haskell" source
1657 compls <- getCompletions docId (Position 1 7)
1317 compls <- getCompletions docId (Position 1 7)
1658− liftIO $ map dropDocs compls @?=
1318+ liftIO $ map dropDocs compls @?=
1659 [ complItem "True" (Just CiConstructor) (Just "Bool")
1319 [ complItem "True" (Just CiConstructor) (Just "Bool")
1660#if MIN_GHC_API_VERSION(8,6,0)
1320#if MIN_GHC_API_VERSION(8,6,0)
1661 , complItem "truncate" (Just CiFunction) (Just "(RealFrac a, Integral b) => a -> b")
1321 , complItem "truncate" (Just CiFunction) (Just "(RealFrac a, Integral b) => a -> b")
1663− , complItem "truncate" (Just CiFunction) (Just "RealFrac a => forall b. Integral b => a -> b")
1323+ , complItem "truncate" (Just CiFunction) (Just "RealFrac a => forall b. Integral b => a -> b")
1666 , testSessionWait "type" $ do
1326 , testSessionWait "type" $ do
1667 let source = T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: ()", "f = ()"]
1327 let source = T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: ()", "f = ()"]
1668− docId <- createDoc "A.hs" "haskell" source
1328+ docId <- openDoc' "A.hs" "haskell" source
1669 expectDiagnostics [ ("A.hs", [(DsWarning, (3,0), "not used")]) ]
1329 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"]]
1330 changeDoc docId [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: Bo", "f = True"]]
1671 compls <- getCompletions docId (Position 2 7)
1331 compls <- getCompletions docId (Position 2 7)
@@ -1675,51 +1335,30 @@ completionTests
1675 let [ CompletionItem { _documentation = boundedDocs},
1335 let [ CompletionItem { _documentation = boundedDocs},
1676 CompletionItem { _documentation = boolDocs } ] = compls
1336 CompletionItem { _documentation = boolDocs } ] = compls
1677 checkDocText "Bounded" boundedDocs [ "Defined in 'Prelude'"
1337 checkDocText "Bounded" boundedDocs [ "Defined in 'Prelude'"
1678−#if MIN_GHC_API_VERSION(8,6,5)
1338+#if MIN_GHC_API_VERSION(8,6,0)
1679 , "name the upper and lower limits"
1339 , "name the upper and lower limits"
1682 checkDocText "Bool" boolDocs [ "Defined in 'Prelude'" ]
1342 checkDocText "Bool" boolDocs [ "Defined in 'Prelude'" ]
1683 , testSessionWait "qualified" $ do
1343 , testSessionWait "qualified" $ do
1684 let source = T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = ()"]
1344 let source = T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = ()"]
1685− docId <- createDoc "A.hs" "haskell" source
1345+ docId <- openDoc' "A.hs" "haskell" source
1686 expectDiagnostics [ ("A.hs", [(DsWarning, (2, 0), "not used")]) ]
1346 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"]]
1347 changeDoc docId [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = Prelude.hea"]]
1688 compls <- getCompletions docId (Position 2 15)
1348 compls <- getCompletions docId (Position 2 15)
1689− liftIO $ map dropDocs compls @?=
1349+ liftIO $ map dropDocs compls @?=
1690 [complItem "head" (Just CiFunction) (Just "[a] -> a")]
1350 [complItem "head" (Just CiFunction) (Just "[a] -> a")]
1691 let [CompletionItem { _documentation = headDocs}] = compls
1351 let [CompletionItem { _documentation = headDocs}] = compls
1692 checkDocText "head" headDocs [ "Defined in 'Prelude'"
1352 checkDocText "head" headDocs [ "Defined in 'Prelude'"
1693−#if MIN_GHC_API_VERSION(8,6,5)
1353+#if MIN_GHC_API_VERSION(8,6,0)
1694 , "Extract the first element of a list"
1354 , "Extract the first element of a list"
1697 , testSessionWait "keyword" $ do
1357 , testSessionWait "keyword" $ do
1698 let source = T.unlines ["module A where", "f = newty"]
1358 let source = T.unlines ["module A where", "f = newty"]
1699− docId <- createDoc "A.hs" "haskell" source
1359+ docId <- openDoc' "A.hs" "haskell" source
1700 compls <- getCompletions docId (Position 1 9)
1360 compls <- getCompletions docId (Position 1 9)
1701 liftIO $ compls @?= [keywordItem "newtype"]
1361 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
1364 dropDocs :: CompletionItem -> CompletionItem
@@ -1727,7 +1366,6 @@ completionTests
1727 complItem label kind ty = CompletionItem
1366 complItem label kind ty = CompletionItem
1728 { _label = label
1367 { _label = label
1729 , _kind = kind
1368 , _kind = kind
1731 , _detail = (":: " <>) <$> ty
1369 , _detail = (":: " <>) <$> ty
1732 , _documentation = Nothing
1370 , _documentation = Nothing
1733 , _deprecated = Nothing
1371 , _deprecated = Nothing
@@ -1745,7 +1383,6 @@ completionTests
1745 keywordItem label = CompletionItem
1383 keywordItem label = CompletionItem
1746 { _label = label
1384 { _label = label
1747 , _kind = Just CiKeyword
1385 , _kind = Just CiKeyword
1749 , _detail = Nothing
1386 , _detail = Nothing
1750 , _documentation = Nothing
1387 , _documentation = Nothing
1751 , _deprecated = Nothing
1388 , _deprecated = Nothing
@@ -1773,7 +1410,7 @@ outlineTests = testGroup
1773 "outline"
1410 "outline"
1774 [ testSessionWait "type class" $ do
1411 [ testSessionWait "type class" $ do
1775 let source = T.unlines ["module A where", "class A a where a :: a -> Bool"]
1412 let source = T.unlines ["module A where", "class A a where a :: a -> Bool"]
1776− docId <- createDoc "A.hs" "haskell" source
1413+ docId <- openDoc' "A.hs" "haskell" source
1777 symbols <- getDocumentSymbols docId
1414 symbols <- getDocumentSymbols docId
1778 liftIO $ symbols @?= Left
1415 liftIO $ symbols @?= Left
1779 [ moduleSymbol
1416 [ moduleSymbol
@@ -1786,7 +1423,7 @@ outlineTests = testGroup
1787 , testSessionWait "type class instance " $ do
1424 , testSessionWait "type class instance " $ do
1788 let source = T.unlines ["class A a where", "instance A () where"]
1425 let source = T.unlines ["class A a where", "instance A () where"]
1789− docId <- createDoc "A.hs" "haskell" source
1426+ docId <- openDoc' "A.hs" "haskell" source
1790 symbols <- getDocumentSymbols docId
1427 symbols <- getDocumentSymbols docId
1791 liftIO $ symbols @?= Left
1428 liftIO $ symbols @?= Left
1792 [ classSymbol "A a" (R 0 0 0 15) []
1429 [ classSymbol "A a" (R 0 0 0 15) []
@@ -1794,7 +1431,7 @@ outlineTests = testGroup
1795 , testSessionWait "type family" $ do
1432 , testSessionWait "type family" $ do
1796 let source = T.unlines ["{-# language TypeFamilies #-}", "type family A"]
1433 let source = T.unlines ["{-# language TypeFamilies #-}", "type family A"]
1797− docId <- createDoc "A.hs" "haskell" source
1434+ docId <- openDoc' "A.hs" "haskell" source
1798 symbols <- getDocumentSymbols docId
1435 symbols <- getDocumentSymbols docId
1799 liftIO $ symbols @?= Left [docSymbolD "A" "type family" SkClass (R 1 0 1 13)]
1436 liftIO $ symbols @?= Left [docSymbolD "A" "type family" SkClass (R 1 0 1 13)]
1800 , testSessionWait "type family instance " $ do
1437 , testSessionWait "type family instance " $ do
@@ -1803,7 +1440,7 @@ outlineTests = testGroup
1803 , "type family A a"
1440 , "type family A a"
1804 , "type instance A () = ()"
1441 , "type instance A () = ()"
1806− docId <- createDoc "A.hs" "haskell" source
1443+ docId <- openDoc' "A.hs" "haskell" source
1807 symbols <- getDocumentSymbols docId
1444 symbols <- getDocumentSymbols docId
1808 liftIO $ symbols @?= Left
1445 liftIO $ symbols @?= Left
1809 [ docSymbolD "A a" "type family" SkClass (R 1 0 1 15)
1446 [ docSymbolD "A a" "type family" SkClass (R 1 0 1 15)
@@ -1811,7 +1448,7 @@ outlineTests = testGroup
1812 , testSessionWait "data family" $ do
1449 , testSessionWait "data family" $ do
1813 let source = T.unlines ["{-# language TypeFamilies #-}", "data family A"]
1450 let source = T.unlines ["{-# language TypeFamilies #-}", "data family A"]
1814− docId <- createDoc "A.hs" "haskell" source
1451+ docId <- openDoc' "A.hs" "haskell" source
1815 symbols <- getDocumentSymbols docId
1452 symbols <- getDocumentSymbols docId
1816 liftIO $ symbols @?= Left [docSymbolD "A" "data family" SkClass (R 1 0 1 11)]
1453 liftIO $ symbols @?= Left [docSymbolD "A" "data family" SkClass (R 1 0 1 11)]
1817 , testSessionWait "data family instance " $ do
1454 , testSessionWait "data family instance " $ do
@@ -1820,7 +1457,7 @@ outlineTests = testGroup
1820 , "data family A a"
1457 , "data family A a"
1821 , "data instance A () = A ()"
1458 , "data instance A () = A ()"
1823− docId <- createDoc "A.hs" "haskell" source
1460+ docId <- openDoc' "A.hs" "haskell" source
1824 symbols <- getDocumentSymbols docId
1461 symbols <- getDocumentSymbols docId
1825 liftIO $ symbols @?= Left
1462 liftIO $ symbols @?= Left
1826 [ docSymbolD "A a" "data family" SkClass (R 1 0 1 11)
1463 [ docSymbolD "A a" "data family" SkClass (R 1 0 1 11)
@@ -1828,36 +1465,36 @@ outlineTests = testGroup
1829 , testSessionWait "constant" $ do
1466 , testSessionWait "constant" $ do
1830 let source = T.unlines ["a = ()"]
1467 let source = T.unlines ["a = ()"]
1831− docId <- createDoc "A.hs" "haskell" source
1468+ docId <- openDoc' "A.hs" "haskell" source
1832 symbols <- getDocumentSymbols docId
1469 symbols <- getDocumentSymbols docId
1833 liftIO $ symbols @?= Left
1470 liftIO $ symbols @?= Left
1834 [docSymbol "a" SkFunction (R 0 0 0 6)]
1471 [docSymbol "a" SkFunction (R 0 0 0 6)]
1835 , testSessionWait "pattern" $ do
1472 , testSessionWait "pattern" $ do
1836 let source = T.unlines ["Just foo = Just 21"]
1473 let source = T.unlines ["Just foo = Just 21"]
1837− docId <- createDoc "A.hs" "haskell" source
1474+ docId <- openDoc' "A.hs" "haskell" source
1838 symbols <- getDocumentSymbols docId
1475 symbols <- getDocumentSymbols docId
1839 liftIO $ symbols @?= Left
1476 liftIO $ symbols @?= Left
1840 [docSymbol "Just foo" SkFunction (R 0 0 0 18)]
1477 [docSymbol "Just foo" SkFunction (R 0 0 0 18)]
1841 , testSessionWait "pattern with type signature" $ do
1478 , testSessionWait "pattern with type signature" $ do
1842 let source = T.unlines ["{-# language ScopedTypeVariables #-}", "a :: () = ()"]
1479 let source = T.unlines ["{-# language ScopedTypeVariables #-}", "a :: () = ()"]
1843− docId <- createDoc "A.hs" "haskell" source
1480+ docId <- openDoc' "A.hs" "haskell" source
1844 symbols <- getDocumentSymbols docId
1481 symbols <- getDocumentSymbols docId
1845 liftIO $ symbols @?= Left
1482 liftIO $ symbols @?= Left
1846 [docSymbol "a :: ()" SkFunction (R 1 0 1 12)]
1483 [docSymbol "a :: ()" SkFunction (R 1 0 1 12)]
1847 , testSessionWait "function" $ do
1484 , testSessionWait "function" $ do
1848 let source = T.unlines ["a x = ()"]
1485 let source = T.unlines ["a x = ()"]
1849− docId <- createDoc "A.hs" "haskell" source
1486+ docId <- openDoc' "A.hs" "haskell" source
1850 symbols <- getDocumentSymbols docId
1487 symbols <- getDocumentSymbols docId
1851 liftIO $ symbols @?= Left [docSymbol "a" SkFunction (R 0 0 0 8)]
1488 liftIO $ symbols @?= Left [docSymbol "a" SkFunction (R 0 0 0 8)]
1852 , testSessionWait "type synonym" $ do
1489 , testSessionWait "type synonym" $ do
1853 let source = T.unlines ["type A = Bool"]
1490 let source = T.unlines ["type A = Bool"]
1854− docId <- createDoc "A.hs" "haskell" source
1491+ docId <- openDoc' "A.hs" "haskell" source
1855 symbols <- getDocumentSymbols docId
1492 symbols <- getDocumentSymbols docId
1856 liftIO $ symbols @?= Left
1493 liftIO $ symbols @?= Left
1857 [docSymbol' "A" SkTypeParameter (R 0 0 0 13) (R 0 5 0 6)]
1494 [docSymbol' "A" SkTypeParameter (R 0 0 0 13) (R 0 5 0 6)]
1858 , testSessionWait "datatype" $ do
1495 , testSessionWait "datatype" $ do
1859 let source = T.unlines ["data A = C"]
1496 let source = T.unlines ["data A = C"]
1860− docId <- createDoc "A.hs" "haskell" source
1497+ docId <- openDoc' "A.hs" "haskell" source
1861 symbols <- getDocumentSymbols docId
1498 symbols <- getDocumentSymbols docId
1862 liftIO $ symbols @?= Left
1499 liftIO $ symbols @?= Left
1863 [ docSymbolWithChildren "A"
1500 [ docSymbolWithChildren "A"
@@ -1865,47 +1502,18 @@ outlineTests = testGroup
1865 (R 0 0 0 10)
1502 (R 0 0 0 10)
1866 [docSymbol "C" SkConstructor (R 0 9 0 10)]
1503 [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
1505 , testSessionWait "import" $ do
1881 let source = T.unlines ["import Data.Maybe"]
1506 let source = T.unlines ["import Data.Maybe"]
1882− docId <- createDoc "A.hs" "haskell" source
1507+ docId <- openDoc' "A.hs" "haskell" source
1883 symbols <- getDocumentSymbols docId
1508 symbols <- getDocumentSymbols docId
1884 liftIO $ symbols @?= Left
1509 liftIO $ symbols @?= Left
1885− [docSymbolWithChildren "imports"
1888− [ docSymbol "import Data.Maybe" SkModule (R 0 0 0 17)
1510+ [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
1511 , testSessionWait "foreign import" $ do
1904 let source = T.unlines
1512 let source = T.unlines
1905 [ "{-# language ForeignFunctionInterface #-}"
1513 [ "{-# language ForeignFunctionInterface #-}"
1906 , "foreign import ccall \"a\" a :: Int"
1514 , "foreign import ccall \"a\" a :: Int"
1908− docId <- createDoc "A.hs" "haskell" source
1516+ docId <- openDoc' "A.hs" "haskell" source
1909 symbols <- getDocumentSymbols docId
1517 symbols <- getDocumentSymbols docId
1910 liftIO $ symbols @?= Left [docSymbolD "a" "import" SkObject (R 1 0 1 33)]
1518 liftIO $ symbols @?= Left [docSymbolD "a" "import" SkObject (R 1 0 1 33)]
1911 , testSessionWait "foreign export" $ do
1519 , testSessionWait "foreign export" $ do
@@ -1913,7 +1521,7 @@ outlineTests = testGroup
1913 [ "{-# language ForeignFunctionInterface #-}"
1521 [ "{-# language ForeignFunctionInterface #-}"
1914 , "foreign export ccall odd :: Int -> Bool"
1522 , "foreign export ccall odd :: Int -> Bool"
1916− docId <- createDoc "A.hs" "haskell" source
1524+ docId <- openDoc' "A.hs" "haskell" source
1917 symbols <- getDocumentSymbols docId
1525 symbols <- getDocumentSymbols docId
1918 liftIO $ symbols @?= Left [docSymbolD "odd" "export" SkObject (R 1 0 1 39)]
1526 liftIO $ symbols @?= Left [docSymbolD "odd" "export" SkObject (R 1 0 1 39)]
@@ -1926,8 +1534,6 @@ outlineTests = testGroup
1926 DocumentSymbol name (Just detail) kind Nothing loc loc Nothing
1534 DocumentSymbol name (Just detail) kind Nothing loc loc Nothing
1927 docSymbolWithChildren name kind loc cc =
1535 docSymbolWithChildren name kind loc cc =
1928 DocumentSymbol name Nothing kind Nothing loc loc (Just $ List cc)
1536 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
1537 moduleSymbol name loc cc = DocumentSymbol name
@@ -1949,16 +1555,8 @@ pattern R x y x' y' = Range (Position x y) (Position x' y')
1949xfail :: TestTree -> String -> TestTree
1555xfail :: TestTree -> String -> TestTree
1950xfail = flip expectFailBecause
1556xfail = flip expectFailBecause
1952−xfail8101 :: TestTree -> String -> TestTree
1953−#if MIN_GHC_API_VERSION(8,10,0)
1954−xfail8101 = flip expectFailBecause
1959data Expect
1558data Expect
1960 = ExpectRange Range -- Both gotoDef and hover should report this range
1559 = ExpectRange Range -- Both gotoDef and hover should report this range
1961− | ExpectLocation Location
1962-- | ExpectDefRange Range -- Only gotoDef should report this range
1560-- | ExpectDefRange Range -- Only gotoDef should report this range
1963 | ExpectHoverRange Range -- Only hover should report this range
1561 | ExpectHoverRange Range -- Only hover should report this range
1964 | ExpectHoverText [T.Text] -- the hover message must contain these snippets
1562 | ExpectHoverText [T.Text] -- the hover message must contain these snippets
@@ -1970,226 +1568,6 @@ data Expect
1971mkR :: Int -> Int -> Int -> Int -> Expect
1569mkR :: Int -> Int -> Int -> Int -> Expect
1972mkR startLine startColumn endLine endColumn = ExpectRange $ mkRange startLine startColumn endLine endColumn
1570mkR 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
1977−haddockTests :: TestTree
1979− = testGroup "haddock"
1980− [ testCase "Num" $ checkHaddock
1982− [ "However, '(+)' and '(*)' are"
1983− , "customarily expected to define a ring and have the following properties:"
1985− , "[__Associativity of (+)__]: @(x + y) + z@ = @x + (y + z)@"
1986− , "[__Commutativity of (+)__]: @x + y@ = @y + x@"
1987− , "[__@fromInteger 0@ is the additive identity__]: @x + fromInteger 0@ = @x@"
1993− , "However, `(+)` and `(*)` are"
1994− , "customarily expected to define a ring and have the following properties: "
1995− , "+ ****Associativity of (+)****: `(x + y) + z` = `x + (y + z)`"
1996− , "+ ****Commutativity of (+)****: `x + y` = `y + x`"
1997− , "+ ****`fromInteger 0` is the additive identity****: `x + fromInteger 0` = `x`"
2000− , testCase "unsafePerformIO" $ checkHaddock
2003− , "different precautions:"
2005− , " * Use @{\\-\\# NOINLINE foo \\#-\\}@ as a pragma on any function @foo@"
2006− , " that calls 'unsafePerformIO'. If the call is inlined,"
2007− , " the I\\/O may be performed more than once."
2009− , " * Use the compiler flag @-fno-cse@ to prevent common sub-expression"
2010− , " elimination being performed on the module."
2018− , "different precautions: "
2019− , "+ Use `{-# NOINLINE foo #-}` as a pragma on any function `foo` "
2020− , " that calls `unsafePerformIO` . If the call is inlined,"
2021− , " the I/O may be performed more than once."
2023− , "+ Use the compiler flag `-fno-cse` to prevent common sub-expression"
2024− , " elimination being performed on the module."
2030− 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
2156−sessionDepsArePickedUp :: TestTree
2157−sessionDepsArePickedUp = testSession'
2158− "session-deps-are-picked-up"
2162− (dir </> "hie.yaml")
2163− "cradle: {direct: {arguments: []}}"
2164− -- Open without OverloadedStrings and expect an error.
2165− doc <- createDoc "Foo.hs" "haskell" fooContent
2167− [("Foo.hs", [(DsError, (3, 6), "Couldn't match expected type")])]
2168− -- Update hie.yaml to enable OverloadedStrings.
2171− (dir </> "hie.yaml")
2172− "cradle: {direct: {arguments: [-XOverloadedStrings]}}"
2173− -- Send change event.
2175− TextDocumentContentChangeEvent
2176− { _range = Just (Range (Position 4 0) (Position 4 0)),
2177− _rangeLength = Nothing,
2180− changeDoc doc [change]
2182− expectDiagnostics [("Foo.hs", [])]
2186− [ "module Foo where",
2187− "import Data.Text",
2193----------------------------------------------------------------------
1571----------------------------------------------------------------------
@@ -2197,12 +1575,6 @@ sessionDepsArePickedUp = testSession'
2197testSession :: String -> Session () -> TestTree
1575testSession :: String -> Session () -> TestTree
2198testSession name = testCase name . run
1576testSession name = testCase name . run
2200−testSessionWithExtraFiles :: FilePath -> String -> (FilePath -> Session ()) -> TestTree
2201−testSessionWithExtraFiles prefix name = testCase name . runWithExtraFiles prefix
2203−testSession' :: String -> (FilePath -> Session ()) -> TestTree
2204−testSession' name = testCase name . run'
2206testSessionWait :: String -> Session () -> TestTree
1578testSessionWait :: String -> Session () -> TestTree
2207testSessionWait name = testSession name .
1579testSessionWait name = testSession name .
2208 -- Check that any diagnostics produced were already consumed by the test case.
1580 -- Check that any diagnostics produced were already consumed by the test case.
@@ -2213,53 +1585,24 @@ testSessionWait name = testSession name .
2213 -- Experimentally, 0.5s seems to be long enough to wait for any final diagnostics to appear.
1585 -- Experimentally, 0.5s seems to be long enough to wait for any final diagnostics to appear.
2214 ( >> expectNoMoreDiagnostics 0.5)
1586 ( >> expectNoMoreDiagnostics 0.5)
2216−pickActionWithTitle :: T.Text -> [CAResult] -> IO CodeAction
1588+pickActionWithTitle :: T.Text -> [CAResult] -> CodeAction
2217−pickActionWithTitle title actions = do
1589+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
1590+ [ action
2227− | CACodeAction action@CodeAction { _title = actionTitle } <- actions
1591+ | CACodeAction action@CodeAction{ _title = actionTitle } <- actions
2228− , title == actionTitle
1592+ , title == actionTitle ]
2231mkRange :: Int -> Int -> Int -> Int -> Range
1594mkRange :: Int -> Int -> Int -> Int -> Range
2232mkRange a b c d = Range (Position a b) (Position c d)
1595mkRange a b c d = Range (Position a b) (Position c d)
2234run :: Session a -> IO a
1597run :: Session a -> IO a
2235−run s = withTempDir $ \dir -> runInDir dir s
1598+run s = withTempDir $ \dir -> do
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)
2250−run' :: (FilePath -> Session a) -> IO a
2251−run' s = withTempDir $ \dir -> runInDir dir (s dir)
2253−runInDir :: FilePath -> Session a -> IO a
2255 ghcideExe <- locateGhcideExecutable
1599 ghcideExe <- locateGhcideExecutable
2257 -- Temporarily hack around https://github.com/mpickering/hie-bios/pull/56
1601 -- Temporarily hack around https://github.com/mpickering/hie-bios/pull/56
2258 -- since the package import test creates "Data/List.hs", which otherwise has no physical home
1602 -- since the package import test creates "Data/List.hs", which otherwise has no physical home
2259 createDirectoryIfMissing True $ dir ++ "/Data"
1603 createDirectoryIfMissing True $ dir ++ "/Data"
2262− let cmd = unwords [ghcideExe, "--lsp", "--test", "--cwd", dir]
1605+ let cmd = unwords [ghcideExe, "--lsp", "--cwd", dir]
2263 -- HIE calls getXgdDirectory which assumes that HOME is set.
1606 -- HIE calls getXgdDirectory which assumes that HOME is set.
2264 -- Only sets HOME if it wasn't already set.
1607 -- Only sets HOME if it wasn't already set.
2265 setEnv "HOME" "/homeless-shelter" False
1608 setEnv "HOME" "/homeless-shelter" False
@@ -2276,7 +1619,7 @@ runInDir dir s = do
2276openTestDataDoc :: FilePath -> Session TextDocumentIdentifier
1619openTestDataDoc :: FilePath -> Session TextDocumentIdentifier
2277openTestDataDoc path = do
1620openTestDataDoc path = do
2278 source <- liftIO $ readFileUtf8 $ "test/data" </> path
1621 source <- liftIO $ readFileUtf8 $ "test/data" </> path
2279− createDoc path "haskell" source
1622+ openDoc' path "haskell" source
2281findCodeActions :: TextDocumentIdentifier -> Range -> [T.Text] -> Session [CodeAction]
1624findCodeActions :: TextDocumentIdentifier -> Range -> [T.Text] -> Session [CodeAction]
2282findCodeActions doc range expectedTitles = do
1625findCodeActions doc range expectedTitles = do
@@ -2291,7 +1634,7 @@ findCodeActions doc range expectedTitles = do
2291 [ actionTitle
1634 [ actionTitle
2292 | CACodeAction CodeAction { _title = actionTitle } <- actions
1635 | CACodeAction CodeAction { _title = actionTitle } <- actions
2294− ++ " is not a superset of "
1637+ ++ "is not a superset of "
2295 ++ show expectedTitles
1638 ++ show expectedTitles
2296 liftIO $ case matches of
1639 liftIO $ case matches of
2297 Nothing -> assertFailure msg
1640 Nothing -> assertFailure msg
@@ -2304,193 +1647,13 @@ findCodeAction doc range t = head <$> findCodeActions doc range [t]
2304unitTests :: TestTree
1647unitTests :: TestTree
2305unitTests = do
1648unitTests = do
2306 testGroup "Unit"
1649 testGroup "Unit"
2307− [ testCase "empty file path does NOT work with the empty String literal" $
1650+ [ testCase "empty file path" $
2308− uriToFilePath' (fromNormalizedUri $ filePathToUri' "") @?= Just "."
1651+ 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 ""
2320−positionMappingTests :: TestTree
1654+-- | Wrapper around 'LSPTest.openDoc'' that sends file creation events
2321−positionMappingTests =
1655+openDoc' :: FilePath -> String -> T.Text -> Session TextDocumentIdentifier
2322− testGroup "position mapping"
1656+openDoc' fp name contents = do
2323− [ testGroup "toCurrent"
1657+ res@(TextDocumentIdentifier uri) <- LSPTest.openDoc' fp name contents
2324− [ testCase "before" $
1658+ sendNotification WorkspaceDidChangeWatchedFiles (DidChangeWatchedFilesParams $ List [FileEvent uri FcCreated])
2325− toCurrent
1659+ return res
2326− (Range (Position 0 1) (Position 0 3))
2328− (Position 0 0) @?= Just (Position 0 0)
2329− , testCase "after, same line, same length" $
2331− (Range (Position 0 1) (Position 0 3))
2333− (Position 0 3) @?= Just (Position 0 3)
2334− , testCase "after, same line, increased length" $
2336− (Range (Position 0 1) (Position 0 3))
2338− (Position 0 3) @?= Just (Position 0 4)
2339− , testCase "after, same line, decreased length" $
2341− (Range (Position 0 1) (Position 0 3))
2343− (Position 0 3) @?= Just (Position 0 2)
2344− , testCase "after, next line, no newline" $
2346− (Range (Position 0 1) (Position 0 3))
2348− (Position 1 3) @?= Just (Position 1 3)
2349− , testCase "after, next line, newline" $
2351− (Range (Position 0 1) (Position 0 3))
2353− (Position 1 0) @?= Just (Position 2 0)
2354− , testCase "after, same line, newline" $
2356− (Range (Position 0 1) (Position 0 3))
2358− (Position 0 4) @?= Just (Position 1 2)
2359− , testCase "after, same line, newline + newline at end" $
2361− (Range (Position 0 1) (Position 0 3))
2363− (Position 0 4) @?= Just (Position 2 1)
2364− , testCase "after, same line, newline + newline at end" $
2366− (Range (Position 0 1) (Position 0 1))
2368− (Position 0 1) @?= Just (Position 0 4)
2370− , testGroup "fromCurrent"
2371− [ testCase "before" $
2373− (Range (Position 0 1) (Position 0 3))
2375− (Position 0 0) @?= Just (Position 0 0)
2376− , testCase "after, same line, same length" $
2378− (Range (Position 0 1) (Position 0 3))
2380− (Position 0 3) @?= Just (Position 0 3)
2381− , testCase "after, same line, increased length" $
2383− (Range (Position 0 1) (Position 0 3))
2385− (Position 0 4) @?= Just (Position 0 3)
2386− , testCase "after, same line, decreased length" $
2388− (Range (Position 0 1) (Position 0 3))
2390− (Position 0 2) @?= Just (Position 0 3)
2391− , testCase "after, next line, no newline" $
2393− (Range (Position 0 1) (Position 0 3))
2395− (Position 1 3) @?= Just (Position 1 3)
2396− , testCase "after, next line, newline" $
2398− (Range (Position 0 1) (Position 0 3))
2400− (Position 2 0) @?= Just (Position 1 0)
2401− , testCase "after, same line, newline" $
2403− (Range (Position 0 1) (Position 0 3))
2405− (Position 1 2) @?= Just (Position 0 4)
2406− , testCase "after, same line, newline + newline at end" $
2408− (Range (Position 0 1) (Position 0 3))
2410− (Position 2 1) @?= Just (Position 0 4)
2411− , testCase "after, same line, newline + newline at end" $
2413− (Range (Position 0 1) (Position 0 1))
2415− (Position 0 4) @?= Just (Position 0 1)
2417− , adjustOption (\(QuickCheckTests i) -> QuickCheckTests (max 1000 i)) $ testGroup "properties"
2418− [ testProperty "fromCurrent r t <=< toCurrent r t" $ do
2419− -- Note that it is important to use suchThatMap on all values at once
2420− -- instead of only using it on the position. Otherwise you can get
2421− -- into situations where there is no position that can be mapped back
2422− -- for the edit which will result in QuickCheck looping forever.
2425− range <- genRange rope
2426− PrintableText replacement <- arbitrary
2427− oldPos <- genPosition rope
2428− pure (range, replacement, oldPos)
2431− (\(range, replacement, oldPos) -> (range, replacement, oldPos,) <$> toCurrent range replacement oldPos)) $
2432− \(range, replacement, oldPos, newPos) ->
2433− fromCurrent range replacement newPos === Just oldPos
2434− , testProperty "toCurrent r t <=< fromCurrent r t" $ do
2437− range <- genRange rope
2438− PrintableText replacement <- arbitrary
2439− let newRope = applyChange rope (TextDocumentContentChangeEvent (Just range) Nothing replacement)
2440− newPos <- genPosition newRope
2441− pure (range, replacement, newPos)
2444− (\(range, replacement, newPos) -> (range, replacement, newPos,) <$> fromCurrent range replacement newPos)) $
2445− \(range, replacement, newPos, oldPos) ->
2446− toCurrent range replacement oldPos === Just newPos
2450−newtype PrintableText = PrintableText { getPrintableText :: T.Text }
2453−instance Arbitrary PrintableText where
2454− arbitrary = PrintableText . T.pack . getPrintableString <$> arbitrary
2458−genRope = Rope.fromText . getPrintableText <$> arbitrary
2460−genPosition :: Rope -> Gen Position
2462− row <- choose (0, max 0 $ rows - 1)
2463− let columns = Rope.columns (nthLine row r)
2464− column <- choose (0, max 0 $ columns - 1)
2465− pure $ Position row column
2466− where rows = Rope.rows r
2468−genRange :: Rope -> Gen Range
2470− startPos@(Position startLine startColumn) <- genPosition r
2471− let maxLineDiff = max 0 $ rows - 1 - startLine
2472− endLine <- choose (startLine, startLine + maxLineDiff)
2473− let columns = Rope.columns (nthLine endLine r)
2475− if startLine == endLine
2476− then choose (startColumn, columns)
2477− else choose (0, max 0 $ columns - 1)
2478− pure $ Range startPos (Position endLine endColumn)
2479− where rows = Rope.rows r
2481−-- | Get the ith line of a rope, starting from 0. Trailing newline not included.
2482−nthLine :: Int -> Rope -> Rope
2484− | i < 0 = error $ "Negative line number: " <> show i
2485− | i == 0 && Rope.rows r == 0 = r
2486− | 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
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