1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
12import Control.Monad.Except (liftIO)
13import qualified Data.ByteString as BS
14import qualified Data.Map as Map
15import qualified Data.Time.Calendar as Day
16import qualified Data.Time.Clock as Time
17import qualified System.Directory as Dir
19import qualified AST.Source as Src
20import qualified Elm.Compiler.Imports as Imports
21import qualified Elm.ModuleName as ModuleName
22import qualified Elm.Package as Pkg
23import qualified Elm.Project.Json as Project
24import Elm.Project.Json (Project)
25import Elm.Project.Summary (Summary(..))
26import qualified File.IO as IO
27import qualified Parse.Module as Module
28import Parse.Utils (Parser)
29import qualified Parse.Primitives as P
30import qualified Reporting.Annotation as A
31import qualified Reporting.Exit as Exit
32import qualified Reporting.Exit.Crawl as E
33import qualified Reporting.Task as Task
43 , _time :: Time.UTCTime
44 , _source :: BS.ByteString
45 , _imports :: [ModuleName.Raw]
49atRoot :: Task.Task_ E.Problem a -> Task.Task_ E.Exit a
51 Task.mapError (\problem -> E.DependencyProblems problem []) task
57readModule :: Summary -> ModuleName.Raw -> FilePath -> Task.Task_ E.Problem (ModuleName.Raw, Info)
58readModule summary expectedName path =
59 do time <- liftIO $ Dir.getModificationTime path
60 source <- liftIO $ IO.readUtf8 path
61 (maybeName, info) <- parse (_project summary) path time source
62 name <- checkName path expectedName maybeName
66checkName :: FilePath -> ModuleName.Raw -> Maybe ModuleName.Raw -> Task.Task_ E.Problem ModuleName.Raw
67checkName path expectedName maybeName =
70 Task.throw (E.ModuleNameMissing path expectedName)
73 if expectedName == actualName
74 then return expectedName
75 else Task.throw (E.ModuleNameMismatch path expectedName actualName)
82readOneFile :: Summary -> FilePath -> Task.Task (Maybe ModuleName.Raw, Info)
83readOneFile summary path =
84 Task.mapError Exit.Crawl $
85 do (time, source) <- readOneHelp path
86 atRoot $ parse (_project summary) path time source
89readOneHelp :: FilePath -> Task.Task_ E.Exit (Time.UTCTime, BS.ByteString)
91 do exists <- liftIO $ IO.exists path
93 then liftIO $ (,) <$> Dir.getModificationTime path <*> IO.readUtf8 path
94 else Task.throw $ E.RootFileNotFound path
101readManyFiles :: Summary -> FilePath -> [FilePath] -> Task.Task ((ModuleName.Raw, Info), [(ModuleName.Raw, Info)])
102readManyFiles summary file files =
103 Task.mapError Exit.Crawl $
104 do info <- readManyFilesHelp summary file
105 infos <- traverse (readManyFilesHelp summary) files
106 let nameTable = foldr insert Map.empty (info:infos)
107 _ <- Map.traverseWithKey detectDuplicateNames nameTable
110 append (x,xs) (y,ys) = (x, xs ++ y : ys)
111 insert (k,v) dict = Map.insertWith append k (v, []) dict
114readManyFilesHelp :: Summary -> FilePath -> Task.Task_ E.Exit (ModuleName.Raw, Info)
115readManyFilesHelp summary path =
116 do (time, source) <- readOneHelp path
117 (maybeName, info) <- atRoot $ parse (_project summary) path time source
120 Task.throw (E.RootNameless path)
126detectDuplicateNames :: ModuleName.Raw -> (Info, [Info]) -> Task.Task_ E.Exit ()
127detectDuplicateNames name (info, otherInfos) =
133 Task.throw (E.RootModuleNameDuplicate name (map _path (info : otherInfos)))
141readSource :: Project -> BS.ByteString -> Task.Task (Maybe ModuleName.Raw, Info)
142readSource project source =
143 Task.mapError Exit.Crawl $
144 atRoot $ parse project "elm" fakeTime source
147fakeTime :: Time.UTCTime
149 Time.UTCTime (Day.fromGregorian 3000 1 1) 0
156parse :: Project -> FilePath -> Time.UTCTime -> BS.ByteString -> Task.Task_ E.Problem (Maybe ModuleName.Raw, Info)
157parse project path time source =
158 -- TODO get regions on data extracted here
159 case P.fromByteString parser source of
160 P.Ok (maybeHeader, imports) _ ->
163 map (\(Src.Import (A.At _ name) _ _) -> name) $
164 if Project.getName project == Pkg.core
166 else Imports.addDefaults imports
168 do maybeName <- checkTag project path maybeHeader
169 return ( maybeName, Info path time source deps )
172 Task.throw (error "TODO give an error on bad headers / stop having a double parse")
175parser :: Parser (Maybe Module.Header, [Src.Import])
178 header <- Module.chompHeader
179 Module.maybeSkipDocComment
180 imports <- Module.chompImports []
181 return (header, imports)
184checkTag :: Project -> FilePath -> Maybe Module.Header -> Task.Task_ E.Problem (Maybe ModuleName.Raw)
185checkTag project path maybeHeader =
190 Just (Module.Header name effects _) ->
192 Module.NoEffects _ ->
197 Project.App _ -> return (Just name)
198 Project.Pkg _ -> Task.throw (E.PortsInPackage path name)
200 Module.Manager _ _ ->
201 if Project.isPlatformPackage project
202 then return (Just name)
203 else Task.throw (E.EffectsUnexpected path name)
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