on master help sign in
track if srcDir is absolute or relative
3c61804Evan Czaplicki
builder/src/Build.hs+83−68
@@ -42,6 +42,7 @@ import qualified Elm.Details as Details
42import qualified Elm.Docs as Docs
42import qualified Elm.Docs as Docs
43import qualified Elm.Interface as I
43import qualified Elm.Interface as I
44import qualified Elm.ModuleName as ModuleName
44import qualified Elm.ModuleName as ModuleName
45+import qualified Elm.Outline as Outline
45import qualified Elm.Package as Pkg
46import qualified Elm.Package as Pkg
46import qualified File
47import qualified File
47import qualified Json.Encode as E
48import qualified Json.Encode as E
@@ -65,21 +66,46 @@ data Env =
65 { _key :: Reporting.BKey
66 { _key :: Reporting.BKey
66 , _root :: FilePath
67 , _root :: FilePath
67 , _project :: Parse.ProjectType
68 , _project :: Parse.ProjectType
68− , _srcDirs :: [FilePath]
69+ , _srcDirs :: [AbsoluteSrcDir]
69 , _buildID :: Details.BuildID
70 , _buildID :: Details.BuildID
70 , _locals :: Map.Map ModuleName.Raw Details.Local
71 , _locals :: Map.Map ModuleName.Raw Details.Local
71 , _foreigns :: Map.Map ModuleName.Raw Details.Foreign
72 , _foreigns :: Map.Map ModuleName.Raw Details.Foreign
72 }
73 }
73
74
74
75
75−makeEnv :: Reporting.BKey -> FilePath -> Details.Details -> Env
76+makeEnv :: Reporting.BKey -> FilePath -> Details.Details -> IO Env
76makeEnv key root (Details.Details _ validOutline buildID locals foreigns _) =
77makeEnv key root (Details.Details _ validOutline buildID locals foreigns _) =
77 case validOutline of
78 case validOutline of
78− Details.ValidApp srcDirs ->
79+ Details.ValidApp givenSrcDirs ->
80+ do srcDirs <- traverse (toAbsoluteSrcDir root) (NE.toList givenSrcDirs)
79− Env key root Parse.Application (NE.toList srcDirs) buildID locals foreigns
81+ return $ Env key root Parse.Application srcDirs buildID locals foreigns
80
82
81 Details.ValidPkg pkg _ _ ->
83 Details.ValidPkg pkg _ _ ->
84+ do srcDir <- toAbsoluteSrcDir root (Outline.RelativeSrcDir "src")
82− Env key root (Parse.Package pkg) ["src"] buildID locals foreigns
85+ return $ Env key root (Parse.Package pkg) [srcDir] buildID locals foreigns
86+
87+
88+
89+-- SOURCE DIRECTORY
90+
91+
92+newtype AbsoluteSrcDir =
93+ AbsoluteSrcDir FilePath
94+
95+
96+toAbsoluteSrcDir :: FilePath -> Outline.SrcDir -> IO AbsoluteSrcDir
97+toAbsoluteSrcDir root srcDir =
98+ AbsoluteSrcDir <$> Dir.canonicalizePath
99+ (
100+ case srcDir of
101+ Outline.AbsoluteSrcDir dir -> dir
102+ Outline.RelativeSrcDir dir -> root </> dir
103+ )
104+
105+
106+addRelative :: AbsoluteSrcDir -> FilePath -> FilePath
107+addRelative (AbsoluteSrcDir srcDir) path =
108+ srcDir </> path
83
109
84
110
85
111
@@ -110,7 +136,7 @@ forkWithKey func dict =
110fromExposed :: Reporting.Style -> FilePath -> Details.Details -> DocsGoal docs -> NE.List ModuleName.Raw -> IO (Either Exit.BuildProblem docs)
136fromExposed :: Reporting.Style -> FilePath -> Details.Details -> DocsGoal docs -> NE.List ModuleName.Raw -> IO (Either Exit.BuildProblem docs)
111fromExposed style root details docsGoal exposed@(NE.List e es) =
137fromExposed style root details docsGoal exposed@(NE.List e es) =
112 Reporting.trackBuild style $ \key ->
138 Reporting.trackBuild style $ \key ->
113− do let env = makeEnv key root details
139+ do env <- makeEnv key root details
114 dmvar <- Details.loadInterfaces root details
140 dmvar <- Details.loadInterfaces root details
115
141
116 -- crawl
142 -- crawl
@@ -161,7 +187,7 @@ type Dependencies =
161fromMains :: Reporting.Style -> FilePath -> Details.Details -> NE.List FilePath -> IO (Either Exit.BuildProblem Artifacts)
187fromMains :: Reporting.Style -> FilePath -> Details.Details -> NE.List FilePath -> IO (Either Exit.BuildProblem Artifacts)
162fromMains style root details paths =
188fromMains style root details paths =
163 Reporting.trackBuild style $ \key ->
189 Reporting.trackBuild style $ \key ->
164− do let env = makeEnv key root details
190+ do env <- makeEnv key root details
165
191
166 elmains <- findMains env paths
192 elmains <- findMains env paths
167 case elmains of
193 case elmains of
@@ -241,9 +267,8 @@ crawlDeps env mvar deps blockedValue =
241crawlModule :: Env -> MVar StatusDict -> DocsNeed -> ModuleName.Raw -> IO Status
267crawlModule :: Env -> MVar StatusDict -> DocsNeed -> ModuleName.Raw -> IO Status
242crawlModule env@(Env _ root projectType srcDirs buildID locals foreigns) mvar docsNeed name =
268crawlModule env@(Env _ root projectType srcDirs buildID locals foreigns) mvar docsNeed name =
243 do let fileName = ModuleName.toFilePath name <.> "elm"
269 do let fileName = ModuleName.toFilePath name <.> "elm"
244− let inRoot path = File.exists (root </> path)
245
270
246− paths <- filterM inRoot (map (</> fileName) srcDirs)
271+ paths <- filterM File.exists (map (`addRelative` fileName) srcDirs)
247
272
248 case paths of
273 case paths of
249 [path] ->
274 [path] ->
@@ -263,7 +288,7 @@ crawlModule env@(Env _ root projectType srcDirs buildID locals foreigns) mvar do
263 else crawlDeps env mvar deps (SCached local)
288 else crawlDeps env mvar deps (SCached local)
264
289
265 p1:p2:ps ->
290 p1:p2:ps ->
266− return $ SBadImport $ Import.AmbiguousLocal p1 p2 ps
291+ return $ SBadImport $ Import.AmbiguousLocal (FP.makeRelative root p1) (FP.makeRelative root p2) (map (FP.makeRelative root) ps)
267
292
268 [] ->
293 [] ->
269 case Map.lookup name foreigns of
294 case Map.lookup name foreigns of
@@ -856,35 +881,33 @@ data ReplArtifacts =
856
881
857fromRepl :: FilePath -> Details.Details -> B.ByteString -> IO (Either Exit.Repl ReplArtifacts)
882fromRepl :: FilePath -> Details.Details -> B.ByteString -> IO (Either Exit.Repl ReplArtifacts)
858fromRepl root details source =
883fromRepl root details source =
859− let
860− env@(Env _ _ projectType _ _ _ _) = makeEnv Reporting.ignorer root details
884+ do env@(Env _ _ projectType _ _ _ _) <- makeEnv Reporting.ignorer root details
861− in
862− case Parse.fromByteString projectType source of
885+ case Parse.fromByteString projectType source of
863− Left syntaxError ->
886+ Left syntaxError ->
864− return $ Left $ Exit.ReplBadInput source $ Error.BadSyntax syntaxError
887+ return $ Left $ Exit.ReplBadInput source $ Error.BadSyntax syntaxError
865
888
866− Right modul@(Src.Module _ _ _ imports _ _ _ _ _) ->
889+ Right modul@(Src.Module _ _ _ imports _ _ _ _ _) ->
867− do dmvar <- Details.loadInterfaces root details
890+ do dmvar <- Details.loadInterfaces root details
868
891
869− let deps = map Src.getImportName imports
892+ let deps = map Src.getImportName imports
870− mvar <- newMVar Map.empty
893+ mvar <- newMVar Map.empty
871− crawlDeps env mvar deps ()
894+ crawlDeps env mvar deps ()
872
895
873− statuses <- traverse readMVar =<< readMVar mvar
896+ statuses <- traverse readMVar =<< readMVar mvar
874− midpoint <- checkMidpoint dmvar statuses
897+ midpoint <- checkMidpoint dmvar statuses
875
898
876− case midpoint of
899+ case midpoint of
877− Left problem ->
900+ Left problem ->
878− return $ Left $ Exit.ReplProjectProblem problem
901+ return $ Left $ Exit.ReplProjectProblem problem
879
902
880− Right foreigns ->
903+ Right foreigns ->
881− do rmvar <- newEmptyMVar
904+ do rmvar <- newEmptyMVar
882− resultMVars <- forkWithKey (checkModule env foreigns rmvar) statuses
905+ resultMVars <- forkWithKey (checkModule env foreigns rmvar) statuses
883− putMVar rmvar resultMVars
906+ putMVar rmvar resultMVars
884− results <- traverse readMVar resultMVars
907+ results <- traverse readMVar resultMVars
885− writeDetails root details results
908+ writeDetails root details results
886− depsStatus <- checkDeps root resultMVars deps 0
909+ depsStatus <- checkDeps root resultMVars deps 0
887− finalizeReplArtifacts env source modul depsStatus resultMVars results
910+ finalizeReplArtifacts env source modul depsStatus resultMVars results
888
911
889
912
890finalizeReplArtifacts :: Env -> B.ByteString -> Src.Module -> DepsStatus -> ResultDict -> Map.Map ModuleName.Raw Result -> IO (Either Exit.Repl ReplArtifacts)
913finalizeReplArtifacts :: Env -> B.ByteString -> Src.Module -> DepsStatus -> ResultDict -> Map.Map ModuleName.Raw Result -> IO (Either Exit.Repl ReplArtifacts)
@@ -997,45 +1020,39 @@ findLoc (Env _ root _ srcDirs _ _ _) path absolutePath =
997 return $ Left $ Exit.BP_WithBadExtension path
1020 return $ Left $ Exit.BP_WithBadExtension path
998 else
1021 else
999 let
1022 let
1000− roots = FP.splitDirectories root
1001− segments = FP.splitDirectories dirs ++ [final]
1023+ absoluteSegments = FP.splitDirectories dirs ++ [final]
1002 in
1024 in
1003− case dropPrefix roots segments of
1025+ case Maybe.mapMaybe (isInsideSrcDirByPath absoluteSegments) srcDirs of
1004− Nothing ->
1026+ [] ->
1005 return $ Right $ Location absolutePath path (LOutside path)
1027 return $ Right $ Location absolutePath path (LOutside path)
1006
1028
1007− Just relativeSegments ->
1008− case Maybe.mapMaybe (isInsideSrcDirByPath relativeSegments) srcDirs of
1009− [] ->
1010− return $ Right $ Location absolutePath path (LOutside path)
1011−
1012− [(_, Right names)] ->
1029+ [(_, Right names)] ->
1013− do let name = Name.fromChars (List.intercalate "." names)
1030+ do let name = Name.fromChars (List.intercalate "." names)
1014− matchingDirs <- filterM (isInsideSrcDirByName root names) srcDirs
1031+ matchingDirs <- filterM (isInsideSrcDirByName names) srcDirs
1015− case matchingDirs of
1032+ case matchingDirs of
1016− d1:d2:_ ->
1033+ d1:d2:_ ->
1017− do let p1 = d1 </> FP.joinPath names <.> "elm"
1034+ do let p1 = addRelative d1 (FP.joinPath names <.> "elm")
1018− let p2 = d2 </> FP.joinPath names <.> "elm"
1035+ let p2 = addRelative d2 (FP.joinPath names <.> "elm")
1019− return $ Left $ Exit.BP_MainNameDuplicate name p1 p2
1036+ return $ Left $ Exit.BP_MainNameDuplicate name p1 p2
1020
1037
1021− _ ->
1038+ _ ->
1022− return $ Right $ Location absolutePath path (LInside name)
1039+ return $ Right $ Location absolutePath path (LInside name)
1023
1040
1024− [(s, Left names)] ->
1041+ [(s, Left names)] ->
1025− return $ Left $ Exit.BP_MainNameInvalid path s names
1042+ return $ Left $ Exit.BP_MainNameInvalid path s names
1026
1043
1027− (s1,_):(s2,_):_ ->
1044+ (s1,_):(s2,_):_ ->
1028− return $ Left $ Exit.BP_WithAmbiguousSrcDir path s1 s2
1045+ return $ Left $ Exit.BP_WithAmbiguousSrcDir path s1 s2
1029
1046
1030
1047
1031
1048
1032−isInsideSrcDirByName :: FilePath -> [String] -> FilePath -> IO Bool
1049+isInsideSrcDirByName :: [String] -> AbsoluteSrcDir -> IO Bool
1033−isInsideSrcDirByName root names srcDir =
1050+isInsideSrcDirByName names srcDir =
1034− File.exists (root </> srcDir </> FP.joinPath names <.> "elm")
1051+ File.exists (addRelative srcDir (FP.joinPath names <.> "elm"))
1035
1052
1036
1053
1037−isInsideSrcDirByPath :: [String] -> FilePath -> Maybe (FilePath, Either [String] [String])
1054+isInsideSrcDirByPath :: [String] -> AbsoluteSrcDir -> Maybe (FilePath, Either [String] [String])
1038−isInsideSrcDirByPath segments srcDir =
1055+isInsideSrcDirByPath segments (AbsoluteSrcDir srcDir) =
1039 case dropPrefix (FP.splitDirectories srcDir) segments of
1056 case dropPrefix (FP.splitDirectories srcDir) segments of
1040 Nothing ->
1057 Nothing ->
1041 Nothing
1058 Nothing
@@ -1056,20 +1073,18 @@ isGoodName name =
1056 Char.isUpper char && all (\c -> Char.isAlphaNum c || c == '_') chars
1073 Char.isUpper char && all (\c -> Char.isAlphaNum c || c == '_') chars
1057
1074
1058
1075
1076+-- INVARIANT: Dir.canonicalizePath has been run on both inputs
1077+--
1059dropPrefix :: [FilePath] -> [FilePath] -> Maybe [FilePath]
1078dropPrefix :: [FilePath] -> [FilePath] -> Maybe [FilePath]
1060dropPrefix roots paths =
1079dropPrefix roots paths =
1061 case roots of
1080 case roots of
1062 [] ->
1081 [] ->
1063 Just paths
1082 Just paths
1064
1083
1065− ".":rs ->
1066− dropPrefix rs paths
1067−
1068 r:rs ->
1084 r:rs ->
1069 case paths of
1085 case paths of
1070− [] -> Nothing
1086+ [] -> Nothing
1071− ".":ps -> dropPrefix roots ps
1072− p:ps -> if r == p then dropPrefix rs ps else Nothing
1087+ p:ps -> if r == p then dropPrefix rs ps else Nothing
1073
1088
1074
1089
1075
1090
builder/src/Elm/Details.hs+1−1
@@ -79,7 +79,7 @@ type BuildID = Word64
79
79
80
80
81data ValidOutline
81data ValidOutline
82− = ValidApp (NE.List FilePath)
82+ = ValidApp (NE.List Outline.SrcDir)
83 | ValidPkg Pkg.Name [ModuleName.Raw] (Map.Map Pkg.Name V.Version {- for docs in reactor -})
83 | ValidPkg Pkg.Name [ModuleName.Raw] (Map.Map Pkg.Name V.Version {- for docs in reactor -})
84
84
85
85
builder/src/Elm/Outline.hs+96−12
@@ -5,6 +5,7 @@ module Elm.Outline
5 , AppOutline(..)
5 , AppOutline(..)
6 , PkgOutline(..)
6 , PkgOutline(..)
7 , Exposed(..)
7 , Exposed(..)
8+ , SrcDir(..)
8 , read
9 , read
9 , write
10 , write
10 , encode
11 , encode
@@ -16,11 +17,14 @@ module Elm.Outline
16
17
17
18
18import Prelude hiding (read)
19import Prelude hiding (read)
19−import Control.Monad (filterM)
20+import Control.Monad (filterM, liftM)
21+import Data.Binary (Binary, get, put, getWord8, putWord8)
20import qualified Data.Map as Map
22import qualified Data.Map as Map
21import qualified Data.NonEmptyList as NE
23import qualified Data.NonEmptyList as NE
24+import qualified Data.OneOrMore as OneOrMore
22import Foreign.Ptr (minusPtr)
25import Foreign.Ptr (minusPtr)
23import qualified System.Directory as Dir
26import qualified System.Directory as Dir
27+import qualified System.FilePath as FP
24import System.FilePath ((</>))
28import System.FilePath ((</>))
25
29
26import qualified Elm.Constraint as Con
30import qualified Elm.Constraint as Con
@@ -49,7 +53,7 @@ data Outline
49data AppOutline =
53data AppOutline =
50 AppOutline
54 AppOutline
51 { _app_elm_version :: V.Version
55 { _app_elm_version :: V.Version
52− , _app_source_dirs :: NE.List FilePath
56+ , _app_source_dirs :: NE.List SrcDir
53 , _app_deps_direct :: Map.Map Pkg.Name V.Version
57 , _app_deps_direct :: Map.Map Pkg.Name V.Version
54 , _app_deps_indirect :: Map.Map Pkg.Name V.Version
58 , _app_deps_indirect :: Map.Map Pkg.Name V.Version
55 , _app_test_direct :: Map.Map Pkg.Name V.Version
59 , _app_test_direct :: Map.Map Pkg.Name V.Version
@@ -75,6 +79,11 @@ data Exposed
75 | ExposedDict [(Json.String, [ModuleName.Raw])]
79 | ExposedDict [(Json.String, [ModuleName.Raw])]
76
80
77
81
82+data SrcDir
83+ = AbsoluteSrcDir FilePath
84+ | RelativeSrcDir FilePath
85+
86+
78
87
79-- DEFAULTS
88-- DEFAULTS
80
89
@@ -117,7 +126,7 @@ encode outline =
117 App (AppOutline elm srcDirs depsDirect depsTrans testDirect testTrans) ->
126 App (AppOutline elm srcDirs depsDirect depsTrans testDirect testTrans) ->
118 E.object
127 E.object
119 [ "type" ==> E.chars "application"
128 [ "type" ==> E.chars "application"
120− , "source-directories" ==> E.list E.chars (NE.toList srcDirs)
129+ , "source-directories" ==> E.list encodeSrcDir (NE.toList srcDirs)
121 , "elm-version" ==> V.encode elm
130 , "elm-version" ==> V.encode elm
122 , "dependencies" ==>
131 , "dependencies" ==>
123 E.object
132 E.object
@@ -165,6 +174,13 @@ encodeDeps encodeValue deps =
165 E.dict Pkg.toJsonString encodeValue deps
174 E.dict Pkg.toJsonString encodeValue deps
166
175
167
176
177+encodeSrcDir :: SrcDir -> E.Value
178+encodeSrcDir srcDir =
179+ case srcDir of
180+ AbsoluteSrcDir dir -> E.chars dir
181+ RelativeSrcDir dir -> E.chars dir
182+
183+
168
184
169-- PARSE AND VERIFY
185-- PARSE AND VERIFY
170
186
@@ -192,15 +208,58 @@ read root =
192 return $ Left Exit.OutlineNoAppJson
208 return $ Left Exit.OutlineNoAppJson
193
209
194 | otherwise ->
210 | otherwise ->
195− do badDirs <- filterM (isBadSrcDir root) (NE.toList srcDirs)
211+ do badDirs <- filterM (isSrcDirMissing root) (NE.toList srcDirs)
196− case badDirs of
212+ case map toGiven badDirs of
213+ d:ds ->
214+ return $ Left (Exit.OutlineHasMissingSrcDirs d ds)
215+
216+ [] ->
217+ do maybeDups <- detectDuplicates root (NE.toList srcDirs)
218+ case maybeDups of
219+ Nothing ->
197− [] -> return $ Right outline
220+ return $ Right outline
198− d:ds -> return $ Left (Exit.OutlineHasBadSrcDirs d ds)
221+
222+ Just (canonicalDir, (dir1,dir2)) ->
223+ return $ Left (Exit.OutlineHasDuplicateSrcDirs canonicalDir dir1 dir2)
224+
225+
226+isSrcDirMissing :: FilePath -> SrcDir -> IO Bool
227+isSrcDirMissing root srcDir =
228+ not <$> Dir.doesDirectoryExist (toAbsolute root srcDir)
229+
230+
231+toGiven :: SrcDir -> FilePath
232+toGiven srcDir =
233+ case srcDir of
234+ AbsoluteSrcDir dir -> dir
235+ RelativeSrcDir dir -> dir
236+
237+
238+toAbsolute :: FilePath -> SrcDir -> FilePath
239+toAbsolute root srcDir =
240+ case srcDir of
241+ AbsoluteSrcDir dir -> dir
242+ RelativeSrcDir dir -> root </> dir
199
243
200
244
201−isBadSrcDir :: FilePath -> FilePath -> IO Bool
245+detectDuplicates :: FilePath -> [SrcDir] -> IO (Maybe (FilePath, (FilePath, FilePath)))
202−isBadSrcDir root dir =
246+detectDuplicates root srcDirs =
203− not <$> Dir.doesDirectoryExist (root </> dir)
247+ do pairs <- traverse (toPair root) srcDirs
248+ return $ Map.lookupMin $ Map.mapMaybe isDup $
249+ Map.fromListWith OneOrMore.more pairs
250+
251+
252+toPair :: FilePath -> SrcDir -> IO (FilePath, OneOrMore.OneOrMore FilePath)
253+toPair root srcDir =
254+ do key <- Dir.canonicalizePath (toAbsolute root srcDir)
255+ return (key, OneOrMore.one (toGiven srcDir))
256+
257+
258+isDup :: OneOrMore.OneOrMore FilePath -> Maybe (FilePath, FilePath)
259+isDup paths =
260+ case paths of
261+ OneOrMore.One _ -> Nothing
262+ OneOrMore.More a b -> Just (OneOrMore.getFirstTwo a b)
204
263
205
264
206
265
@@ -278,9 +337,16 @@ depsDecoder valueDecoder =
278 D.dict (Pkg.keyDecoder Exit.OP_BadDependencyName) valueDecoder
337 D.dict (Pkg.keyDecoder Exit.OP_BadDependencyName) valueDecoder
279
338
280
339
281−dirsDecoder :: Decoder (NE.List FilePath)
340+dirsDecoder :: Decoder (NE.List SrcDir)
282dirsDecoder =
341dirsDecoder =
283− fmap Json.toChars <$> D.nonEmptyList D.string Exit.OP_NoSrcDirs
342+ fmap (toSrcDir . Json.toChars) <$> D.nonEmptyList D.string Exit.OP_NoSrcDirs
343+
344+
345+toSrcDir :: FilePath -> SrcDir
346+toSrcDir path =
347+ if FP.isRelative path
348+ then RelativeSrcDir path
349+ else AbsoluteSrcDir path
284
350
285
351
286
352
@@ -321,3 +387,21 @@ boundParser bound tooLong =
321 if len < bound
387 if len < bound
322 then cok (Json.fromPtr pos end) (P.State src end end indent row newCol)
388 then cok (Json.fromPtr pos end) (P.State src end end indent row newCol)
323 else cerr row newCol (\_ _ -> tooLong)
389 else cerr row newCol (\_ _ -> tooLong)
390+
391+
392+
393+-- BINARY
394+
395+
396+instance Binary SrcDir where
397+ put outline =
398+ case outline of
399+ AbsoluteSrcDir a -> putWord8 0 >> put a
400+ RelativeSrcDir a -> putWord8 1 >> put a
401+
402+ get =
403+ do n <- getWord8
404+ case n of
405+ 0 -> liftM AbsoluteSrcDir get
406+ 1 -> liftM RelativeSrcDir get
407+ _ -> fail "binary encoding of SrcDir was corrupted"
builder/src/Reporting/Exit.hs+26−4
@@ -948,7 +948,8 @@ toSolverReport problem =
948
948
949data Outline
949data Outline
950 = OutlineHasBadStructure (Decode.Error OutlineProblem)
950 = OutlineHasBadStructure (Decode.Error OutlineProblem)
951− | OutlineHasBadSrcDirs FilePath [FilePath]
951+ | OutlineHasMissingSrcDirs FilePath [FilePath]
952+ | OutlineHasDuplicateSrcDirs FilePath FilePath FilePath
952 | OutlineNoPkgCore
953 | OutlineNoPkgCore
953 | OutlineNoAppCore
954 | OutlineNoAppCore
954 | OutlineNoAppJson
955 | OutlineNoAppJson
@@ -974,12 +975,12 @@ toOutlineReport problem =
974 Json.toReport "elm.json" (Json.FailureToReport toOutlineProblemReport) decodeError $
975 Json.toReport "elm.json" (Json.FailureToReport toOutlineProblemReport) decodeError $
975 Json.ExplicitReason "I ran into a problem with your elm.json file."
976 Json.ExplicitReason "I ran into a problem with your elm.json file."
976
977
977− OutlineHasBadSrcDirs dir dirs ->
978+ OutlineHasMissingSrcDirs dir dirs ->
978 case dirs of
979 case dirs of
979 [] ->
980 [] ->
980 Help.report "MISSING SOURCE DIRECTORY" (Just "elm.json")
981 Help.report "MISSING SOURCE DIRECTORY" (Just "elm.json")
981 "I need a valid elm.json file, but the \"source-directories\" field lists the following directory:"
982 "I need a valid elm.json file, but the \"source-directories\" field lists the following directory:"
982− [ D.indent 4 $ D.dullyellow $ D.fromChars dir
983+ [ D.indent 4 $ D.red $ D.fromChars dir
983 , D.reflow $
984 , D.reflow $
984 "I cannot find it though. Is it missing? Is there a typo?"
985 "I cannot find it though. Is it missing? Is there a typo?"
985 ]
986 ]
@@ -988,11 +989,32 @@ toOutlineReport problem =
988 Help.report "MISSING SOURCE DIRECTORIES" (Just "elm.json")
989 Help.report "MISSING SOURCE DIRECTORIES" (Just "elm.json")
989 "I need a valid elm.json file, but the \"source-directories\" field lists the following directories:"
990 "I need a valid elm.json file, but the \"source-directories\" field lists the following directories:"
990 [ D.indent 4 $ D.vcat $
991 [ D.indent 4 $ D.vcat $
991− map (D.dullyellow . D.fromChars) (dir:dirs)
992+ map (D.red . D.fromChars) (dir:dirs)
992 , D.reflow $
993 , D.reflow $
993 "I cannot find them though. Are they missing? Are there typos?"
994 "I cannot find them though. Are they missing? Are there typos?"
994 ]
995 ]
995
996
997+ OutlineHasDuplicateSrcDirs canonicalDir dir1 dir2 ->
998+ if dir1 == dir2 then
999+ Help.report "REDUNDANT SOURCE DIRECTORIES" (Just "elm.json")
1000+ "I need a valid elm.json file, but the \"source-directories\" field lists the same directory twice:"
1001+ [ D.indent 4 $ D.vcat $
1002+ map (D.red . D.fromChars) [dir1,dir2]
1003+ , D.reflow $
1004+ "Remove one of the entries!"
1005+ ]
1006+ else
1007+ Help.report "REDUNDANT SOURCE DIRECTORIES" (Just "elm.json")
1008+ "I need a valid elm.json file, but the \"source-directories\" field has some redundant directories:"
1009+ [ D.indent 4 $ D.vcat $
1010+ map (D.red . D.fromChars) [dir1,dir2]
1011+ , D.reflow $
1012+ "These are two different ways of refering to the same directory:"
1013+ , D.indent 4 $ D.dullyellow $ D.fromChars canonicalDir
1014+ , D.reflow $
1015+ "Remove one of the redundant entries from your \"source-directories\" field."
1016+ ]
1017+
996 OutlineNoPkgCore ->
1018 OutlineNoPkgCore ->
997 Help.report "MISSING DEPENDENCY" (Just "elm.json")
1019 Help.report "MISSING DEPENDENCY" (Just "elm.json")
998 "I need to see an \"elm/core\" dependency your elm.json file. The default imports\
1020 "I need to see an \"elm/core\" dependency your elm.json file. The default imports\
terminal/src/Init.hs+1−1
@@ -90,7 +90,7 @@ init =
90 in
90 in
91 do Dir.createDirectoryIfMissing True "src"
91 do Dir.createDirectoryIfMissing True "src"
92 Outline.write "." $ Outline.App $
92 Outline.write "." $ Outline.App $
93− Outline.AppOutline V.compiler (NE.List "src" []) directs indirects Map.empty Map.empty
93+ Outline.AppOutline V.compiler (NE.List (Outline.RelativeSrcDir "src") []) directs indirects Map.empty Map.empty
94 putStrLn "Okay, I created it. Now read that link!"
94 putStrLn "Okay, I created it. Now read that link!"
95 return (Right ())
95 return (Right ())
96
96