Skip to content

Commit 75ff238

Browse files
authored
Multi component issues in GHC 9.2 (#2687)
* Delete useAnnotatedParsedSource (not used anywhere) * Multi component test suite: test packages * Multi component test suite: replace delays with waits * Multi component: test with 3 components * Helpers for reference/ready message parsing * Multi component test: wait for reference ready * mark test as known broken in 9.2
1 parent 7c02148 commit 75ff238

File tree

9 files changed

+73
-46
lines changed

9 files changed

+73
-46
lines changed

ghcide/src/Development/IDE/GHC/ExactPrint.hs

-11
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ module Development.IDE.GHC.ExactPrint
2323
transformM,
2424
ExactPrint(..),
2525
#if !MIN_VERSION_ghc(9,2,0)
26-
useAnnotatedSource,
2726
Anns,
2827
Annotate,
2928
setPrecedingLinesT,
@@ -122,16 +121,6 @@ annotateParsedSource :: ParsedModule -> Annotated ParsedSource
122121
annotateParsedSource = fixAnns
123122
#endif
124123

125-
#if !MIN_VERSION_ghc(9,2,0)
126-
useAnnotatedSource ::
127-
String ->
128-
IdeState ->
129-
NormalizedFilePath ->
130-
IO (Maybe (Annotated ParsedSource))
131-
useAnnotatedSource herald state nfp =
132-
runAction herald state (use GetAnnotatedParsedSource nfp)
133-
#endif
134-
135124
------------------------------------------------------------------------------
136125

137126
{- | A transformation for grafting source trees together. Use the semigroup

ghcide/test/data/multi/a/A.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module A(foo) where
2-
2+
import Control.Concurrent.Async
33
foo = ()

ghcide/test/data/multi/a/a.cabal

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ build-type: Simple
44
cabal-version: >= 1.2
55

66
library
7-
build-depends: base
7+
build-depends: base, async
88
exposed-modules: A
99
hs-source-dirs: .

ghcide/test/data/multi/c/C.hs

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module C(module C) where
2+
import A
3+
cux = foo

ghcide/test/data/multi/c/c.cabal

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name: c
2+
version: 1.0.0
3+
build-type: Simple
4+
cabal-version: >= 1.2
5+
6+
library
7+
build-depends: base, a
8+
exposed-modules: C
9+
hs-source-dirs: .

ghcide/test/data/multi/cabal.project

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
packages: a b
1+
packages: a b c

ghcide/test/data/multi/hie.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ cradle:
44
component: "lib:a"
55
- path: "./b"
66
component: "lib:b"
7+
- path: "./c"
8+
component: "lib:c"

ghcide/test/exe/Main.hs

+35-31
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ import Development.IDE.Test (Cursor,
5858
standardizeQuotes,
5959
waitForAction,
6060
waitForGC,
61-
waitForTypecheck)
61+
waitForTypecheck,
62+
isReferenceReady,
63+
referenceReady)
6264
import Development.IDE.Test.Runfiles
6365
import qualified Development.IDE.Types.Diagnostics as Diagnostics
6466
import Development.IDE.Types.Location
@@ -5373,7 +5375,7 @@ cradleTests = testGroup "cradle"
53735375
[testGroup "dependencies" [sessionDepsArePickedUp]
53745376
,testGroup "ignore-fatal" [ignoreFatalWarning]
53755377
,testGroup "loading" [loadCradleOnlyonce, retryFailedCradle]
5376-
,testGroup "multi" [simpleMultiTest, simpleMultiTest2, simpleMultiDefTest]
5378+
,testGroup "multi" [simpleMultiTest, simpleMultiTest2, simpleMultiTest3, simpleMultiDefTest]
53775379
,testGroup "sub-directory" [simpleSubDirectoryTest]
53785380
]
53795381

@@ -5493,12 +5495,10 @@ simpleMultiTest :: TestTree
54935495
simpleMultiTest = testCase "simple-multi-test" $ withLongTimeout $ runWithExtraFiles "multi" $ \dir -> do
54945496
let aPath = dir </> "a/A.hs"
54955497
bPath = dir </> "b/B.hs"
5496-
aSource <- liftIO $ readFileUtf8 aPath
5497-
adoc <- createDoc aPath "haskell" aSource
5498+
adoc <- openDoc aPath "haskell"
5499+
bdoc <- openDoc bPath "haskell"
54985500
WaitForIdeRuleResult {..} <- waitForAction "TypeCheck" adoc
54995501
liftIO $ assertBool "A should typecheck" ideResultSuccess
5500-
bSource <- liftIO $ readFileUtf8 bPath
5501-
bdoc <- createDoc bPath "haskell" bSource
55025502
WaitForIdeRuleResult {..} <- waitForAction "TypeCheck" bdoc
55035503
liftIO $ assertBool "B should typecheck" ideResultSuccess
55045504
locs <- getDefinitions bdoc (Position 2 7)
@@ -5511,15 +5511,30 @@ simpleMultiTest2 :: TestTree
55115511
simpleMultiTest2 = testCase "simple-multi-test2" $ runWithExtraFiles "multi" $ \dir -> do
55125512
let aPath = dir </> "a/A.hs"
55135513
bPath = dir </> "b/B.hs"
5514-
bSource <- liftIO $ readFileUtf8 bPath
5515-
bdoc <- createDoc bPath "haskell" bSource
5516-
expectNoMoreDiagnostics 10
5517-
aSource <- liftIO $ readFileUtf8 aPath
5518-
(TextDocumentIdentifier adoc) <- createDoc aPath "haskell" aSource
5519-
-- Need to have some delay here or the test fails
5520-
expectNoMoreDiagnostics 10
5514+
bdoc <- openDoc bPath "haskell"
5515+
WaitForIdeRuleResult {} <- waitForAction "TypeCheck" bdoc
5516+
TextDocumentIdentifier auri <- openDoc aPath "haskell"
5517+
skipManyTill anyMessage $ isReferenceReady aPath
55215518
locs <- getDefinitions bdoc (Position 2 7)
5522-
let fooL = mkL adoc 2 0 2 3
5519+
let fooL = mkL auri 2 0 2 3
5520+
checkDefs locs (pure [fooL])
5521+
expectNoMoreDiagnostics 0.5
5522+
5523+
-- Now with 3 components
5524+
simpleMultiTest3 :: TestTree
5525+
simpleMultiTest3 = knownBrokenForGhcVersions [GHC92] "#2693" $
5526+
testCase "simple-multi-test3" $ runWithExtraFiles "multi" $ \dir -> do
5527+
let aPath = dir </> "a/A.hs"
5528+
bPath = dir </> "b/B.hs"
5529+
cPath = dir </> "c/C.hs"
5530+
bdoc <- openDoc bPath "haskell"
5531+
WaitForIdeRuleResult {} <- waitForAction "TypeCheck" bdoc
5532+
TextDocumentIdentifier auri <- openDoc aPath "haskell"
5533+
skipManyTill anyMessage $ isReferenceReady aPath
5534+
cdoc <- openDoc cPath "haskell"
5535+
WaitForIdeRuleResult {} <- waitForAction "TypeCheck" cdoc
5536+
locs <- getDefinitions cdoc (Position 2 7)
5537+
let fooL = mkL auri 2 0 2 3
55235538
checkDefs locs (pure [fooL])
55245539
expectNoMoreDiagnostics 0.5
55255540

@@ -5531,11 +5546,7 @@ simpleMultiDefTest = testCase "simple-multi-def-test" $ runWithExtraFiles "multi
55315546
adoc <- liftIO $ runInDir dir $ do
55325547
aSource <- liftIO $ readFileUtf8 aPath
55335548
adoc <- createDoc aPath "haskell" aSource
5534-
~() <- skipManyTill anyMessage $ satisfyMaybe $ \case
5535-
FromServerMess (SCustomMethod "ghcide/reference/ready") (NotMess NotificationMessage{_params = fp}) -> do
5536-
A.Success fp' <- pure $ fromJSON fp
5537-
if equalFilePath fp' aPath then pure () else Nothing
5538-
_ -> Nothing
5549+
skipManyTill anyMessage $ isReferenceReady aPath
55395550
closeDoc adoc
55405551
pure adoc
55415552
bSource <- liftIO $ readFileUtf8 bPath
@@ -5566,18 +5577,15 @@ bootTests = testGroup "boot"
55665577
-- `ghcide/reference/ready` notification.
55675578
-- Once we receive one of the above, we wait for the other that we
55685579
-- haven't received yet.
5569-
-- If we don't wait for the `ready` notification it is possible
5570-
-- that the `getDefinitions` request/response in the outer ghcide
5580+
-- If we don't wait for the `ready` notification it is possible
5581+
-- that the `getDefinitions` request/response in the outer ghcide
55715582
-- session will find no definitions.
55725583
let hoverParams = HoverParams cDoc (Position 4 3) Nothing
55735584
hoverRequestId <- sendRequest STextDocumentHover hoverParams
5574-
let parseReadyMessage = satisfy $ \case
5575-
FromServerMess (SCustomMethod "ghcide/reference/ready") (NotMess NotificationMessage{_params = params})
5576-
| A.Success fp <- fromJSON params -> equalFilePath fp cPath
5577-
_ -> False
5585+
let parseReadyMessage = isReferenceReady cPath
55785586
let parseHoverResponse = responseForId STextDocumentHover hoverRequestId
55795587
hoverResponseOrReadyMessage <- skipManyTill anyMessage ((Left <$> parseHoverResponse) <|> (Right <$> parseReadyMessage))
5580-
_ <- skipManyTill anyMessage $
5588+
_ <- skipManyTill anyMessage $
55815589
case hoverResponseOrReadyMessage of
55825590
Left _ -> void parseReadyMessage
55835591
Right _ -> void parseHoverResponse
@@ -5990,11 +5998,7 @@ referenceTestSession name thisDoc docs' f = testSessionWithExtraFiles "reference
59905998
loop :: [FilePath] -> Session ()
59915999
loop [] = pure ()
59926000
loop docs = do
5993-
doc <- skipManyTill anyMessage $ satisfyMaybe $ \case
5994-
FromServerMess (SCustomMethod "ghcide/reference/ready") (NotMess NotificationMessage{_params = fp}) -> do
5995-
A.Success fp' <- pure $ fromJSON fp
5996-
find (fp' ==) docs
5997-
_ -> Nothing
6001+
doc <- skipManyTill anyMessage $ referenceReady (`elem` docs)
59986002
loop (delete doc docs)
59996003
loop docs
60006004
f dir

ghcide/test/src/Development/IDE/Test.hs

+21-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,13 @@ module Development.IDE.Test
2929
, getStoredKeys
3030
, waitForCustomMessage
3131
, waitForGC
32-
,getBuildKeysBuilt,getBuildKeysVisited,getBuildKeysChanged,getBuildEdgesCount,configureCheckProject) where
32+
, getBuildKeysBuilt
33+
, getBuildKeysVisited
34+
, getBuildKeysChanged
35+
, getBuildEdgesCount
36+
, configureCheckProject
37+
, isReferenceReady
38+
, referenceReady) where
3339

3440
import Control.Applicative.Combinators
3541
import Control.Lens hiding (List)
@@ -58,6 +64,7 @@ import Language.LSP.Types.Lens as Lsp
5864
import System.Directory (canonicalizePath)
5965
import System.Time.Extra
6066
import Test.Tasty.HUnit
67+
import System.FilePath (equalFilePath)
6168

6269
requireDiagnosticM
6370
:: (Foldable f, Show (f Diagnostic), HasCallStack)
@@ -254,3 +261,16 @@ configureCheckProject overrideCheckProject =
254261
sendNotification SWorkspaceDidChangeConfiguration
255262
(DidChangeConfigurationParams $ toJSON
256263
def{checkProject = overrideCheckProject})
264+
265+
-- | Pattern match a message from ghcide indicating that a file has been indexed
266+
isReferenceReady :: FilePath -> Session ()
267+
isReferenceReady p = void $ referenceReady (equalFilePath p)
268+
269+
referenceReady :: (FilePath -> Bool) -> Session FilePath
270+
referenceReady pred = satisfyMaybe $ \case
271+
FromServerMess (SCustomMethod "ghcide/reference/ready") (NotMess NotificationMessage{_params})
272+
| A.Success fp <- A.fromJSON _params
273+
, pred fp
274+
-> Just fp
275+
_ -> Nothing
276+

0 commit comments

Comments
 (0)