From dc96f8752cff80b011c81884eca9e1886dace89b Mon Sep 17 00:00:00 2001 From: Zubin Duggal Date: Tue, 20 Dec 2022 23:02:09 +0530 Subject: [PATCH] Compute the source hash before the preprocessor runs because this is how GHC does it. This reduces spurious rebuilds of modules using CPP on GHC 9.4 --- ghcide/src/Development/IDE/Core/Compile.hs | 6 ++---- ghcide/src/Development/IDE/Core/Preprocessor.hs | 11 ++++++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/ghcide/src/Development/IDE/Core/Compile.hs b/ghcide/src/Development/IDE/Core/Compile.hs index ee59909ef5..14aaf2ad1b 100644 --- a/ghcide/src/Development/IDE/Core/Compile.hs +++ b/ghcide/src/Development/IDE/Core/Compile.hs @@ -1090,7 +1090,8 @@ getModSummaryFromImports -> Maybe Util.StringBuffer -> ExceptT [FileDiagnostic] IO ModSummaryResult getModSummaryFromImports env fp modTime contents = do - (contents, opts, env) <- preprocessor env fp contents + + (contents, opts, env, src_hash) <- preprocessor env fp contents let dflags = hsc_dflags env @@ -1141,9 +1142,6 @@ getModSummaryFromImports env fp modTime contents = do liftIO $ evaluate $ rnf srcImports liftIO $ evaluate $ rnf textualImports -#if MIN_VERSION_ghc (9,3,0) - !src_hash <- liftIO $ fingerprintFromStringBuffer contents -#endif modLoc <- liftIO $ if mod == mAIN_NAME -- specially in tests it's common to have lots of nameless modules diff --git a/ghcide/src/Development/IDE/Core/Preprocessor.hs b/ghcide/src/Development/IDE/Core/Preprocessor.hs index ef08264d7a..76afeaeb67 100644 --- a/ghcide/src/Development/IDE/Core/Preprocessor.hs +++ b/ghcide/src/Development/IDE/Core/Preprocessor.hs @@ -8,6 +8,7 @@ module Development.IDE.Core.Preprocessor import Development.IDE.GHC.Compat import qualified Development.IDE.GHC.Compat.Util as Util +import qualified Development.IDE.GHC.Util as Util import Development.IDE.GHC.CPP import Development.IDE.GHC.Orphans () @@ -36,7 +37,7 @@ import GHC.Utils.Outputable (renderWithContext) -- | Given a file and some contents, apply any necessary preprocessors, -- e.g. unlit/cpp. Return the resulting buffer and the DynFlags it implies. -preprocessor :: HscEnv -> FilePath -> Maybe Util.StringBuffer -> ExceptT [FileDiagnostic] IO (Util.StringBuffer, [String], HscEnv) +preprocessor :: HscEnv -> FilePath -> Maybe Util.StringBuffer -> ExceptT [FileDiagnostic] IO (Util.StringBuffer, [String], HscEnv, Util.Fingerprint) preprocessor env filename mbContents = do -- Perform unlit (isOnDisk, contents) <- @@ -48,6 +49,10 @@ preprocessor env filename mbContents = do let isOnDisk = isNothing mbContents return (isOnDisk, contents) + -- Compute the source hash before the preprocessor because this is + -- how GHC does it. + !src_hash <- liftIO $ Util.fingerprintFromStringBuffer contents + -- Perform cpp (opts, env) <- ExceptT $ parsePragmasIntoHscEnv env filename contents let dflags = hsc_dflags env @@ -73,11 +78,11 @@ preprocessor env filename mbContents = do -- Perform preprocessor if not $ gopt Opt_Pp dflags then - return (contents, opts, env) + return (contents, opts, env, src_hash) else do contents <- liftIO $ runPreprocessor env filename $ if isOnDisk then Nothing else Just contents (opts, env) <- ExceptT $ parsePragmasIntoHscEnv env filename contents - return (contents, opts, env) + return (contents, opts, env, src_hash) where logAction :: IORef [CPPLog] -> LogActionCompat logAction cppLogs dflags _reason severity srcSpan _style msg = do