on master help sign in
Add documentation (#368)

* Add documentation for Util.hs * Add documentation to OfInterest

commit19a346a3cc6c613b2c930cbef1a0a92547ae2973 authorNeil Mitchell <ndmitchell@gmail.com> dateSun 26 Jan 2020, 12:37 (7 years ago) parent7e133ea
2 files changed+46−32
src/Development/IDE/Core/OfInterest.hs+16−16 src/Development/IDE/GHC/Util.hs+30−16
src/Development/IDE/Core/OfInterest.hs+16−16
@@ -1,19 +1,17 @@
11-- Copyright (c) 2019 The DAML Authors. All rights reserved.
22-- SPDX-License-Identifier: Apache-2.0
33
4−
5−{-# LANGUAGE TypeFamilies #-}
4+{-# LANGUAGE TypeFamilies #-}
65{-# LANGUAGE FlexibleInstances #-}
76
8−-- | A Shake implementation of the compiler service, built
9−-- using the "Shaker" abstraction layer for in-memory use.
10−--
7+-- | Utilities and state for the files of interest - those which are currently
8+-- open in the editor. The useful function is 'getFilesOfInterest'.
119module Development.IDE.Core.OfInterest(
1210 ofInterestRules,
1311 getFilesOfInterest, setFilesOfInterest, modifyFilesOfInterest,
1412 ) where
1513
16−import Control.Concurrent.Extra
14+import Control.Concurrent.Extra
1715import Data.Binary
1816import Data.Hashable
1917import Control.DeepSeq
@@ -21,26 +19,23 @@ import GHC.Generics
2119import Data.Typeable
2220import qualified Data.ByteString.UTF8 as BS
2321import Control.Exception
24−import Development.IDE.Types.Location
25−import Development.IDE.Types.Logger
26−import Data.Set (Set)
27−import qualified Data.Set as Set
22+import Data.Set (Set)
23+import qualified Data.Set as Set
2824import qualified Data.Text as T
2925import Data.Tuple.Extra
3026import Data.Functor
31−import Development.Shake
32−
33−import Development.IDE.Core.Shake
27+import Development.Shake
3428
29+import Development.IDE.Types.Location
30+import Development.IDE.Types.Logger
31+import Development.IDE.Core.Shake
3532
3633
3734newtype OfInterestVar = OfInterestVar (Var (Set NormalizedFilePath))
3835instance IsIdeGlobal OfInterestVar
3936
40−
4137type instance RuleResult GetFilesOfInterest = Set NormalizedFilePath
4238
43−
4439data GetFilesOfInterest = GetFilesOfInterest
4540 deriving (Eq, Show, Typeable, Generic)
4641instance Hashable GetFilesOfInterest
@@ -48,6 +43,7 @@ instance NFData GetFilesOfInterest
4843instance Binary GetFilesOfInterest
4944
5045
46+-- | The rule that initialises the files of interest state.
5147ofInterestRules :: Rules ()
5248ofInterestRules = do
5349 addIdeGlobal . OfInterestVar =<< liftIO (newVar Set.empty)
@@ -57,6 +53,7 @@ ofInterestRules = do
5753 pure (Just $ BS.fromString $ show filesOfInterest, ([], Just filesOfInterest))
5854
5955
56+-- | Get the files that are open in the IDE.
6057getFilesOfInterest :: Action (Set NormalizedFilePath)
6158getFilesOfInterest = useNoFile_ GetFilesOfInterest
6259
@@ -65,7 +62,8 @@ getFilesOfInterest = useNoFile_ GetFilesOfInterest
6562------------------------------------------------------------
6663-- Exposed API
6764
68−-- | Set the files-of-interest which will be built and kept-up-to-date.
65+-- | Set the files-of-interest - not usually necessary or advisable.
66+-- The LSP client will keep this information up to date.
6967setFilesOfInterest :: IdeState -> Set NormalizedFilePath -> IO ()
7068setFilesOfInterest state files = modifyFilesOfInterest state (const files)
7169
@@ -74,6 +72,8 @@ getFilesOfInterestUntracked = do
7472 OfInterestVar var <- getIdeGlobalAction
7573 liftIO $ readVar var
7674
75+-- | Modify the files-of-interest - not usually necessary or advisable.
76+-- The LSP client will keep this information up to date.
7777modifyFilesOfInterest :: IdeState -> (Set NormalizedFilePath -> Set NormalizedFilePath) -> IO ()
7878modifyFilesOfInterest state f = do
7979 OfInterestVar var <- getIdeGlobalState state
src/Development/IDE/GHC/Util.hs+30−16
@@ -5,23 +5,22 @@
55{-# LANGUAGE CPP #-}
66#include "ghc-api-version.h"
77
8−-- | GHC utility functions. Importantly, code using our GHC should never:
9−--
10−-- * Call runGhc, use runGhcFast instead. It's faster and doesn't require config we don't have.
11−--
12−-- * Call setSessionDynFlags, use modifyDynFlags instead. It's faster and avoids loading packages.
8+-- | General utility functions, mostly focused around GHC operations.
139module Development.IDE.GHC.Util(
14− lookupPackageConfig,
10+ -- * HcsEnv and environment
11+ HscEnvEq, hscEnv, newHscEnvEq,
1512 modifyDynFlags,
1613 fakeDynFlags,
17− prettyPrint,
1814 runGhcEnv,
19− textToStringBuffer,
15+ -- * GHC wrappers
16+ prettyPrint,
17+ lookupPackageConfig,
2018 moduleImportPath,
21− HscEnvEq, hscEnv, newHscEnvEq,
19+ cgGutsToCoreModule,
20+ -- * General utilities
21+ textToStringBuffer,
2222 readFileUtf8,
2323 hDuplicateTo',
24− cgGutsToCoreModule
2524 ) where
2625
2726import Config
@@ -60,6 +59,8 @@ import Development.IDE.Types.Location
6059----------------------------------------------------------------------
6160-- GHC setup
6261
62+-- | Used to modify dyn flags in preference to calling 'setSessionDynFlags',
63+-- since that function also reloads packages (which is very slow).
6364modifyDynFlags :: GhcMonad m => (DynFlags -> DynFlags) -> m ()
6465modifyDynFlags f = do
6566 newFlags <- f <$> getSessionDynFlags
@@ -68,6 +69,7 @@ modifyDynFlags f = do
6869 modifySession $ \h ->
6970 h { hsc_dflags = newFlags, hsc_IC = (hsc_IC h) {ic_dflags = newFlags} }
7071
72+-- | Given a 'UnitId' try and find the associated 'PackageConfig' in the environment.
7173lookupPackageConfig :: UnitId -> HscEnv -> Maybe PackageConfig
7274lookupPackageConfig unitId env =
7375 lookupPackage' False pkgConfigMap unitId
@@ -78,14 +80,18 @@ lookupPackageConfig unitId env =
7880 getPackageConfigMap $ hsc_dflags env
7981
8082
81−-- would be nice to do this more efficiently...
83+-- | Convert from the @text@ package to the @GHC@ 'StringBuffer'.
84+-- Currently implemented somewhat inefficiently (if it ever comes up in a profile).
8285textToStringBuffer :: T.Text -> StringBuffer
8386textToStringBuffer = stringToStringBuffer . T.unpack
8487
8588
89+-- | Pretty print a GHC value using 'fakeDynFlags'.
8690prettyPrint :: Outputable a => a -> String
8791prettyPrint = showSDoc fakeDynFlags . ppr
8892
93+-- | Run a 'Ghc' monad value using an existing 'HscEnv'. Sets up and tears down all the required
94+-- pieces, but designed to be more efficient than a standard 'runGhc'.
8995runGhcEnv :: HscEnv -> Ghc a -> IO a
9096runGhcEnv env act = do
9197 filesToClean <- newIORef emptyFilesToClean
@@ -96,8 +102,8 @@ runGhcEnv env act = do
96102 cleanTempFiles dflags
97103 cleanTempDirs dflags
98104
99−-- Fake DynFlags which are mostly undefined, but define enough to do a
100−-- little bit.
105+-- | A 'DynFlags' value where most things are undefined. It's sufficient to call pretty printing,
106+-- but not much else.
101107fakeDynFlags :: DynFlags
102108fakeDynFlags = defaultDynFlags settings mempty
103109 where
@@ -120,6 +126,9 @@ fakeDynFlags = defaultDynFlags settings mempty
120126 , pc_WORD_SIZE=8
121127 }
122128
129+-- | Given a module location, and its parse tree, figure out what is the include directory implied by it.
130+-- For example, given the file @\/usr\/\Test\/Foo\/Bar.hs@ with the module name @Foo.Bar@ the directory
131+-- @\/usr\/Test@ should be on the include path to find sibling modules.
123132moduleImportPath :: NormalizedFilePath -> GHC.ParsedModule -> Maybe FilePath
124133-- The call to takeDirectory is required since DAML does not require that
125134-- the file name matches the module name in the last component.
@@ -137,12 +146,15 @@ moduleImportPath (takeDirectory . fromNormalizedFilePath -> pathDir) pm
137146 fromNormalizedFilePath $ toNormalizedFilePath $
138147 moduleNameSlashes $ GHC.moduleName mod'
139148
140−-- | An HscEnv with equality.
149+-- | An 'HscEnv' with equality. Two values are considered equal
150+-- if they are created with the same call to 'newHscEnvEq'.
141151data HscEnvEq = HscEnvEq Unique HscEnv
142152
153+-- | Unwrap an 'HsEnvEq'.
143154hscEnv :: HscEnvEq -> HscEnv
144155hscEnv (HscEnvEq _ x) = x
145156
157+-- | Wrap an 'HscEnv' into an 'HscEnvEq'.
146158newHscEnvEq :: HscEnv -> IO HscEnvEq
147159newHscEnvEq e = do u <- newUnique; return $ HscEnvEq u e
148160
@@ -155,9 +167,11 @@ instance Eq HscEnvEq where
155167instance NFData HscEnvEq where
156168 rnf (HscEnvEq a b) = rnf (hashUnique a) `seq` b `seq` ()
157169
170+-- | Read a UTF8 file, with lenient decoding, so it will never raise a decoding error.
158171readFileUtf8 :: FilePath -> IO T.Text
159172readFileUtf8 f = T.decodeUtf8With T.lenientDecode <$> BS.readFile f
160173
174+-- | Convert from a 'CgGuts' to a 'CoreModule'.
161175cgGutsToCoreModule :: SafeHaskellMode -> CgGuts -> ModDetails -> CoreModule
162176cgGutsToCoreModule safeMode guts modDetails = CoreModule
163177 (cg_module guts)
@@ -165,8 +179,8 @@ cgGutsToCoreModule safeMode guts modDetails = CoreModule
165179 (cg_binds guts)
166180 safeMode
167181
168−-- This is a slightly modified version of hDuplicateTo in GHC.
169−-- See the inline comment for more details.
182+-- | A slightly modified version of 'hDuplicateTo' from GHC.
183+-- Importantly, it avoids the bug listed in https://gitlab.haskell.org/ghc/ghc/merge_requests/2318.
170184hDuplicateTo' :: Handle -> Handle -> IO ()
171185hDuplicateTo' h1@(FileHandle path m1) h2@(FileHandle _ m2) = do
172186 withHandle__' "hDuplicateTo" h2 m2 $ \h2_ -> do