Skip to content
This repository was archived by the owner on Jan 2, 2021. It is now read-only.

Commit 66c9107

Browse files
committed
Add GetHieAsts rule
1 parent 114e184 commit 66c9107

File tree

8 files changed

+113
-20
lines changed

8 files changed

+113
-20
lines changed

src-ghc810/Development/IDE/GHC/HieAst.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Main functions for .hie file generation
1717
{-# LANGUAGE AllowAmbiguousTypes #-}
1818
{-# LANGUAGE ViewPatterns #-}
1919
{-# LANGUAGE DeriveDataTypeable #-}
20-
module Development.IDE.GHC.HieAst ( mkHieFile ) where
20+
module Development.IDE.GHC.HieAst ( mkHieFile, enrichHie ) where
2121

2222
import GhcPrelude
2323

src-ghc86/Development/IDE/GHC/HieAst.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Main functions for .hie file generation
1717
{-# LANGUAGE ViewPatterns #-}
1818
{-# LANGUAGE DeriveDataTypeable #-}
1919
{-# LANGUAGE DataKinds #-}
20-
module Development.IDE.GHC.HieAst ( mkHieFile ) where
20+
module Development.IDE.GHC.HieAst ( mkHieFile, enrichHie ) where
2121

2222
import Avail ( Avails )
2323
import Bag ( Bag, bagToList )

src-ghc88/Development/IDE/GHC/HieAst.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Main functions for .hie file generation
1616
{-# LANGUAGE AllowAmbiguousTypes #-}
1717
{-# LANGUAGE ViewPatterns #-}
1818
{-# LANGUAGE DeriveDataTypeable #-}
19-
module Development.IDE.GHC.HieAst ( mkHieFile ) where
19+
module Development.IDE.GHC.HieAst ( mkHieFile, enrichHie ) where
2020

2121
import Avail ( Avails )
2222
import Bag ( Bag, bagToList )

src/Development/IDE/Core/Compile.hs

+28-13
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ module Development.IDE.Core.Compile
1818
, addRelativeImport
1919
, mkTcModuleResult
2020
, generateByteCode
21-
, generateAndWriteHieFile
21+
, generateHieAsts
22+
, writeHieFile
2223
, writeHiFile
2324
, getModSummaryFromImports
2425
, loadHieFile
@@ -55,7 +56,7 @@ import ErrUtils
5556
#endif
5657

5758
import Finder
58-
import Development.IDE.GHC.Compat hiding (parseModule, typecheckModule)
59+
import Development.IDE.GHC.Compat hiding (parseModule, typecheckModule, writeHieFile)
5960
import qualified Development.IDE.GHC.Compat as GHC
6061
import qualified Development.IDE.GHC.Compat as Compat
6162
import GhcMonad
@@ -64,7 +65,7 @@ import qualified HeaderInfo as Hdr
6465
import HscMain (hscInteractive, hscSimplify)
6566
import MkIface
6667
import StringBuffer as SB
67-
import TcRnMonad (tct_id, TcTyThing(AGlobal, ATcId), initTc, initIfaceLoad, tcg_th_coreplugins)
68+
import TcRnMonad (tct_id, TcTyThing(AGlobal, ATcId), initTc, initIfaceLoad, tcg_th_coreplugins, tcg_binds)
6869
import TcIface (typecheckIface)
6970
import TidyPgm
7071

@@ -270,7 +271,7 @@ mkTcModuleResult tcm upgradedError = do
270271
(iface, _) <- liftIO $ mkIfaceTc session Nothing sf details tcGblEnv
271272
#endif
272273
let mod_info = HomeModInfo iface details Nothing
273-
return $ TcModuleResult tcm mod_info upgradedError
274+
return $ TcModuleResult tcm mod_info upgradedError Nothing
274275
where
275276
(tcGblEnv, details) = tm_internals_ tcm
276277

@@ -281,19 +282,25 @@ atomicFileWrite targetPath write = do
281282
(tempFilePath, cleanUp) <- newTempFileWithin dir
282283
(write tempFilePath >> renameFile tempFilePath targetPath) `onException` cleanUp
283284

284-
generateAndWriteHieFile :: HscEnv -> TypecheckedModule -> BS.ByteString -> IO [FileDiagnostic]
285-
generateAndWriteHieFile hscEnv tcm source =
286-
handleGenerationErrors dflags "extended interface generation" $ do
285+
generateHieAsts :: HscEnv -> TypecheckedModule -> IO ([FileDiagnostic], Maybe (HieASTs Type))
286+
generateHieAsts hscEnv tcm =
287+
handleGenerationErrors' dflags "extended interface generation" $ do
287288
case tm_renamed_source tcm of
288-
Just rnsrc -> do
289-
hf <- runHsc hscEnv $
290-
GHC.mkHieFile mod_summary (fst $ tm_internals_ tcm) rnsrc source
291-
atomicFileWrite targetPath $ flip GHC.writeHieFile hf
289+
Just rnsrc -> runHsc hscEnv $
290+
Just <$> GHC.enrichHie (tcg_binds $ fst $ tm_internals_ tcm) rnsrc
292291
_ ->
293-
return ()
292+
return Nothing
293+
where
294+
dflags = hsc_dflags hscEnv
295+
296+
writeHieFile :: HscEnv -> ModSummary -> [GHC.AvailInfo] -> HieASTs Type -> BS.ByteString -> IO [FileDiagnostic]
297+
writeHieFile hscEnv mod_summary exports ast source =
298+
handleGenerationErrors dflags "extended interface write/compression" $ do
299+
hf <- runHsc hscEnv $
300+
GHC.mkHieFile' mod_summary exports ast source
301+
atomicFileWrite targetPath $ flip GHC.writeHieFile hf
294302
where
295303
dflags = hsc_dflags hscEnv
296-
mod_summary = pm_mod_summary $ tm_parsed_module tcm
297304
mod_location = ms_location mod_summary
298305
targetPath = Compat.ml_hie_file mod_location
299306

@@ -315,6 +322,14 @@ handleGenerationErrors dflags source action =
315322
. (("Error during " ++ T.unpack source) ++) . show @SomeException
316323
]
317324

325+
handleGenerationErrors' :: DynFlags -> T.Text -> IO (Maybe a) -> IO ([FileDiagnostic], Maybe a)
326+
handleGenerationErrors' dflags source action =
327+
fmap ([],) action `catches`
328+
[ Handler $ return . (,Nothing) . diagFromGhcException source dflags
329+
, Handler $ return . (,Nothing) . diagFromString source DsError (noSpan "<internal>")
330+
. (("Error during " ++ T.unpack source) ++) . show @SomeException
331+
]
332+
318333

319334
-- | Setup the environment that GHC needs according to our
320335
-- best understanding (!)

src/Development/IDE/Core/RuleTypes.hs

+19
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ data TcModuleResult = TcModuleResult
6565
-- HomeModInfo instead
6666
, tmrModInfo :: HomeModInfo
6767
, tmrDeferedError :: !Bool -- ^ Did we defer any type errors for this module?
68+
, tmrHieAsts :: !(Maybe (HieASTs Type)) -- ^ The HieASTs if we computed them
6869
}
6970
instance Show TcModuleResult where
7071
show = show . pm_mod_summary . tm_parsed_module . tmrModule
@@ -97,9 +98,21 @@ instance NFData HiFileResult where
9798
instance Show HiFileResult where
9899
show = show . hirModSummary
99100

101+
-- | Save the uncompressed AST here, we compress it just before writing to disk
102+
data HieAstResult = HAR { hieModule :: Module, hieAst :: !(HieASTs Type), refMap :: !RefMap }
103+
104+
instance NFData HieAstResult where
105+
rnf (HAR m hf rm) = rnf m `seq` rwhnf hf `seq` rnf rm
106+
107+
instance Show HieAstResult where
108+
show = show . hieModule
109+
100110
-- | The type checked version of this file, requires TypeCheck+
101111
type instance RuleResult TypeCheck = TcModuleResult
102112

113+
-- | The uncompressed HieAST
114+
type instance RuleResult GetHieAst = HieAstResult
115+
103116
-- | Information about what spans occur where, requires TypeCheck
104117
type instance RuleResult GetSpanInfo = SpansInfo
105118

@@ -201,6 +214,12 @@ instance Hashable GetSpanInfo
201214
instance NFData GetSpanInfo
202215
instance Binary GetSpanInfo
203216

217+
data GetHieAst = GetHieAst
218+
deriving (Eq, Show, Typeable, Generic)
219+
instance Hashable GetHieAst
220+
instance NFData GetHieAst
221+
instance Binary GetHieAst
222+
204223
data GenerateCore = GenerateCore
205224
deriving (Eq, Show, Typeable, Generic)
206225
instance Hashable GenerateCore

src/Development/IDE/Core/Rules.hs

+25-3
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ import Development.IDE.Core.FileExists
4646
import Development.IDE.Core.FileStore (modificationTime, getFileContents)
4747
import Development.IDE.Types.Diagnostics as Diag
4848
import Development.IDE.Types.Location
49-
import Development.IDE.GHC.Compat hiding (parseModule, typecheckModule)
49+
import Development.IDE.GHC.Compat hiding (parseModule, typecheckModule, writeHieFile)
5050
import Development.IDE.GHC.Util
5151
import Development.IDE.GHC.WithDynFlags
5252
import Data.Either.Extra
@@ -504,6 +504,21 @@ getDependenciesRule =
504504
let mbFingerprints = map (fingerprintString . fromNormalizedFilePath) allFiles <$ optShakeFiles opts
505505
return (fingerprintToBS . fingerprintFingerprints <$> mbFingerprints, ([], transitiveDeps depInfo file))
506506

507+
getHieAstsRule :: Rules ()
508+
getHieAstsRule =
509+
define $ \GetHieAst f -> do
510+
tmr <- use_ TypeCheck f
511+
(diags,masts) <- case tmrHieAsts tmr of
512+
-- If we already have them from typechecking, return them
513+
Just asts -> pure ([], Just asts)
514+
-- Compute asts if we haven't already computed them
515+
Nothing -> do
516+
hsc <- hscEnv <$> use_ GhcSession f
517+
(diagsHieGen, masts) <- liftIO $ generateHieAsts hsc (tmrModule tmr)
518+
pure (diagsHieGen, masts)
519+
let refmap = generateReferencesMap . getAsts <$> masts
520+
pure (diags, HAR (ms_mod $ tmrModSummary tmr) <$> masts <*> refmap)
521+
507522
-- Source SpanInfo is used by AtPoint and Goto Definition.
508523
getSpanInfoRule :: Rules ()
509524
getSpanInfoRule =
@@ -570,14 +585,20 @@ typeCheckRuleDefinition hsc pm isFoi source = do
570585
case isFoi of
571586
IsFOI Modified -> return (diags, Just tcm)
572587
_ -> do -- If the file is saved on disk, or is not a FOI, we write out ifaces
573-
diagsHie <- generateAndWriteHieFile hsc (tmrModule tcm) (fromMaybe "" source)
588+
let tm = tmrModule tcm
589+
ms = tmrModSummary tcm
590+
exports = tcg_exports $ fst $ tm_internals_ tm
591+
(diagsHieGen, masts) <- generateHieAsts hsc (tmrModule tcm)
592+
diagsHieWrite <- case masts of
593+
Nothing -> pure mempty
594+
Just asts -> writeHieFile hsc ms exports asts $ fromMaybe "" source
574595
-- Don't save interface files for modules that compiled due to defering
575596
-- type errors, as we won't get proper diagnostics if we load these from
576597
-- disk
577598
diagsHi <- if not $ tmrDeferedError tcm
578599
then writeHiFile hsc tcm
579600
else pure mempty
580-
return (diags <> diagsHi <> diagsHie, Just tcm)
601+
return (diags <> diagsHi <> diagsHieGen <> diagsHieWrite, Just tcm{tmrHieAsts = masts})
581602
(diags, res) ->
582603
return (diags, snd <$> res)
583604
where
@@ -849,6 +870,7 @@ mainRule = do
849870
isHiFileStableRule
850871
getModuleGraphRule
851872
knownFilesRule
873+
getHieAstsRule
852874

853875
-- | Given the path to a module src file, this rule returns True if the
854876
-- corresponding `.hi` file is stable, that is, if it is newer

src/Development/IDE/GHC/Compat.hs

+29-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ module Development.IDE.GHC.Compat(
1616
NameCacheUpdater(..),
1717
hieExportNames,
1818
mkHieFile,
19+
mkHieFile',
20+
enrichHie,
21+
RefMap,
1922
writeHieFile,
2023
readHieFile,
2124
supportsHieFiles,
@@ -54,6 +57,8 @@ module Development.IDE.GHC.Compat(
5457
getLoc,
5558
upNameCache,
5659
disableWarningsAsErrors,
60+
AvailInfo,
61+
tcg_exports,
5762

5863
module GHC,
5964
#if MIN_GHC_API_VERSION(8,6,0)
@@ -78,6 +83,10 @@ import Packages
7883
import Data.IORef
7984
import HscTypes
8085
import NameCache
86+
import qualified Data.ByteString as BS
87+
import MkIface
88+
import Data.Map.Strict (Map)
89+
import TcRnTypes
8190

8291
import qualified GHC
8392
import GHC hiding (
@@ -110,7 +119,7 @@ import ErrUtils (ErrorMessages)
110119
import FastString (FastString)
111120

112121
#if MIN_GHC_API_VERSION(8,6,0)
113-
import Development.IDE.GHC.HieAst (mkHieFile)
122+
import Development.IDE.GHC.HieAst (mkHieFile,enrichHie)
114123
import Development.IDE.GHC.HieBin
115124

116125
#if MIN_GHC_API_VERSION(8,8,0)
@@ -181,6 +190,25 @@ includePathsGlobal = id
181190
includePathsQuote = const []
182191
#endif
183192

193+
type RefMap = Map Identifier [(Span, IdentifierDetails Type)]
194+
195+
mkHieFile' :: ModSummary
196+
-> [AvailInfo]
197+
-> HieASTs Type
198+
-> BS.ByteString
199+
-> Hsc HieFile
200+
mkHieFile' ms exports asts src = do
201+
let Just src_file = ml_hs_file $ ms_location ms
202+
(asts',arr) = compressTypes asts
203+
return $ HieFile
204+
{ hie_hs_file = src_file
205+
, hie_module = ms_mod ms
206+
, hie_types = arr
207+
, hie_asts = asts'
208+
-- mkIfaceExports sorts the AvailInfos for stability
209+
, hie_exports = mkIfaceExports exports
210+
, hie_hs_src = src
211+
}
184212

185213
addIncludePathsQuote :: FilePath -> DynFlags -> DynFlags
186214
#if MIN_GHC_API_VERSION(8,6,0)

src/Development/IDE/GHC/Orphans.hs

+9
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,12 @@ instance Show ModuleName where
8080
show = moduleNameString
8181
instance Hashable ModuleName where
8282
hashWithSalt salt = hashWithSalt salt . show
83+
84+
instance NFData a => NFData (IdentifierDetails a) where
85+
rnf (IdentifierDetails a b) = rnf a `seq` rnf (length b)
86+
87+
instance NFData RealSrcSpan where
88+
rnf = rwhnf
89+
90+
instance NFData Type where
91+
rnf = rwhnf

0 commit comments

Comments
 (0)