on 49f58cf help sign in
elk/builder/src/File/Find.hs
102 lines 2.9 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module File.Find
4 ( Asset(..)
5 , find
6 )
7 where
9import Control.Monad.Except (liftIO)
10import qualified Data.Map as Map
11import qualified Data.Maybe as Maybe
12import qualified System.FilePath as FP
13import qualified System.Directory as Dir
14import System.FilePath ((</>), (<.>))
16import qualified Elm.Compiler.Module as Module
17import qualified Elm.Name as N
18import qualified Elm.Package as Pkg
20import qualified Elm.Project.Json as Project
21import qualified Elm.Project.Summary as Summary
22import qualified Reporting.Exit.Crawl as E
23import qualified Reporting.Task as Task
27-- ASSET
30data Asset
31 = Local FilePath
32 | Kernel FilePath (Maybe FilePath)
33 | Foreign Pkg.Package
37-- FIND
40find :: Summary.Summary -> E.Origin -> Module.Raw -> Task.Task_ E.Problem Asset
41find (Summary.Summary root project exposed _ _) origin name =
42 do here <- liftIO Dir.getCurrentDirectory
43 let toRoot dir = FP.makeRelative here (root </> dir)
44 case project of
45 Project.App info ->
46 do let srcDirs = map toRoot (Project._app_source_dirs info)
47 findElm srcDirs exposed origin name
49 Project.Pkg _ ->
50 if N.startsWith "Elm.Kernel." name then
51 if Project.isPlatformPackage project then
52 findKernel (toRoot "src") origin name
53 else
54 Task.throw $ E.ModuleNameReservedForKernel origin name
56 else
57 findElm [ toRoot "src" ] exposed origin name
61-- FIND ELM
64findElm :: [FilePath] -> Summary.ExposedModules -> E.Origin -> Module.Raw -> Task.Task_ E.Problem Asset
65findElm srcDirs exposed origin name =
66 do
67 paths <- liftIO $ Maybe.catMaybes <$> mapM (elmExists name) srcDirs
69 case (paths, Map.lookup name exposed) of
70 ([path], Nothing) ->
71 return (Local path)
73 ([], Just [pkg]) ->
74 return (Foreign pkg)
76 ([], Nothing) ->
77 Task.throw $ E.ModuleNotFound origin name srcDirs
79 (_, maybePkgs) ->
80 Task.throw $ E.ModuleAmbiguous origin name paths (maybe [] id maybePkgs)
83elmExists :: Module.Raw -> FilePath -> IO (Maybe FilePath)
84elmExists name srcDir =
85 do let path = srcDir </> Module.nameToSlashPath name <.> "elm"
86 exists <- Dir.doesFileExist path
87 return $ if exists then Just path else Nothing
91-- FIND KERNEL
94findKernel :: FilePath -> E.Origin -> Module.Raw -> Task.Task_ E.Problem Asset
95findKernel srcDir origin name =
96 do let clientPath = srcDir </> Module.nameToSlashPath name <.> "js"
97 let serverPath = srcDir </> Module.nameToSlashPath name <.> "server.js"
98 client <- liftIO $ Dir.doesFileExist clientPath
99 server <- liftIO $ Dir.doesFileExist serverPath
100 if client
101 then return $ Kernel clientPath (if server then Just serverPath else Nothing)
102 else Task.throw $ E.ModuleNotFound origin name [srcDir]