ghcide-2.9.0.0: The core of an IDE

Safe Haskell | None
Language | GHC2021

Development.IDE.Core.Shake

Description

A Shake implementation of the compiler service.

There are two primary locations where data lives, and both of these contain much the same data:

- The Shake database (inside `shakeDb`) stores a map of shake keys to shake values. In our case, these are all of type `Q` to `A`. During a single run all the values in the Shake database are consistent so are used in conjunction with each other, e.g. in `uses`.
- The `Values` type stores a map of keys to values. These values are always stored as real Haskell values, whereas Shake serialises all `A` values between runs. To deserialise a Shake value, we just consult Values.

Synopsis

- data IdeState
- shakeSessionInit :: Recorder (WithPriority Log) -> IdeState -> IO ()
- shakeExtras :: IdeState -> ShakeExtras
- shakeDb :: IdeState -> ShakeDatabase
- rootDir :: IdeState -> FilePath
- data ShakeExtras = ShakeExtras {
  - lspEnv :: Maybe (LanguageContextEnv Config)
  - debouncer :: Debouncer NormalizedUri
  - shakeRecorder :: Recorder (WithPriority Log)
  - idePlugins :: IdePlugins IdeState
  - globals :: TVar (HashMap TypeRep Dynamic)
  - state :: Values
  - diagnostics :: STMDiagnosticStore
  - hiddenDiagnostics :: STMDiagnosticStore
  - publishedDiagnostics :: Map NormalizedUri [Diagnostic]
  - semanticTokensCache :: Map NormalizedFilePath SemanticTokens
  - semanticTokensId :: TVar Int
  - positionMapping :: Map NormalizedUri (EnumMap Int32 (PositionDelta, PositionMapping))
  - progress :: ProgressReporting
  - ideTesting :: IdeTesting
  - restartShakeSession :: VFSModified -> String -> [DelayedAction ()] -> IO [Key] -> IO ()
  - ideNc :: NameCache
  - knownTargetsVar :: TVar (Hashed KnownTargets)
  - exportsMap :: TVar ExportsMap
  - actionQueue :: ActionQueue
  - clientCapabilities :: ClientCapabilities
  - withHieDb :: WithHieDb
  - hiedbWriter :: HieDbWriter
  - persistentKeys :: TVar (KeyMap GetStalePersistent)
  - vfsVar :: TVar VFS
  - defaultConfig :: Config
  - dirtyKeys :: TVar KeySet
  - restartQueue :: TQueue (IO ())
  - loaderQueue :: TQueue (IO ())
  }
- getShakeExtras :: Action ShakeExtras
- getShakeExtrasRules :: Rules ShakeExtras
- data KnownTargets = KnownTargets {
  - targetMap :: !(HashMap Target (HashSet NormalizedFilePath))
  - normalisingMap :: !(HashMap Target Target)
  }
- data Target
  - = TargetModule ModuleName
  - | TargetFile NormalizedFilePath
- toKnownFiles :: KnownTargets -> HashSet NormalizedFilePath
- unionKnownTargets :: KnownTargets -> KnownTargets -> KnownTargets
- mkKnownTargets :: [(Target, HashSet NormalizedFilePath)] -> KnownTargets
- type IdeRule k v = (RuleResult k ~ v, ShakeValue k, Show v, Typeable v, NFData v)
- type IdeResult v = ([FileDiagnostic], Maybe v)
- newtype GetModificationTime where
  - GetModificationTime_ {
    - missingFileDiagnostics :: Bool
    }
  - pattern GetModificationTime :: GetModificationTime
- shakeOpen :: Recorder (WithPriority Log) -> Maybe (LanguageContextEnv Config) -> Config -> IdePlugins IdeState -> Debouncer NormalizedUri -> Maybe FilePath -> IdeReportProgress -> IdeTesting -> WithHieDb -> ThreadQueue -> ShakeOptions -> Monitoring -> Rules () -> FilePath -> IO IdeState
- shakeShut :: IdeState -> IO ()
- shakeEnqueue :: ShakeExtras -> DelayedAction a -> IO (IO a)
- newSession :: Recorder (WithPriority Log) -> ShakeExtras -> VFSModified -> ShakeDatabase -> [DelayedActionInternal] -> String -> IO ShakeSession
- use :: IdeRule k v => k -> NormalizedFilePath -> Action (Maybe v)
- useNoFile :: IdeRule k v => k -> Action (Maybe v)
- uses :: (Traversable f, IdeRule k v) => k -> f NormalizedFilePath -> Action (f (Maybe v))
- useWithStaleFast :: IdeRule k v => k -> NormalizedFilePath -> IdeAction (Maybe (v, PositionMapping))
- useWithStaleFast' :: IdeRule k v => k -> NormalizedFilePath -> IdeAction (FastResult v)
- delayedAction :: DelayedAction a -> IdeAction (IO a)
- data FastResult a = FastResult {
  - stale :: Maybe (a, PositionMapping)
  - uptoDate :: IO (Maybe a)
  }
- use_ :: IdeRule k v => k -> NormalizedFilePath -> Action v
- useNoFile_ :: IdeRule k v => k -> Action v
- uses_ :: (Traversable f, IdeRule k v) => k -> f NormalizedFilePath -> Action (f v)
- useWithStale :: IdeRule k v => k -> NormalizedFilePath -> Action (Maybe (v, PositionMapping))
- usesWithStale :: (Traversable f, IdeRule k v) => k -> f NormalizedFilePath -> Action (f (Maybe (v, PositionMapping)))
- useWithStale_ :: IdeRule k v => k -> NormalizedFilePath -> Action (v, PositionMapping)
- usesWithStale_ :: (Traversable f, IdeRule k v) => k -> f NormalizedFilePath -> Action (f (v, PositionMapping))
- newtype BadDependency = BadDependency String
- data RuleBody k v
  - = Rule (k -> NormalizedFilePath -> Action (Maybe ByteString, IdeResult v))
  - | RuleNoDiagnostics (k -> NormalizedFilePath -> Action (Maybe ByteString, Maybe v))
  - | RuleWithCustomNewnessCheck {
    - newnessCheck :: ByteString -> ByteString -> Bool
    - build :: k -> NormalizedFilePath -> Action (Maybe ByteString, Maybe v)
    }
  - | RuleWithOldValue (k -> NormalizedFilePath -> Value v -> Action (Maybe ByteString, IdeResult v))
- define :: IdeRule k v => Recorder (WithPriority Log) -> (k -> NormalizedFilePath -> Action (IdeResult v)) -> Rules ()
- defineNoDiagnostics :: IdeRule k v => Recorder (WithPriority Log) -> (k -> NormalizedFilePath -> Action (Maybe v)) -> Rules ()
- defineEarlyCutoff :: IdeRule k v => Recorder (WithPriority Log) -> RuleBody k v -> Rules ()
- defineNoFile :: IdeRule k v => Recorder (WithPriority Log) -> (k -> Action v) -> Rules ()
- defineEarlyCutOffNoFile :: IdeRule k v => Recorder (WithPriority Log) -> (k -> Action (ByteString, v)) -> Rules ()
- getDiagnostics :: IdeState -> STM [FileDiagnostic]
- mRunLspT :: Applicative m => Maybe (LanguageContextEnv c) -> LspT c m () -> m ()
- mRunLspTCallback :: Monad m => Maybe (LanguageContextEnv c) -> (LspT c m a -> LspT c m a) -> m a -> m a
- getHiddenDiagnostics :: IdeState -> STM [FileDiagnostic]
- class Typeable a => IsIdeGlobal (a :: k)
- addIdeGlobal :: IsIdeGlobal a => a -> Rules ()
- addIdeGlobalExtras :: IsIdeGlobal a => ShakeExtras -> a -> IO ()
- getIdeGlobalState :: IsIdeGlobal a => IdeState -> IO a
- getIdeGlobalAction :: (HasCallStack, IsIdeGlobal a) => Action a
- getIdeGlobalExtras :: (HasCallStack, IsIdeGlobal a) => ShakeExtras -> IO a
- getIdeOptions :: Action IdeOptions
- getIdeOptionsIO :: ShakeExtras -> IO IdeOptions
- newtype GlobalIdeOptions = GlobalIdeOptions IdeOptions
- getClientConfig :: MonadLsp Config m => m Config
- getPluginConfigAction :: PluginId -> Action PluginConfig
- knownTargets :: Action (Hashed KnownTargets)
- ideLogger :: IdeState -> Recorder (WithPriority Log)
- actionLogger :: Action (Recorder (WithPriority Log))
- getVirtualFile :: NormalizedFilePath -> Action (Maybe VirtualFile)
- data FileVersion
  - = ModificationTime !POSIXTime
  - | VFSVersion !Int32
- updatePositionMapping :: IdeState -> VersionedTextDocumentIdentifier -> [TextDocumentContentChangeEvent] -> STM ()
- updatePositionMappingHelper :: Int32 -> [TextDocumentContentChangeEvent] -> EnumMap Int32 (PositionDelta, PositionMapping) -> EnumMap Int32 (PositionDelta, PositionMapping)
- deleteValue :: ShakeValue k => ShakeExtras -> k -> NormalizedFilePath -> STM [Key]
- type WithProgressFunc = forall a. Text -> ProgressCancellable -> ((ProgressAmount -> IO ()) -> IO a) -> IO a
- type WithIndefiniteProgressFunc = forall a. Text -> ProgressCancellable -> IO a -> IO a
- data ProgressEvent
  - = KickStarted
  - | KickCompleted
- data DelayedAction a
- mkDelayedAction :: String -> Priority -> Action a -> DelayedAction a
- newtype IdeAction a = IdeAction {
  - runIdeActionT :: ReaderT ShakeExtras IO a
  }
- runIdeAction :: String -> ShakeExtras -> IdeAction a -> IO a
- mkUpdater :: NameCache -> NameCacheUpdater
- newtype Q k = Q (k, NormalizedFilePath)
- type IndexQueue = TQueue (((HieDb -> IO ()) -> IO ()) -> IO ())
- data HieDb
- data HieDbWriter = HieDbWriter {
  - indexQueue :: IndexQueue
  - indexPending :: TVar (HashMap NormalizedFilePath Fingerprint)
  - indexCompleted :: TVar Int
  - indexProgressToken :: Var (Maybe ProgressToken)
  }
- addPersistentRule :: IdeRule k v => k -> (NormalizedFilePath -> IdeAction (Maybe (v, PositionDelta, Maybe Int32))) -> Rules ()
- garbageCollectDirtyKeys :: Action [Key]
- garbageCollectDirtyKeysOlderThan :: Int -> CheckParents -> Action [Key]
- data Log
  - = LogCreateHieDbExportsMapStart
  - | LogCreateHieDbExportsMapFinish !Int
  - | LogBuildSessionRestart !String ![DelayedActionInternal] !KeySet !Seconds !(Maybe FilePath)
  - | LogBuildSessionRestartTakingTooLong !Seconds
  - | LogDelayedAction !(DelayedAction ()) !Seconds
  - | LogBuildSessionFinish !(Maybe SomeException)
  - | LogDiagsDiffButNoLspEnv ![FileDiagnostic]
  - | LogDefineEarlyCutoffRuleNoDiagHasDiag !FileDiagnostic
  - | LogDefineEarlyCutoffRuleCustomNewnessHasDiag !FileDiagnostic
  - | LogCancelledAction !Text
  - | LogSessionInitialised
  - | LogLookupPersistentKey !Text
  - | LogShakeGarbageCollection !Text !Int !Seconds
  - | LogSetFilesOfInterest ![(NormalizedFilePath, FileOfInterestStatus)]
- data VFSModified
  - = VFSUnmodified
  - | VFSModified !VFS
- getClientConfigAction :: Action Config
- data ThreadQueue = ThreadQueue {
  - tIndexQueue :: IndexQueue
  - tRestartQueue :: TQueue (IO ())
  - tLoaderQueue :: TQueue (IO ())
  }

# Documentation

data IdeState #

A Shake database plus persistent store. Can be thought of as storing mappings from `(FilePath, k)` to `RuleResult k`.

#### Instances

Instances details

MonadReader (ReactorChan, IdeState) (ServerM c) # |
Instance details Defined in Development.IDE.LSP.Server Methods ask :: ServerM c (ReactorChan, IdeState) # local :: ((ReactorChan, IdeState) -> (ReactorChan, IdeState)) -> ServerM c a -> ServerM c a # reader :: ((ReactorChan, IdeState) -> a) -> ServerM c a #

shakeSessionInit :: Recorder (WithPriority Log) -> IdeState -> IO () #

Must be called in the `Initialized` handler and only once

shakeExtras :: IdeState -> ShakeExtras #

shakeDb :: IdeState -> ShakeDatabase #

rootDir :: IdeState -> FilePath #

See Note [Root Directory]

data ShakeExtras #

Constructors

ShakeExtras |
Fields lspEnv :: Maybe (LanguageContextEnv Config) debouncer :: Debouncer NormalizedUri shakeRecorder :: Recorder (WithPriority Log) idePlugins :: IdePlugins IdeState globals :: TVar (HashMap TypeRep Dynamic) Registry of global state used by rules. Small and immutable after startup, so not worth using an STM.Map. state :: Values diagnostics :: STMDiagnosticStore hiddenDiagnostics :: STMDiagnosticStore publishedDiagnostics :: Map NormalizedUri [Diagnostic] This represents the set of diagnostics that we have published. Due to debouncing not every change might get published. semanticTokensCache :: Map NormalizedFilePath SemanticTokens Cache of last response of semantic tokens for each file, so we can compute deltas for semantic tokens(SMethod_TextDocumentSemanticTokensFullDelta). putting semantic tokens cache and id in shakeExtras might not be ideal see Note [Semantic Tokens Cache Location] semanticTokensId :: TVar Int semanticTokensId is used to generate unique ids for each lsp response of semantic tokens. positionMapping :: Map NormalizedUri (EnumMap Int32 (PositionDelta, PositionMapping)) Map from a text document version to a PositionMapping that describes how to map positions in a version of that document to positions in the latest version First mapping is delta from previous version and second one is an accumulation to the current version. progress :: ProgressReporting ideTesting :: IdeTesting Whether to enable additional lsp messages used by the test suite for checking invariants restartShakeSession :: VFSModified -> String -> [DelayedAction ()] -> IO [Key] -> IO () ideNc :: NameCache knownTargetsVar :: TVar (Hashed KnownTargets) A mapping of module name to known target (or candidate targets, if missing) exportsMap :: TVar ExportsMap A mapping of exported identifiers for local modules. Updated on kick actionQueue :: ActionQueue A work queue for actions added via `runInShakeSession` clientCapabilities :: ClientCapabilities withHieDb :: WithHieDb Use only to read. hiedbWriter :: HieDbWriter use to write persistentKeys :: TVar (KeyMap GetStalePersistent) Registry for functions that compute/get "stale" results for the rule (possibly from disk) vfsVar :: TVar VFS A snapshot of the current state of the virtual file system. Updated on shakeRestart VFS state is managed by LSP. However, the state according to the lsp library may be newer than the state of the current session, leaving us vulnerable to subtle race conditions. To avoid this, we take a snapshot of the state of the VFS on every restart, so that the whole session sees a single consistent view of the VFS. We don't need a STM.Map because we never update individual keys ourselves. defaultConfig :: Config Default HLS config, only relevant if the client does not provide any Config dirtyKeys :: TVar KeySet Set of dirty rule keys since the last Shake run restartQueue :: TQueue (IO ()) Queue of restart actions to be run. loaderQueue :: TQueue (IO ()) Queue of loader actions to be run.

#### Instances

Instances details

MonadReader ShakeExtras IdeAction # |
Instance details Defined in Development.IDE.Core.Shake Methods ask :: IdeAction ShakeExtras # local :: (ShakeExtras -> ShakeExtras) -> IdeAction a -> IdeAction a # reader :: (ShakeExtras -> a) -> IdeAction a #

getShakeExtras :: Action ShakeExtras #

getShakeExtrasRules :: Rules ShakeExtras #

data KnownTargets #

A mapping of module name to known files

Constructors

KnownTargets |
- Fields targetMap :: !(HashMap Target (HashSet NormalizedFilePath)) normalisingMap :: !(HashMap Target Target) `normalisingMap` is a cached copy of `HMap.mapKey const targetMap` At startup `GetLocatedImports` is called on all known files. Say you have 10000 modules in your project then this leads to 10000 calls to `GetLocatedImports` running concurrently. In `GetLocatedImports` the known targets are consulted and the targetsMap is created by mapping the known targets. This map is used for introducing sharing amongst filepaths. This operation copies a local copy of the `target` map which is local to the rule.
      let targetsMap = HMap.mapWithKey const targets
So now each rule has a `HashMap` of size 10000 held locally to it and depending on how the threads are scheduled there will be 10000^2 elements in total allocated in `HashMap`s. This used a lot of memory. Solution: Return the `normalisingMap` in the result of the `GetKnownTargets` rule so it is shared across threads.

#### Instances

Instances details

NFData KnownTargets # |
Instance details Defined in Development.IDE.Types.KnownTargets Methods rnf :: KnownTargets -> () #
Show KnownTargets # |
Instance details Defined in Development.IDE.Types.KnownTargets Methods showsPrec :: Int -> KnownTargets -> ShowS # show :: KnownTargets -> String # showList :: [KnownTargets] -> ShowS #
Eq KnownTargets # |
Instance details Defined in Development.IDE.Types.KnownTargets Methods (==) :: KnownTargets -> KnownTargets -> Bool # (/=) :: KnownTargets -> KnownTargets -> Bool #
Hashable KnownTargets # |
Instance details Defined in Development.IDE.Types.KnownTargets Methods hashWithSalt :: Int -> KnownTargets -> Int # hash :: KnownTargets -> Int #

data Target #

Constructors

TargetModule ModuleName |
TargetFile NormalizedFilePath |

#### Instances

Instances details

NFData Target # |
Instance details Defined in Development.IDE.Types.KnownTargets Methods rnf :: Target -> () #
Generic Target # |
Instance details Defined in Development.IDE.Types.KnownTargets Associated Types
type Rep Target |
Instance details Defined in Development.IDE.Types.KnownTargets type Rep Target = D1 ('MetaData "Target" "Development.IDE.Types.KnownTargets" "ghcide-2.9.0.0-1G3u1vh8JKWDpMQ8kfXrG1" 'False) (C1 ('MetaCons "TargetModule" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ModuleName)) :+: C1 ('MetaCons "TargetFile" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 NormalizedFilePath)))
Methods from :: Target -> Rep Target x # to :: Rep Target x -> Target #
Show Target # |
Instance details Defined in Development.IDE.Types.KnownTargets Methods showsPrec :: Int -> Target -> ShowS # show :: Target -> String # showList :: [Target] -> ShowS #
Eq Target # |
Instance details Defined in Development.IDE.Types.KnownTargets Methods (==) :: Target -> Target -> Bool # (/=) :: Target -> Target -> Bool #
Ord Target # |
Instance details Defined in Development.IDE.Types.KnownTargets Methods compare :: Target -> Target -> Ordering # (<) :: Target -> Target -> Bool # (<=) :: Target -> Target -> Bool # (>) :: Target -> Target -> Bool # (>=) :: Target -> Target -> Bool # max :: Target -> Target -> Target # min :: Target -> Target -> Target #
Hashable Target # |
Instance details Defined in Development.IDE.Types.KnownTargets Methods hashWithSalt :: Int -> Target -> Int # hash :: Target -> Int #
type Rep Target # |
Instance details Defined in Development.IDE.Types.KnownTargets type Rep Target = D1 ('MetaData "Target" "Development.IDE.Types.KnownTargets" "ghcide-2.9.0.0-1G3u1vh8JKWDpMQ8kfXrG1" 'False) (C1 ('MetaCons "TargetModule" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 ModuleName)) :+: C1 ('MetaCons "TargetFile" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 NormalizedFilePath)))

toKnownFiles :: KnownTargets -> HashSet NormalizedFilePath #

unionKnownTargets :: KnownTargets -> KnownTargets -> KnownTargets #

mkKnownTargets :: [(Target, HashSet NormalizedFilePath)] -> KnownTargets #

type IdeRule k v = (RuleResult k ~ v, ShakeValue k, Show v, Typeable v, NFData v) #

type IdeResult v = ([FileDiagnostic], Maybe v) #

The result of an IDE operation. Warnings and errors are in the Diagnostic, and a value is in the Maybe. For operations that throw an error you expect a non-empty list of diagnostics, at least one of which is an error, and a Nothing. For operations that succeed you expect perhaps some warnings and a Just. For operations that depend on other failing operations you may get empty diagnostics and a Nothing, to indicate this phase throws no fresh errors but still failed.

A rule on a file should only return diagnostics for that given file. It should not propagate diagnostic errors through multiple phases.

newtype GetModificationTime #

Constructors

GetModificationTime_ |
Fields missingFileDiagnostics :: Bool If false, missing file diagnostics are not reported

Bundled Patterns

pattern GetModificationTime :: GetModificationTime |

#### Instances

Instances details

NFData GetModificationTime # |
Instance details Defined in Development.IDE.Core.RuleTypes Methods rnf :: GetModificationTime -> () #
Generic GetModificationTime # |
Instance details Defined in Development.IDE.Core.RuleTypes Associated Types
type Rep GetModificationTime |
Instance details Defined in Development.IDE.Core.RuleTypes type Rep GetModificationTime = D1 ('MetaData "GetModificationTime" "Development.IDE.Core.RuleTypes" "ghcide-2.9.0.0-1G3u1vh8JKWDpMQ8kfXrG1" 'True) (C1 ('MetaCons "GetModificationTime_" 'PrefixI 'True) (S1 ('MetaSel ('Just "missingFileDiagnostics") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Bool)))
Methods from :: GetModificationTime -> Rep GetModificationTime x # to :: Rep GetModificationTime x -> GetModificationTime #
Show GetModificationTime # |
Instance details Defined in Development.IDE.Core.RuleTypes Methods showsPrec :: Int -> GetModificationTime -> ShowS # show :: GetModificationTime -> String # showList :: [GetModificationTime] -> ShowS #
Eq GetModificationTime # |
Instance details Defined in Development.IDE.Core.RuleTypes Methods (==) :: GetModificationTime -> GetModificationTime -> Bool # (/=) :: GetModificationTime -> GetModificationTime -> Bool #
Hashable GetModificationTime # |
Instance details Defined in Development.IDE.Core.RuleTypes Methods hashWithSalt :: Int -> GetModificationTime -> Int # hash :: GetModificationTime -> Int #
type Rep GetModificationTime # |
Instance details Defined in Development.IDE.Core.RuleTypes type Rep GetModificationTime = D1 ('MetaData "GetModificationTime" "Development.IDE.Core.RuleTypes" "ghcide-2.9.0.0-1G3u1vh8JKWDpMQ8kfXrG1" 'True) (C1 ('MetaCons "GetModificationTime_" 'PrefixI 'True) (S1 ('MetaSel ('Just "missingFileDiagnostics") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Bool)))
type RuleResult GetModificationTime # | Get the modification time of a file.
Instance details Defined in Development.IDE.Core.RuleTypes type RuleResult GetModificationTime = FileVersion

shakeOpen #

Arguments

:: Recorder (WithPriority Log) |
-> Maybe (LanguageContextEnv Config) |
-> Config |
-> IdePlugins IdeState |
-> Debouncer NormalizedUri |
-> Maybe FilePath |
-> IdeReportProgress |
-> IdeTesting |
-> WithHieDb |
-> ThreadQueue |
-> ShakeOptions |
-> Monitoring |
-> Rules () |
-> FilePath | Root directory, this one might be picking up from `LanguageContextEnv`'s `resRootPath` , see Note [Root Directory]
-> IO IdeState |

Open a `IdeState`, should be shut using `shakeShut`.

shakeShut :: IdeState -> IO () #

shakeEnqueue :: ShakeExtras -> DelayedAction a -> IO (IO a) #

Enqueue an action in the existing `ShakeSession`. Returns a computation to block until the action is run, propagating exceptions. Assumes a `ShakeSession` is available.

Appropriate for user actions other than edits.

newSession :: Recorder (WithPriority Log) -> ShakeExtras -> VFSModified -> ShakeDatabase -> [DelayedActionInternal] -> String -> IO ShakeSession #

Set up a new `ShakeSession` with a set of initial actions Will crash if there is an existing `ShakeSession` running.

use :: IdeRule k v => k -> NormalizedFilePath -> Action (Maybe v) #

Request a Rule result if available

useNoFile :: IdeRule k v => k -> Action (Maybe v) #

uses :: (Traversable f, IdeRule k v) => k -> f NormalizedFilePath -> Action (f (Maybe v)) #

Plural version of `use`

useWithStaleFast :: IdeRule k v => k -> NormalizedFilePath -> IdeAction (Maybe (v, PositionMapping)) #

Lookup value in the database and return with the stale value immediately Will queue an action to refresh the value. Might block the first time the rule runs, but never blocks after that.

useWithStaleFast' :: IdeRule k v => k -> NormalizedFilePath -> IdeAction (FastResult v) #

Same as useWithStaleFast but lets you wait for an up to date result

delayedAction :: DelayedAction a -> IdeAction (IO a) #

These actions are run asynchronously after the current action is finished running. For example, to trigger a key build after a rule has already finished as is the case with useWithStaleFast

data FastResult a #

A (maybe) stale result now, and an up to date one later

Constructors

FastResult |
Fields stale :: Maybe (a, PositionMapping) uptoDate :: IO (Maybe a)

use_ :: IdeRule k v => k -> NormalizedFilePath -> Action v #

useNoFile_ :: IdeRule k v => k -> Action v #

uses_ :: (Traversable f, IdeRule k v) => k -> f NormalizedFilePath -> Action (f v) #

Plural version of `use_`

Throws an `BadDependency` exception which is caught by the rule system if none available.

WARNING: Not suitable for PluginHandlers. Use `usesE` instead.

useWithStale :: IdeRule k v => k -> NormalizedFilePath -> Action (Maybe (v, PositionMapping)) #

Request a Rule result, it not available return the last computed result, if any, which may be stale

usesWithStale :: (Traversable f, IdeRule k v) => k -> f NormalizedFilePath -> Action (f (Maybe (v, PositionMapping))) #

Return the last computed result which might be stale.

useWithStale_ :: IdeRule k v => k -> NormalizedFilePath -> Action (v, PositionMapping) #

Request a Rule result, it not available return the last computed result which may be stale.

Throws an `BadDependency` exception which is caught by the rule system if none available.

WARNING: Not suitable for PluginHandlers. Use `useWithStaleE` instead.

usesWithStale_ :: (Traversable f, IdeRule k v) => k -> f NormalizedFilePath -> Action (f (v, PositionMapping)) #

Plural version of `useWithStale_`

Throws an `BadDependency` exception which is caught by the rule system if none available.

WARNING: Not suitable for PluginHandlers.

newtype BadDependency #

When we depend on something that reported an error, and we fail as a direct result, throw BadDependency which short-circuits the rest of the action

Constructors

BadDependency String |

#### Instances

Instances details

Exception BadDependency # |
Instance details Defined in Development.IDE.Types.Shake Methods toException :: BadDependency -> SomeException # fromException :: SomeException -> Maybe BadDependency # displayException :: BadDependency -> String # backtraceDesired :: BadDependency -> Bool #
Show BadDependency # |
Instance details Defined in Development.IDE.Types.Shake Methods showsPrec :: Int -> BadDependency -> ShowS # show :: BadDependency -> String # showList :: [BadDependency] -> ShowS #

data RuleBody k v #

Constructors

Rule (k -> NormalizedFilePath -> Action (Maybe ByteString, IdeResult v)) |
RuleNoDiagnostics (k -> NormalizedFilePath -> Action (Maybe ByteString, Maybe v)) |
RuleWithCustomNewnessCheck |
Fields newnessCheck :: ByteString -> ByteString -> Bool build :: k -> NormalizedFilePath -> Action (Maybe ByteString, Maybe v)
RuleWithOldValue (k -> NormalizedFilePath -> Value v -> Action (Maybe ByteString, IdeResult v)) |

define :: IdeRule k v => Recorder (WithPriority Log) -> (k -> NormalizedFilePath -> Action (IdeResult v)) -> Rules () #

Define a new Rule without early cutoff

defineNoDiagnostics :: IdeRule k v => Recorder (WithPriority Log) -> (k -> NormalizedFilePath -> Action (Maybe v)) -> Rules () #

defineEarlyCutoff :: IdeRule k v => Recorder (WithPriority Log) -> RuleBody k v -> Rules () #

Define a new Rule with early cutoff

defineNoFile :: IdeRule k v => Recorder (WithPriority Log) -> (k -> Action v) -> Rules () #

defineEarlyCutOffNoFile :: IdeRule k v => Recorder (WithPriority Log) -> (k -> Action (ByteString, v)) -> Rules () #

getDiagnostics :: IdeState -> STM [FileDiagnostic] #

mRunLspT :: Applicative m => Maybe (LanguageContextEnv c) -> LspT c m () -> m () #

mRunLspTCallback :: Monad m => Maybe (LanguageContextEnv c) -> (LspT c m a -> LspT c m a) -> m a -> m a #

getHiddenDiagnostics :: IdeState -> STM [FileDiagnostic] #

class Typeable a => IsIdeGlobal (a :: k) #

#### Instances

Instances details

IsIdeGlobal OfInterestVar # |
Instance details Defined in Development.IDE.Core.OfInterest
IsIdeGlobal CompiledLinkables # |
Instance details Defined in Development.IDE.Core.Rules
IsIdeGlobal DisplayTHWarning # |
Instance details Defined in Development.IDE.Core.Rules
IsIdeGlobal GlobalIdeOptions # |
Instance details Defined in Development.IDE.Core.Shake

addIdeGlobal :: IsIdeGlobal a => a -> Rules () #

addIdeGlobalExtras :: IsIdeGlobal a => ShakeExtras -> a -> IO () #

getIdeGlobalState :: IsIdeGlobal a => IdeState -> IO a #

getIdeGlobalAction :: (HasCallStack, IsIdeGlobal a) => Action a #

getIdeGlobalExtras :: (HasCallStack, IsIdeGlobal a) => ShakeExtras -> IO a #

getIdeOptions :: Action IdeOptions #

getIdeOptionsIO :: ShakeExtras -> IO IdeOptions #

newtype GlobalIdeOptions #

Constructors

GlobalIdeOptions IdeOptions |

#### Instances

Instances details

IsIdeGlobal GlobalIdeOptions # |
Instance details Defined in Development.IDE.Core.Shake

getClientConfig :: MonadLsp Config m => m Config #

Returns the current client configuration. It is not wise to permanently cache the returned value of this function, as clients can at runtime change their configuration.

getPluginConfigAction :: PluginId -> Action PluginConfig #

knownTargets :: Action (Hashed KnownTargets) #

Get all the files in the project

ideLogger :: IdeState -> Recorder (WithPriority Log) #

actionLogger :: Action (Recorder (WithPriority Log)) #

getVirtualFile :: NormalizedFilePath -> Action (Maybe VirtualFile) #

Read a virtual file from the current snapshot

data FileVersion #

Either the mtime from disk or an LSP version LSP versions always compare as greater than on disk versions

Constructors

ModificationTime !POSIXTime |
VFSVersion !Int32 |

#### Instances

Instances details

NFData FileVersion # |
Instance details Defined in Development.IDE.Core.RuleTypes Methods rnf :: FileVersion -> () #
Generic FileVersion # |
Instance details Defined in Development.IDE.Core.RuleTypes Associated Types
type Rep FileVersion |
Instance details Defined in Development.IDE.Core.RuleTypes type Rep FileVersion = D1 ('MetaData "FileVersion" "Development.IDE.Core.RuleTypes" "ghcide-2.9.0.0-1G3u1vh8JKWDpMQ8kfXrG1" 'False) (C1 ('MetaCons "ModificationTime" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 POSIXTime)) :+: C1 ('MetaCons "VFSVersion" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Int32)))
Methods from :: FileVersion -> Rep FileVersion x # to :: Rep FileVersion x -> FileVersion #
Show FileVersion # |
Instance details Defined in Development.IDE.Core.RuleTypes Methods showsPrec :: Int -> FileVersion -> ShowS # show :: FileVersion -> String # showList :: [FileVersion] -> ShowS #
Eq FileVersion # |
Instance details Defined in Development.IDE.Core.RuleTypes Methods (==) :: FileVersion -> FileVersion -> Bool # (/=) :: FileVersion -> FileVersion -> Bool #
Ord FileVersion # |
Instance details Defined in Development.IDE.Core.RuleTypes Methods compare :: FileVersion -> FileVersion -> Ordering # (<) :: FileVersion -> FileVersion -> Bool # (<=) :: FileVersion -> FileVersion -> Bool # (>) :: FileVersion -> FileVersion -> Bool # (>=) :: FileVersion -> FileVersion -> Bool # max :: FileVersion -> FileVersion -> FileVersion # min :: FileVersion -> FileVersion -> FileVersion #
type Rep FileVersion # |
Instance details Defined in Development.IDE.Core.RuleTypes type Rep FileVersion = D1 ('MetaData "FileVersion" "Development.IDE.Core.RuleTypes" "ghcide-2.9.0.0-1G3u1vh8JKWDpMQ8kfXrG1" 'False) (C1 ('MetaCons "ModificationTime" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 POSIXTime)) :+: C1 ('MetaCons "VFSVersion" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Int32)))

updatePositionMapping :: IdeState -> VersionedTextDocumentIdentifier -> [TextDocumentContentChangeEvent] -> STM () #

updatePositionMappingHelper :: Int32 -> [TextDocumentContentChangeEvent] -> EnumMap Int32 (PositionDelta, PositionMapping) -> EnumMap Int32 (PositionDelta, PositionMapping) #

deleteValue :: ShakeValue k => ShakeExtras -> k -> NormalizedFilePath -> STM [Key] #

Delete the value stored for a given ide build key and return the key that was deleted.

type WithProgressFunc = forall a. Text -> ProgressCancellable -> ((ProgressAmount -> IO ()) -> IO a) -> IO a #

type WithIndefiniteProgressFunc = forall a. Text -> ProgressCancellable -> IO a -> IO a #

data ProgressEvent #

Constructors

KickStarted |
KickCompleted |

data DelayedAction a #

#### Instances

Instances details

Functor DelayedAction # |
Instance details Defined in Development.IDE.Types.Action Methods fmap :: (a -> b) -> DelayedAction a -> DelayedAction b # (<$) :: a -> DelayedAction b -> DelayedAction a #
Show (DelayedAction a) # |
Instance details Defined in Development.IDE.Types.Action Methods showsPrec :: Int -> DelayedAction a -> ShowS # show :: DelayedAction a -> String # showList :: [DelayedAction a] -> ShowS #
Eq (DelayedAction a) # |
Instance details Defined in Development.IDE.Types.Action Methods (==) :: DelayedAction a -> DelayedAction a -> Bool # (/=) :: DelayedAction a -> DelayedAction a -> Bool #
Hashable (DelayedAction a) # |
Instance details Defined in Development.IDE.Types.Action Methods hashWithSalt :: Int -> DelayedAction a -> Int # hash :: DelayedAction a -> Int #

mkDelayedAction :: String -> Priority -> Action a -> DelayedAction a #

newtype IdeAction a #

IdeActions are used when we want to return a result immediately, even if it is stale Useful for UI actions like hover, completion where we don't want to block.

Run via `runIdeAction`.

Constructors

IdeAction |
Fields runIdeActionT :: ReaderT ShakeExtras IO a

#### Instances

Instances details

MonadIO IdeAction # |
Instance details Defined in Development.IDE.Core.Shake Methods liftIO :: IO a -> IdeAction a #
Applicative IdeAction # |
Instance details Defined in Development.IDE.Core.Shake Methods pure :: a -> IdeAction a # (<*>) :: IdeAction (a -> b) -> IdeAction a -> IdeAction b # liftA2 :: (a -> b -> c) -> IdeAction a -> IdeAction b -> IdeAction c # (*>) :: IdeAction a -> IdeAction b -> IdeAction b # (<*) :: IdeAction a -> IdeAction b -> IdeAction a #
Functor IdeAction # |
Instance details Defined in Development.IDE.Core.Shake Methods fmap :: (a -> b) -> IdeAction a -> IdeAction b # (<$) :: a -> IdeAction b -> IdeAction a #
Monad IdeAction # |
Instance details Defined in Development.IDE.Core.Shake Methods (>>=) :: IdeAction a -> (a -> IdeAction b) -> IdeAction b # (>>) :: IdeAction a -> IdeAction b -> IdeAction b # return :: a -> IdeAction a #
MonadReader ShakeExtras IdeAction # |
Instance details Defined in Development.IDE.Core.Shake Methods ask :: IdeAction ShakeExtras # local :: (ShakeExtras -> ShakeExtras) -> IdeAction a -> IdeAction a # reader :: (ShakeExtras -> a) -> IdeAction a #
Semigroup a => Semigroup (IdeAction a) # |
Instance details Defined in Development.IDE.Core.Shake Methods (<>) :: IdeAction a -> IdeAction a -> IdeAction a # sconcat :: NonEmpty (IdeAction a) -> IdeAction a # stimes :: Integral b => b -> IdeAction a -> IdeAction a #

runIdeAction :: String -> ShakeExtras -> IdeAction a -> IO a #

mkUpdater :: NameCache -> NameCacheUpdater #

newtype Q k #

Constructors

Q (k, NormalizedFilePath) |

#### Instances

Instances details

NFData k => NFData (Q k) # |
Instance details Defined in Development.IDE.Types.Shake Methods rnf :: Q k -> () #
Show k => Show (Q k) # |
Instance details Defined in Development.IDE.Types.Shake Methods showsPrec :: Int -> Q k -> ShowS # show :: Q k -> String # showList :: [Q k] -> ShowS #
Eq k => Eq (Q k) # |
Instance details Defined in Development.IDE.Types.Shake Methods (==) :: Q k -> Q k -> Bool # (/=) :: Q k -> Q k -> Bool #
Hashable k => Hashable (Q k) # |
Instance details Defined in Development.IDE.Types.Shake Methods hashWithSalt :: Int -> Q k -> Int # hash :: Q k -> Int #
type RuleResult (Q k) # |
Instance details Defined in Development.IDE.Types.Shake type RuleResult (Q k) = A (RuleResult k)

type IndexQueue = TQueue (((HieDb -> IO ()) -> IO ()) -> IO ()) #

Actions to queue up on the index worker thread The inner `(HieDb -> IO ()) -> IO ()` wraps `HieDb -> IO ()` with (currently) retry functionality

data HieDb #

data HieDbWriter #

We need to serialize writes to the database, so we send any function that needs to write to the database over the channel, where it will be picked up by a worker thread.

Constructors

HieDbWriter |
Fields indexQueue :: IndexQueue indexPending :: TVar (HashMap NormalizedFilePath Fingerprint) Avoid unnecessary/out of date indexing indexCompleted :: TVar Int to report progress indexProgressToken :: Var (Maybe ProgressToken) This is a Var instead of a TVar since we need to do IO to initialise/update, so we need a lock

addPersistentRule :: IdeRule k v => k -> (NormalizedFilePath -> IdeAction (Maybe (v, PositionDelta, Maybe Int32))) -> Rules () #

Register a function that will be called to get the "stale" result of a rule, possibly from disk This is called when we don't already have a result, or computing the rule failed. The result of this function will always be marked as `stale`, and a `proper` rebuild of the rule will be queued if the rule hasn't run before.

garbageCollectDirtyKeys :: Action [Key] #

Find and release old keys from the state Hashmap For the record, there are other state sources that this process does not release: * diagnostics store (normal, hidden and published) * position mapping store * indexing queue * exports map

garbageCollectDirtyKeysOlderThan :: Int -> CheckParents -> Action [Key] #

data Log #

Constructors

LogCreateHieDbExportsMapStart |
LogCreateHieDbExportsMapFinish !Int |
LogBuildSessionRestart !String ![DelayedActionInternal] !KeySet !Seconds !(Maybe FilePath) |
LogBuildSessionRestartTakingTooLong !Seconds |
LogDelayedAction !(DelayedAction ()) !Seconds |
LogBuildSessionFinish !(Maybe SomeException) |
LogDiagsDiffButNoLspEnv ![FileDiagnostic] |
LogDefineEarlyCutoffRuleNoDiagHasDiag !FileDiagnostic |
LogDefineEarlyCutoffRuleCustomNewnessHasDiag !FileDiagnostic |
LogCancelledAction !Text |
LogSessionInitialised |
LogLookupPersistentKey !Text |
LogShakeGarbageCollection !Text !Int !Seconds |
LogSetFilesOfInterest ![(NormalizedFilePath, FileOfInterestStatus)] |

#### Instances

Instances details

Show Log # |
Instance details Defined in Development.IDE.Core.Shake Methods showsPrec :: Int -> Log -> ShowS # show :: Log -> String # showList :: [Log] -> ShowS #
Pretty Log # |
Instance details Defined in Development.IDE.Core.Shake Methods pretty :: Log -> Doc ann # prettyList :: [Log] -> Doc ann #

data VFSModified #

Constructors

VFSUnmodified |
VFSModified !VFS |

getClientConfigAction :: Action Config #

Returns the client configuration, creating a build dependency. You should always use this function when accessing client configuration from build rules.

data ThreadQueue #

Constructors

ThreadQueue |
Fields tIndexQueue :: IndexQueue tRestartQueue :: TQueue (IO ()) tLoaderQueue :: TQueue (IO ())