Skip to content
This repository was archived by the owner on Aug 23, 2018. It is now read-only.

Commit 5c7c8a2

Browse files
committed
Beginning of refactor
Start a refactor to better organize the code in this repo. This change also begins addressing error reporting stuff described in #23, #47, and #46. It also adds rudimentary timing information so we know how long different phases take.
1 parent d9bedfd commit 5c7c8a2

15 files changed

+694
-556
lines changed

elm-make.cabal

+7-6
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ Executable elm-make
4040
Main.hs
4141

4242
other-modules:
43-
Arguments,
44-
Build,
45-
CrawlPackage,
46-
CrawlProject,
47-
Generate,
48-
LoadInterfaces,
43+
Flags,
4944
Path,
5045
Paths_elm_make,
46+
Pipeline.Compile,
47+
Pipeline.Crawl,
48+
Pipeline.Crawl.Package,
49+
Pipeline.Generate,
50+
Pipeline.Plan,
5151
Report,
5252
TheMasterPlan,
5353
Utils.File,
@@ -68,4 +68,5 @@ Executable elm-make
6868
filepath,
6969
mtl >= 2.2.1 && < 3,
7070
optparse-applicative >=0.11 && <0.12,
71+
time,
7172
text

src/BuildManager.hs

+203
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
{-# OPTIONS_GHC -Wall #-}
2+
module BuildManager where
3+
4+
import Control.Monad.Except (ExceptT, runExceptT)
5+
import Control.Monad.State (StateT, liftIO, runStateT)
6+
import qualified Control.Monad.State as State
7+
import qualified Data.Time.Clock.POSIX as Time
8+
import qualified Elm.Compiler as Compiler
9+
import qualified Elm.Compiler.Module as Module
10+
import qualified Elm.Package.Name as Pkg
11+
import qualified Elm.Package.Paths as Path
12+
import System.FilePath ((</>))
13+
14+
import qualified Report
15+
import qualified TheMasterPlan as TMP
16+
17+
18+
-- CONFIGURATION
19+
20+
data Config = Config
21+
{ _artifactDirectory :: FilePath
22+
, _files :: [FilePath]
23+
, _output :: Output
24+
, _autoYes :: Bool
25+
, _reportType :: Report.Type
26+
, _warn :: Bool
27+
, _docs :: Maybe FilePath
28+
}
29+
30+
31+
data Output
32+
= Html FilePath
33+
| JS FilePath
34+
35+
36+
outputFilePath :: Config -> FilePath
37+
outputFilePath config =
38+
case _output config of
39+
Html file -> file
40+
JS file -> file
41+
42+
43+
artifactDirectory :: FilePath
44+
artifactDirectory =
45+
Path.stuffDirectory </> "build-artifacts"
46+
47+
48+
-- RUN A BUILD
49+
50+
type Task a =
51+
ExceptT Error (StateT [Phase] IO) a
52+
53+
54+
run :: Task a -> IO (Either Error (a, Timeline))
55+
run task =
56+
do result <-
57+
runStateT (runExceptT (phase "elm-make" task)) []
58+
case result of
59+
(Right answer, [Phase _ start phases end]) ->
60+
return (Right (answer, Timeline start phases end))
61+
62+
(Left err, _) ->
63+
return (Left err)
64+
65+
66+
-- TIMELINE
67+
68+
data Timeline = Timeline
69+
{ _start :: Time.POSIXTime
70+
, _phases :: [Phase]
71+
, _end :: Time.POSIXTime
72+
}
73+
74+
75+
data Phase = Phase
76+
{ _tag :: String
77+
, _start_ :: Time.POSIXTime
78+
, _subphases :: [Phase]
79+
, _end_ :: Time.POSIXTime
80+
}
81+
82+
83+
phase :: String -> Task a -> Task a
84+
phase name task =
85+
do phasesSoFar <- State.get
86+
State.put []
87+
start <- liftIO Time.getPOSIXTime
88+
result <- task
89+
end <- liftIO Time.getPOSIXTime
90+
State.modify' (\phases -> Phase name start (reverse phases) end : phasesSoFar)
91+
return result
92+
93+
94+
timelineToString :: Timeline -> String
95+
timelineToString (Timeline start phases end) =
96+
let
97+
duration = end - start
98+
in
99+
"\nOverall time: " ++ show duration ++ "\n"
100+
++ concatMap (phaseToString duration 1) phases
101+
++ "\n"
102+
103+
104+
phaseToString :: Time.POSIXTime -> Int -> Phase -> String
105+
phaseToString overallDuration indent (Phase tag start subphases end) =
106+
let
107+
duration = end - start
108+
percent = truncate (100 * duration / overallDuration) :: Int
109+
in
110+
'\n' : replicate (indent * 4) ' ' ++ show percent ++ "% - " ++ tag
111+
++ concatMap (phaseToString duration (indent + 1)) subphases
112+
113+
114+
-- ERRORS
115+
116+
data Error
117+
= BadFlags
118+
| CompilerErrors FilePath String [Compiler.Error]
119+
| CorruptedArtifact FilePath
120+
| Cycle [TMP.CanonicalModule]
121+
| PackageProblem String
122+
| MissingPackage Pkg.Name
123+
| ModuleNotFound Module.Name (Maybe Module.Name)
124+
| ModuleDuplicates
125+
{ _name :: Module.Name
126+
, _parent :: Maybe Module.Name
127+
, _local :: [FilePath]
128+
, _foreign :: [Pkg.Name]
129+
}
130+
| ModuleName
131+
{ _path :: FilePath
132+
, _expectedName :: Module.Name
133+
, _actualName :: Module.Name
134+
}
135+
136+
137+
errorToString :: Error -> String
138+
errorToString err =
139+
case err of
140+
BadFlags ->
141+
error "TODO bad flags"
142+
143+
CompilerErrors _ _ _ ->
144+
error "TODO"
145+
146+
CorruptedArtifact filePath ->
147+
concat
148+
[ "Error reading build artifact ", filePath, "\n"
149+
, " The file was generated by a previous build and may be outdated or corrupt.\n"
150+
, " Please remove the file and try again."
151+
]
152+
153+
Cycle moduleCycle ->
154+
"Your dependencies form a cycle:\n\n"
155+
++ error "TODO" moduleCycle
156+
++ "\nYou may need to move some values to a new module to get rid of the cycle."
157+
158+
PackageProblem msg ->
159+
msg
160+
161+
MissingPackage name ->
162+
error "TODO" name
163+
164+
ModuleNotFound name maybeParent ->
165+
unlines
166+
[ "Error when searching for modules" ++ toContext maybeParent ++ ":"
167+
, " Could not find module '" ++ Module.nameToString name ++ "'"
168+
, ""
169+
, "Potential problems could be:"
170+
, " * Misspelled the module name"
171+
, " * Need to add a source directory or new dependency to " ++ Path.description
172+
]
173+
174+
ModuleDuplicates name maybeParent filePaths pkgs ->
175+
"Error when searching for modules" ++ toContext maybeParent ++ ".\n" ++
176+
"Found multiple modules named '" ++ Module.nameToString name ++ "'\n" ++
177+
"Modules with that name were found in the following locations:\n\n" ++
178+
concatMap (\str -> " " ++ str ++ "\n") (paths ++ packages)
179+
where
180+
packages =
181+
map ("package " ++) (map Pkg.toString pkgs)
182+
183+
paths =
184+
map ("directory " ++) filePaths
185+
186+
ModuleName path nameFromPath nameFromSource ->
187+
unlines
188+
[ "The module name is messed up for " ++ path
189+
, " According to the file's name it should be " ++ Module.nameToString nameFromPath
190+
, " According to the source code it should be " ++ Module.nameToString nameFromSource
191+
, "Which is it?"
192+
]
193+
194+
195+
toContext :: Maybe Module.Name -> String
196+
toContext maybeParent =
197+
case maybeParent of
198+
Nothing ->
199+
" exposed by " ++ Path.description
200+
201+
Just parent ->
202+
" imported by module '" ++ Module.nameToString parent ++ "'"
203+

src/CrawlProject.hs

-53
This file was deleted.

0 commit comments

Comments
 (0)