1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
10import Control.Concurrent (forkIO)
11import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)
12import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar, readMVar)
13import Control.Monad (foldM, void, when)
14import Control.Monad.Except (liftIO)
15import qualified Data.Binary as Binary
16import qualified Data.ByteString as BS
17import qualified Data.Map as Map
18import qualified Data.Time.Clock as Time
19import qualified System.Directory as Dir
21import qualified Elm.Interface as I
22import qualified Elm.ModuleName as ModuleName
23import qualified Elm.Package as Pkg
24import qualified Elm.Project.Json as Project
25import qualified Elm.Project.Summary as Summary
26import qualified File.Crawl as Crawl
27import qualified File.Header as Header
28import qualified Reporting.Task as Task
29import qualified Stuff.Paths
36type Dict value = Map.Map ModuleName.Raw value
39plan :: Summary.Summary -> Crawl.Result -> Task.Task (Dict Info, I.Interfaces)
40plan (Summary.Summary root project _ ifaces _) (Crawl.Graph _ locals _ foreigns _) =
43 let env = Env queue root (Project.getName project)
46 statusMVars <- Map.traverseWithKey (getStatus env mvar foreigns) locals
47 putMVar mvar statusMVars
50 do graph <- Map.traverseMaybeWithKey (\_ -> readMVar) statusMVars
51 writeChan queue (EndLoop graph)
53 ifaceLoader queue ifaces
68type Status = Maybe Info
76 , _time :: Time.UTCTime
77 , _src :: BS.ByteString
78 , _clean :: [ModuleName.Raw]
79 , _dirty :: [ModuleName.Raw]
80 , _foreign :: [ModuleName.Canonical] -- TODO is this needed?
90 -> MVar (Dict (MVar Status))
95getStatus env statusMVars foreigns name (Header.Info path time src deps) =
96 do mvar <- newEmptyMVar
98 void $ forkIO $ putMVar mvar =<<
99 do statuses <- readMVar statusMVars
100 info <- foldM (addDep statuses foreigns) (Info path time src [] [] []) deps
102 let elmi = Stuff.Paths.elmi (_root env) name
110 do freshElmi <- isFresh time elmi
111 if name /= "Main" && freshElmi
113 do let canonical = ModuleName.Canonical (_pkg env) name
114 writeChan (_queue env) (Get canonical elmi)
123addDep :: Dict (MVar Status) -> Dict Pkg.Canonical -> Info -> ModuleName.Raw -> IO Info
124addDep locals foreigns info name =
125 case Map.lookup name locals of
127 do status <- readMVar mvar
130 return $ info { _clean = name : _clean info }
133 return $ info { _dirty = name : _dirty info }
136 case Map.lookup name foreigns of
137 Just (Pkg.Canonical pkg _vsn) ->
138 return $ info { _foreign = ModuleName.Canonical pkg name : _foreign info }
141 return info -- must be native
148isFresh :: Time.UTCTime -> FilePath -> IO Bool
149isFresh srcTime cachedFile =
151 [ Dir.doesFileExist cachedFile
152 , do cacheTime <- Dir.getModificationTime cachedFile
153 return (cacheTime >= srcTime)
157andM :: [IO Bool] -> IO Bool
163 check : otherChecks ->
165 if bool then andM otherChecks else return False
168remove :: FilePath -> IO ()
170 do exists <- Dir.doesFileExist path
171 when exists (Dir.removeFile path)
179 = EndLoop (Dict Info)
180 | Get ModuleName.Canonical FilePath
183ifaceLoader :: Chan Msg -> I.Interfaces -> IO (Dict Info, I.Interfaces)
184ifaceLoader queue ifaces =
185 do msg <- readChan queue
188 return ( dirty, ifaces )
190 Get canonical elmi ->
191 case Map.lookup canonical ifaces of
193 ifaceLoader queue ifaces
196 do iface <- Binary.decodeFile elmi
197 ifaceLoader queue $ Map.insert canonical iface ifaces
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list