Skip to content

Commit bc25ea7

Browse files
Track dependencies when using qAddDependentFile (#516)
* Track dependencies when using qAddDependentFile Closes #492 * Add test for qAddDependentFile * Update test/exe/Main.hs Co-authored-by: Moritz Kiefer <[email protected]> * Update test/exe/Main.hs Co-authored-by: Moritz Kiefer <[email protected]> Co-authored-by: Moritz Kiefer <[email protected]>
1 parent a1cb4eb commit bc25ea7

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

src/Development/IDE/Core/Rules.hs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ typeCheckRuleDefinition file pm generateArtifacts = do
426426
setPriority priorityTypeCheck
427427
IdeOptions { optDefer = defer } <- getIdeOptions
428428

429-
liftIO $ do
429+
addUsageDependencies $ liftIO $ do
430430
res <- typecheckModule defer hsc (zipWith unpack mirs bytecodes) pm
431431
case res of
432432
(diags, Just (hsc,tcm)) | DoGenerateInterfaceFiles <- generateArtifacts -> do
@@ -440,6 +440,18 @@ typeCheckRuleDefinition file pm generateArtifacts = do
440440
uses_th_qq dflags =
441441
xopt LangExt.TemplateHaskell dflags || xopt LangExt.QuasiQuotes dflags
442442

443+
addUsageDependencies :: Action (a, Maybe TcModuleResult) -> Action (a, Maybe TcModuleResult)
444+
addUsageDependencies a = do
445+
r@(_, mtc) <- a
446+
forM_ mtc $ \tc -> do
447+
let used_files = mapMaybe udep (mi_usages (hm_iface (tmrModInfo tc)))
448+
udep (UsageFile fp _h) = Just fp
449+
udep _ = Nothing
450+
-- Add a dependency on these files which are added by things like
451+
-- qAddDependentFile
452+
void $ uses_ GetModificationTime (map toNormalizedFilePath' used_files)
453+
return r
454+
443455

444456
generateCore :: RunSimplifier -> NormalizedFilePath -> Action (IdeResult (SafeHaskellMode, CgGuts, ModDetails))
445457
generateCore runSimplifier file = do

test/exe/Main.hs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ main = defaultMainWithRerun $ testGroup "HIE"
7373
, positionMappingTests
7474
, watchedFilesTests
7575
, cradleTests
76+
, dependentFileTest
7677
]
7778

7879
initializeResponseTests :: TestTree
@@ -2046,6 +2047,42 @@ loadCradleOnlyonce = testGroup "load cradle only once"
20462047
liftIO $ length msgs @?= 0
20472048

20482049

2050+
dependentFileTest :: TestTree
2051+
dependentFileTest = testGroup "addDependentFile"
2052+
[testGroup "file-changed" [testSession' "test" test]
2053+
]
2054+
where
2055+
test dir = do
2056+
-- If the file contains B then no type error
2057+
-- otherwise type error
2058+
liftIO $ writeFile (dir </> "dep-file.txt") "A"
2059+
let fooContent = T.unlines
2060+
[ "{-# LANGUAGE TemplateHaskell #-}"
2061+
, "module Foo where"
2062+
, "import Language.Haskell.TH.Syntax"
2063+
, "foo :: Int"
2064+
, "foo = 1 + $(do"
2065+
, " qAddDependentFile \"dep-file.txt\""
2066+
, " f <- qRunIO (readFile \"dep-file.txt\")"
2067+
, " if f == \"B\" then [| 1 |] else lift f)"
2068+
]
2069+
let bazContent = T.unlines ["module Baz where", "import Foo"]
2070+
_ <-createDoc "Foo.hs" "haskell" fooContent
2071+
doc <- createDoc "Baz.hs" "haskell" bazContent
2072+
expectDiagnostics
2073+
[("Foo.hs", [(DsError, (4, 6), "Couldn't match expected type")])]
2074+
-- Now modify the dependent file
2075+
liftIO $ writeFile (dir </> "dep-file.txt") "B"
2076+
let change = TextDocumentContentChangeEvent
2077+
{ _range = Just (Range (Position 2 0) (Position 2 6))
2078+
, _rangeLength = Nothing
2079+
, _text = "f = ()"
2080+
}
2081+
-- Modifying Baz will now trigger Foo to be rebuilt as well
2082+
changeDoc doc [change]
2083+
expectDiagnostics [("Foo.hs", [])]
2084+
2085+
20492086
cradleLoadedMessage :: Session FromServerMessage
20502087
cradleLoadedMessage = satisfy $ \case
20512088
NotCustomServer (NotificationMessage _ (CustomServerMethod m) _) -> m == cradleLoadedMethod

0 commit comments

Comments
 (0)