futhark-0.28.2: src/Futhark/LSP/State.hs
-- | The language server state definition.
module Futhark.LSP.State
( State (..),
emptyState,
getStaleContent,
getStaleMapping,
updateStaleContent,
updateStaleMapping,
)
where
import Data.Int (Int32)
import Data.Map qualified as M
import Data.Set qualified as S
import Futhark.Compiler.Program (LoadedProg)
import Futhark.LSP.PositionMapping (PositionMapping, StaleFile (..))
import Language.LSP.Protocol.Types (NormalizedUri)
import Language.LSP.VFS (VirtualFile)
-- | The state of the language server.
data State = State
{ -- | The loaded program.
stateProgram :: Maybe LoadedProg,
-- | The stale data, stored to provide PositionMapping when requested.
-- All files that have been opened have an entry.
staleData :: M.Map FilePath StaleFile,
-- | The file and version of the most recent compilation, if it
-- failed. Used to avoid recompiling unchanged files.
stateFailed :: Maybe (FilePath, Int32),
-- | The files for which the most recent compilation published
-- diagnostics. These must be cleared by the next compilation.
stateDiagnosed :: S.Set NormalizedUri
}
-- | Initial state.
emptyState :: State
emptyState = State Nothing M.empty Nothing S.empty
-- | Get the contents of a stale (last successfully complied) file's contents.
getStaleContent :: State -> FilePath -> Maybe VirtualFile
getStaleContent state file_path = (Just . staleContent) =<< M.lookup file_path (staleData state)
-- | Get the PositionMapping for a file.
getStaleMapping :: State -> FilePath -> Maybe PositionMapping
getStaleMapping state file_path = staleMapping =<< M.lookup file_path (staleData state)
-- | Update the state with another pair of file_path and contents.
-- Could do a clean up becausae there is no need to store files that are not in lpFilePaths prog.
updateStaleContent :: FilePath -> VirtualFile -> LoadedProg -> State -> State
updateStaleContent file_path file_content loadedProg state =
-- NOTE: insert will replace the old value if the key already exists.
-- updateStaleContent is only called after a successful type-check,
-- so the PositionsMapping should be Nothing here, it's calculated after failed type-check.
state
{ stateProgram = Just loadedProg,
staleData = M.insert file_path (StaleFile file_content Nothing) (staleData state)
}
-- | Update the state with another pair of file_path and PositionMapping.
updateStaleMapping :: Maybe FilePath -> Maybe PositionMapping -> State -> State
updateStaleMapping (Just file_path) mapping state = do
case M.lookup file_path (staleData state) of
Nothing -> state -- Only happends when the file have never been successfully type-checked before.
Just (StaleFile file_content _mapping) ->
state {staleData = M.insert file_path (StaleFile file_content mapping) (staleData state)}
updateStaleMapping _ _ state = state