@@ -22,21 +22,17 @@ module Elm.Project.Json
23import Prelude hiding (read)
23import Prelude hiding (read)
24import Control.Monad.Trans (liftIO)
24import Control.Monad.Trans (liftIO)
25−import qualified Data.ByteString as BS
26import Data.Foldable (traverse_)
25import Data.Foldable (traverse_)
28−import Data.Text (Text)
29import qualified Data.Map as Map
26import qualified Data.Map as Map
30−import qualified Data.Text as Text
27+import qualified Data.Utf8 as Utf8
31import qualified System.Directory as Dir
28import qualified System.Directory as Dir
32import System.FilePath ((</>))
29import System.FilePath ((</>))
31+import qualified Elm.Constraint as Con
32+import qualified Elm.Licenses as Licenses
34import qualified Elm.ModuleName as ModuleName
33import qualified Elm.ModuleName as ModuleName
35import qualified Elm.Package as Pkg
34import qualified Elm.Package as Pkg
36−import Elm.Package (Name, Version)
35+import qualified Elm.Version as V
38−import qualified Elm.Project.Constraint as Con
39−import qualified Elm.Project.Licenses as Licenses
40import qualified Json.Decode as D
36import qualified Json.Decode as D
41import qualified Json.Encode as E
37import qualified Json.Encode as E
42import qualified Reporting.Exit as Exit
38import qualified Reporting.Exit as Exit
@@ -59,12 +55,12 @@ data Project
60data AppInfo =
56data AppInfo =
62− { _app_elm_version :: Version
58+ { _app_elm_version :: V.Version
63 , _app_source_dirs :: [FilePath]
59 , _app_source_dirs :: [FilePath]
64− , _app_deps_direct :: Map Name Version
60+ , _app_deps_direct :: Map.Map Pkg.Name V.Version
65− , _app_deps_trans :: Map Name Version
61+ , _app_deps_trans :: Map.Map Pkg.Name V.Version
66− , _app_test_direct :: Map Name Version
62+ , _app_test_direct :: Map.Map Pkg.Name V.Version
67− , _app_test_trans :: Map Name Version
63+ , _app_test_trans :: Map.Map Pkg.Name V.Version
@@ -74,27 +70,27 @@ data AppInfo =
75data PkgInfo =
71data PkgInfo =
77− { _pkg_name :: Name
73+ { _pkg_name :: Pkg.Name
78− , _pkg_summary :: Text
74+ , _pkg_summary :: Utf8.String
79 , _pkg_license :: Licenses.License
75 , _pkg_license :: Licenses.License
80− , _pkg_version :: Version
76+ , _pkg_version :: V.Version
81 , _pkg_exposed :: Exposed
77 , _pkg_exposed :: Exposed
82− , _pkg_deps :: Map Name Con.Constraint
78+ , _pkg_deps :: Map.Map Pkg.Name Con.Constraint
83− , _pkg_test_deps :: Map Name Con.Constraint
79+ , _pkg_test_deps :: Map.Map Pkg.Name Con.Constraint
84 , _pkg_elm_version :: Con.Constraint
80 , _pkg_elm_version :: Con.Constraint
88data Exposed
84data Exposed
89 = ExposedList [ModuleName.Raw]
85 = ExposedList [ModuleName.Raw]
90− | ExposedDict [(Text, [ModuleName.Raw])]
86+ | ExposedDict [(Utf8.String, [ModuleName.Raw])]
94-- DEFAULTS
90-- DEFAULTS
97−defaultSummary :: Text
93+defaultSummary :: Utf8.String
98defaultSummary =
94defaultSummary =
99 "helpful summary of your project, less than 80 characters"
95 "helpful summary of your project, less than 80 characters"
@@ -117,7 +113,7 @@ isPlatformPackage project =
117 author == "elm" || author == "elm-explorations"
113 author == "elm" || author == "elm-explorations"
120−getName :: Project -> Name
116+getName :: Project -> Pkg.Name
121getName project =
117getName project =
122 case project of
118 case project of
@@ -174,32 +170,32 @@ encode project =
174 case project of
170 case project of
175 App (AppInfo elm srcDirs depsDirect depsTrans testDirect testTrans) ->
171 App (AppInfo elm srcDirs depsDirect depsTrans testDirect testTrans) ->
177− [ "type" ==> E.text "application"
173+ [ "type" ==> E.string "application"
178− , "source-directories" ==> E.list (E.text . Text.pack) srcDirs
174+ , "source-directories" ==> E.list (E.string . Utf8.fromChars) srcDirs
179− , "elm-version" ==> encodeVersion elm
175+ , "elm-version" ==> V.encode elm
180 , "dependencies" ==>
176 , "dependencies" ==>
182− [ "direct" ==> encodeDeps encodeVersion depsDirect
178+ [ "direct" ==> encodeDeps V.encode depsDirect
183− , "indirect" ==> encodeDeps encodeVersion depsTrans
179+ , "indirect" ==> encodeDeps V.encode depsTrans
185 , "test-dependencies" ==>
181 , "test-dependencies" ==>
187− [ "direct" ==> encodeDeps encodeVersion testDirect
183+ [ "direct" ==> encodeDeps V.encode testDirect
188− , "indirect" ==> encodeDeps encodeVersion testTrans
184+ , "indirect" ==> encodeDeps V.encode testTrans
192 Pkg (PkgInfo name summary license version exposed deps tests elm) ->
188 Pkg (PkgInfo name summary license version exposed deps tests elm) ->
194− [ "type" ==> E.text "package"
190+ [ "type" ==> E.string "package"
195− , "name" ==> E.text (Pkg.toText name)
191+ , "name" ==> E.string (Pkg.toString name)
196− , "summary" ==> E.text summary
192+ , "summary" ==> E.string summary
197 , "license" ==> Licenses.encode license
193 , "license" ==> Licenses.encode license
198− , "version" ==> E.text (Pkg.versionToText version)
194+ , "version" ==> V.encode version
199 , "exposed-modules" ==> encodeExposed exposed
195 , "exposed-modules" ==> encodeExposed exposed
200− , "elm-version" ==> encodeConstraint elm
196+ , "elm-version" ==> Con.encode elm
201− , "dependencies" ==> encodeDeps encodeConstraint deps
197+ , "dependencies" ==> encodeDeps Con.encode deps
202− , "test-dependencies" ==> encodeDeps encodeConstraint tests
198+ , "test-dependencies" ==> encodeDeps Con.encode tests
@@ -223,19 +219,9 @@ encodeModule name =
223 E.name name
219 E.name name
226−encodeDeps :: (a -> E.Value) -> Map Pkg.Name a -> E.Value
222+encodeDeps :: (a -> E.Value) -> Map.Map Pkg.Name a -> E.Value
227encodeDeps encodeValue deps =
223encodeDeps encodeValue deps =
228− E.dict Pkg.toText encodeValue deps
224+ E.dict Pkg.toString encodeValue deps
231−encodeConstraint :: Con.Constraint -> E.Value
232−encodeConstraint constraint =
233− E.text (Con.toText constraint)
236−encodeVersion :: Pkg.Version -> E.Value
237−encodeVersion version =
238− E.text (Pkg.versionToText version)
@@ -244,17 +230,19 @@ encodeVersion version =
245read :: FilePath -> Task.Task Project
231read :: FilePath -> Task.Task Project
246read path =
232read path =
247− do bytes <- liftIO $ BS.readFile path
233+ do result <- liftIO $ D.fromFile decoder path
248− case D.parse "project" E.badContentToDocs decoder bytes of
234+ case result of
249− Left err ->
235+ Right project ->
250− throwBadJson (E.BadJson err)
236+ case project of
252− Right project@(Pkg _) ->
240+ App (AppInfo _ srcDirs _ _ _ _) ->
241+ do mapM_ doesDirectoryExist srcDirs
253− return project
242+ return project
255− Right project@(App (AppInfo _ srcDirs _ _ _ _)) ->
244+ Left err ->
256− do mapM_ doesDirectoryExist srcDirs
245+ throwBadJson (error "TODO bad json" err)
260throwBadJson :: E.ElmJsonProblem -> Task.Task a
248throwBadJson :: E.ElmJsonProblem -> Task.Task a
@@ -280,16 +268,16 @@ type Decoder a =
281decoder :: Decoder Project
269decoder :: Decoder Project
283− do tipe <- D.field "type" D.text
271+ do tipe <- D.field "type" D.string
284 case tipe of
272 case tipe of
285 "application" ->
273 "application" ->
286− D.map App appDecoder
274+ App <$> appDecoder
288 "package" ->
276 "package" ->
289− D.map Pkg pkgDecoder
277+ Pkg <$> pkgDecoder
292− D.fail (E.BadType other)
280+ D.failure (E.BadType other)
295appDecoder :: Decoder AppInfo
283appDecoder :: Decoder AppInfo
@@ -325,73 +313,49 @@ pkgNameDecoder =
325 D.mapError E.BadPkgName Pkg.decoder
313 D.mapError E.BadPkgName Pkg.decoder
328−summaryDecoder :: Decoder Text
316+summaryDecoder :: Decoder Utf8.String
329summaryDecoder =
317summaryDecoder =
330− do summary <- D.text
318+ do summary <- D.string
331− if Text.length summary < 80
319+ if Utf8.size summary < 80
332− then D.succeed summary
320+ then return summary
333− else D.fail E.BadSummaryTooLong
321+ else D.failure E.BadSummaryTooLong
336licenseDecoder :: Decoder Licenses.License
324licenseDecoder :: Decoder Licenses.License
337licenseDecoder =
325licenseDecoder =
338− do txt <- D.text
326+ Licenses.decoder E.BadLicense
339− case Licenses.check txt of
341− D.fail (E.BadLicense txt suggestions)
347−versionDecoder :: Decoder Version
329+versionDecoder :: Decoder V.Version
348versionDecoder =
330versionDecoder =
350− case Pkg.versionFromText txt of
355− D.fail (E.BadVersion txt)
331+ D.mapError E.BadVersion V.decoder
358constraintDecoder :: Decoder Con.Constraint
334constraintDecoder :: Decoder Con.Constraint
359constraintDecoder =
335constraintDecoder =
360− do txt <- D.text
336+ D.mapError E.BadConstraint Con.decoder
361− case Con.fromText txt of
363− D.succeed constraint
366− D.fail (E.BadConstraint msg)
369−depsDecoder :: Decoder a -> Decoder (Map Name a)
339+depsDecoder :: Decoder a -> Decoder (Map.Map Pkg.Name a)
370depsDecoder valueDecoder =
340depsDecoder valueDecoder =
371 Map.fromList <$> (
341 Map.fromList <$> (
372 traverse validateKey =<< D.pairs valueDecoder
342 traverse validateKey =<< D.pairs valueDecoder
376−validateKey :: (Text, a) -> Decoder (Name, a)
346+validateKey :: (Utf8.String, a) -> Decoder (Pkg.Name, a)
377validateKey (key, value) =
347validateKey (key, value) =
378− case Pkg.fromText key of
348+ case Pkg.fromString key of
379 Right name ->
349 Right name ->
380− D.succeed (name, value)
350+ return (name, value)
382 Left _ ->
352 Left _ ->
383− D.fail (E.BadDependencyName key)
353+ D.failure (E.BadDependencyName key)
386dirDecoder :: Decoder FilePath
356dirDecoder :: Decoder FilePath
387dirDecoder =
357dirDecoder =
388− do maybeText <- D.maybe D.text
358+ Utf8.toChars <$> D.string
391− D.fail E.BadDirectoryNotString
394− D.succeed (Text.unpack txt)
@@ -413,9 +377,9 @@ moduleDecoder =
413 D.mapError E.BadModuleName ModuleName.decoder
377 D.mapError E.BadModuleName ModuleName.decoder
416−checkHeader :: Text -> Decoder ()
380+checkHeader :: Utf8.String -> Decoder ()
417checkHeader header =
381checkHeader header =
418− if Text.length header < 20 then
382+ if Utf8.size header < 20 then
419− D.succeed ()
383+ return ()
421− D.fail (E.BadModuleHeaderTooLong header)
385+ D.failure (E.BadModuleHeaderTooLong header)