on master help sign in
Merge pull request #1032 from JoeyEremondi/commonPackageFile
803e56bEvan Czaplicki
elm-compiler.cabal+6
@@ -43,6 +43,7 @@ Library
43 Elm.Compiler.Module,
43 Elm.Compiler.Module,
44 Elm.Compiler.Type,
44 Elm.Compiler.Type,
45 Elm.Docs,
45 Elm.Docs,
46+ Elm.Package,
46 Elm.Utils
47 Elm.Utils
47
48
48 other-modules:
49 other-modules:
@@ -165,7 +166,12 @@ Executable elm
165
166
166 Build-depends:
167 Build-depends:
167 base >=4.2 && <5,
168 base >=4.2 && <5,
169+ aeson >= 0.7 && < 0.9,
170+ binary >= 0.7.0.0 && < 0.8,
168 directory >= 1.0 && < 2.0,
171 directory >= 1.0 && < 2.0,
172+ filepath >= 1 && < 2.0,
173+ mtl >= 2.2 && < 3,
174+ text >= 1 && < 2,
169 elm-compiler,
175 elm-compiler,
170 process
176 process
171
177
src/AST/Module.hs+2−1
@@ -21,6 +21,7 @@ import qualified AST.Expression.Optimized as Optimized
21import qualified AST.Type as Type
21import qualified AST.Type as Type
22import qualified AST.Variable as Var
22import qualified AST.Variable as Var
23import qualified Docs.AST as Docs
23import qualified Docs.AST as Docs
24+import qualified Elm.Package as Package
24import qualified Elm.Compiler.Version as Compiler
25import qualified Elm.Compiler.Version as Compiler
25import qualified Reporting.Annotation as A
26import qualified Reporting.Annotation as A
26
27
@@ -142,7 +143,7 @@ toInterface :: CanonicalModule -> Interface
142toInterface modul =
143toInterface modul =
143 let body' = body modul in
144 let body' = body modul in
144 Interface
145 Interface
145− { iVersion = Compiler.version
146+ { iVersion = Package.versionToString Compiler.version
146 , iExports = exports modul
147 , iExports = exports modul
147 , iTypes = types body'
148 , iTypes = types body'
148 , iImports = imports modul
149 , iImports = imports modul
src/CommandLineRouter.hs+2−2
@@ -7,7 +7,7 @@ import System.IO (hPutStrLn, stderr, stdin, stdout)
7import qualified System.Process as Proc
7import qualified System.Process as Proc
8
8
9import qualified Elm.Compiler.Version as Compiler
9import qualified Elm.Compiler.Version as Compiler
10−
10+import qualified Elm.Package as Pkg
11
11
12main :: IO ()
12main :: IO ()
13main =
13main =
@@ -47,7 +47,7 @@ attemptToRun command args =
47
47
48usageMessage :: String
48usageMessage :: String
49usageMessage =
49usageMessage =
50− "Elm Platform " ++ Compiler.version ++ " - a way to run all Elm tools\n\
50+ "Elm Platform " ++ (Pkg.versionToString Compiler.version) ++ " - a way to run all Elm tools\n\
51 \\n\
51 \\n\
52 \Usage: elm <command> [<args>]\n\
52 \Usage: elm <command> [<args>]\n\
53 \\n\
53 \\n\
src/Compile.hs+4−4
@@ -5,6 +5,7 @@ import qualified Data.Map as Map
5import qualified AST.Module as Module
5import qualified AST.Module as Module
6import qualified Canonicalize
6import qualified Canonicalize
7import Elm.Utils ((|>))
7import Elm.Utils ((|>))
8+import qualified Elm.Package as Package
8import qualified Nitpick.PatternMatches as Nitpick
9import qualified Nitpick.PatternMatches as Nitpick
9import qualified Nitpick.TopLevelTypes as Nitpick
10import qualified Nitpick.TopLevelTypes as Nitpick
10import qualified Parse.Helpers as Parse
11import qualified Parse.Helpers as Parse
@@ -16,19 +17,18 @@ import qualified Type.Inference as TI
16
17
17
18
18compile
19compile
19− :: String
20+ :: Package.Name
20− -> String
21 -> Bool
21 -> Bool
22 -> Module.Interfaces
22 -> Module.Interfaces
23 -> String
23 -> String
24 -> Result.Result Warning.Warning Error.Error Module.CanonicalModule
24 -> Result.Result Warning.Warning Error.Error Module.CanonicalModule
25
25
26−compile user projectName isRoot interfaces source =
26+compile packageName isRoot interfaces source =
27 do
27 do
28 -- determine if default imports should be added
28 -- determine if default imports should be added
29 -- only elm-lang/core is exempt
29 -- only elm-lang/core is exempt
30 let needsDefaults =
30 let needsDefaults =
31− not (user == "elm-lang" && projectName == "core")
31+ not (packageName == Package.coreName)
32
32
33 -- Parse the source code
33 -- Parse the source code
34 validModule <-
34 validModule <-
src/Elm/Compiler.hs+8−13
@@ -1,6 +1,6 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2module Elm.Compiler
2module Elm.Compiler
3− ( version, rawVersion
3+ ( version
4 , parseDependencies
4 , parseDependencies
5 , compile, Context(..), Result(..)
5 , compile, Context(..), Result(..)
6 , Dealiaser, dummyDealiaser
6 , Dealiaser, dummyDealiaser
@@ -14,9 +14,10 @@ import qualified Data.Map as Map
14import qualified AST.Module as Module
14import qualified AST.Module as Module
15import qualified Compile
15import qualified Compile
16import qualified Docs.Check as Docs
16import qualified Docs.Check as Docs
17+import qualified Elm.Compiler.Version
17import qualified Elm.Compiler.Module as PublicModule
18import qualified Elm.Compiler.Module as PublicModule
18−import qualified Elm.Compiler.Version as Version
19import qualified Elm.Docs as Docs
19import qualified Elm.Docs as Docs
20+import qualified Elm.Package as Package
20import qualified Generate.JavaScript as JS
21import qualified Generate.JavaScript as JS
21import qualified Optimize
22import qualified Optimize
22import qualified Parse.Module as Parse
23import qualified Parse.Module as Parse
@@ -30,14 +31,9 @@ import qualified Reporting.Warning as Warning
30
31
31-- VERSION
32-- VERSION
32
33
33−version :: String
34+version :: Package.Version
34version =
35version =
35− Version.version
36+ Elm.Compiler.Version.version
36−
37−
38−rawVersion :: [Int]
39−rawVersion =
40− Version.rawVersion
41
37
42
38
43-- DEPENDENCIES
39-- DEPENDENCIES
@@ -72,14 +68,14 @@ compile
72
68
73compile context source interfaces =
69compile context source interfaces =
74 let
70 let
75− (Context user packageName isRoot isExposed) =
71+ (Context packageName isRoot isExposed) =
76 context
72 context
77
73
78 unwrappedInterfaces =
74 unwrappedInterfaces =
79 Map.mapKeysMonotonic (\(PublicModule.Name name) -> name) interfaces
75 Map.mapKeysMonotonic (\(PublicModule.Name name) -> name) interfaces
80
76
81 (Result.Result (dealiaser, warnings) rawResult) =
77 (Result.Result (dealiaser, warnings) rawResult) =
82− do modul <- Compile.compile user packageName isRoot unwrappedInterfaces source
78+ do modul <- Compile.compile packageName isRoot unwrappedInterfaces source
83 docs <- docsGen isExposed modul
79 docs <- docsGen isExposed modul
84
80
85 let interface = Module.toInterface modul
81 let interface = Module.toInterface modul
@@ -95,8 +91,7 @@ compile context source interfaces =
95
91
96
92
97data Context = Context
93data Context = Context
98− { _user :: String
99− , _packageName :: String
94+ { _packageName :: Package.Name
100 , _isRoot :: Bool
95 , _isRoot :: Bool
101 , _isExposed :: Bool
96 , _isExposed :: Bool
102 }
97 }
src/Elm/Compiler/Version.hs+17−6
@@ -1,15 +1,26 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2−module Elm.Compiler.Version (version, rawVersion) where
2+module Elm.Compiler.Version (version) where
3
3
4import qualified Data.Version as Version
4import qualified Data.Version as Version
5import qualified Paths_elm_compiler as This
5import qualified Paths_elm_compiler as This
6+import Elm.Package
6
7
7
8
9+rawVersion :: [Int]
10+rawVersion =
11+ Version.versionBranch This.version
12+
8−version :: String
13+version :: Version
9version =
14version =
10− Version.showVersion This.version
15+ case rawVersion of
16+ major : minor : patch : _ ->
17+ Version major minor patch
11
18
19+ [major, minor] ->
20+ Version major minor 0
12
21
13−rawVersion :: [Int]
22+ [major] ->
14−rawVersion =
23+ Version major 0 0
15− Version.versionBranch This.version
24+
25+ [] ->
26+ error "could not detect version of elm-compiler you are using"
src/Elm/Docs.hs+2−1
@@ -14,6 +14,7 @@ import qualified Docs.AST as Docs
14import qualified Elm.Compiler.Module as Module
14import qualified Elm.Compiler.Module as Module
15import qualified Elm.Compiler.Type as Type
15import qualified Elm.Compiler.Type as Type
16import qualified Elm.Compiler.Version as Version
16import qualified Elm.Compiler.Version as Version
17+import qualified Elm.Package as Pkg
17import qualified Reporting.Annotation as A
18import qualified Reporting.Annotation as A
18
19
19
20
@@ -75,7 +76,7 @@ fromCheckedDocs name (Docs.Docs comment aliases unions values) =
75 (map toAlias (Map.toList aliases))
76 (map toAlias (Map.toList aliases))
76 (map toUnion (Map.toList unions))
77 (map toUnion (Map.toList unions))
77 (map toValue (Map.toList values))
78 (map toValue (Map.toList values))
78− (Version Version.version)
79+ (Version $ (Pkg.versionToString Version.version))
79
80
80
81
81-- PRETTY JSON
82-- PRETTY JSON
src/Elm/Package.hsnew file+187
@@ -0,0 +1,187 @@
1+{-# LANGUAGE FlexibleContexts #-}
2+module Elm.Package where
3+
4+import Control.Applicative ((<$>), (<*>))
5+import Control.Monad.Error.Class (MonadError, throwError)
6+import Data.Aeson
7+import Data.Binary
8+import qualified Data.List as List
9+import qualified Data.Text as T
10+import qualified Data.Maybe as Maybe
11+import System.FilePath ((</>))
12+import Data.Char (isDigit)
13+import Data.Function (on)
14+
15+data Name = Name
16+ { user :: String
17+ , project :: String
18+ }
19+ deriving (Eq, Ord)
20+
21+
22+dummyName :: Name
23+dummyName =
24+ Name "USER" "PROJECT"
25+
26+
27+coreName :: Name
28+coreName =
29+ Name "elm-lang" "core"
30+
31+
32+toString :: Name -> String
33+toString name =
34+ user name ++ "/" ++ project name
35+
36+
37+toUrl :: Name -> String
38+toUrl name =
39+ user name ++ "/" ++ project name
40+
41+
42+toFilePath :: Name -> FilePath
43+toFilePath name =
44+ user name </> project name
45+
46+
47+fromString :: String -> Maybe Name
48+fromString string =
49+ case break (=='/') string of
50+ ( user@(_:_), '/' : project@(_:_) )
51+ | all (/='/') project -> Just (Name user project)
52+ _ -> Nothing
53+
54+
55+fromString' :: (MonadError String m) => String -> m Name
56+fromString' string =
57+ Maybe.maybe (throwError $ errorMsg string) return (fromString string)
58+
59+
60+instance Binary Name where
61+ get = Name <$> get <*> get
62+ put (Name user project) =
63+ do put user
64+ put project
65+
66+
67+instance FromJSON Name where
68+ parseJSON (String text) =
69+ let string = T.unpack text in
70+ Maybe.maybe (fail $ errorMsg string) return (fromString string)
71+
72+ parseJSON _ = fail "Project name must be a string."
73+
74+
75+instance ToJSON Name where
76+ toJSON name =
77+ toJSON (toString name)
78+
79+
80+errorMsg :: String -> String
81+errorMsg string =
82+ unlines
83+ [ "Dependency file has an invalid name: " ++ string
84+ , "Must have format USER/PROJECT and match a public github project."
85+ ]
86+
87+
88+
89+
90+data Version = Version
91+ { major :: Int
92+ , minor :: Int
93+ , patch :: Int
94+ }
95+ deriving (Eq, Ord)
96+
97+
98+initialVersion :: Version
99+initialVersion =
100+ Version 1 0 0
101+
102+dummyVersion :: Version
103+dummyVersion =
104+ Version 0 0 0
105+
106+
107+bumpPatch :: Version -> Version
108+bumpPatch (Version major minor patch) =
109+ Version major minor (patch + 1)
110+
111+bumpMinor :: Version -> Version
112+bumpMinor (Version major minor _patch) =
113+ Version major (minor + 1) 0
114+
115+bumpMajor :: Version -> Version
116+bumpMajor (Version major _minor _patch) =
117+ Version (major + 1) 0 0
118+
119+
120+-- FILTERING
121+
122+filterLatest :: (Ord a) => (Version -> a) -> [Version] -> [Version]
123+filterLatest characteristic versions =
124+ map last (List.groupBy ((==) `on` characteristic) (List.sort versions))
125+
126+
127+majorAndMinor :: Version -> (Int,Int)
128+majorAndMinor (Version major minor _patch) =
129+ (major, minor)
130+
131+
132+-- CONVERSIONS
133+
134+versionToString :: Version -> String
135+versionToString (Version major minor patch) =
136+ show major ++ "." ++ show minor ++ "." ++ show patch
137+
138+
139+versionFromString :: String -> Maybe Version
140+versionFromString string =
141+ case splitNumbers string of
142+ Just [major, minor, patch] ->
143+ Just (Version major minor patch)
144+ _ -> Nothing
145+ where
146+ splitNumbers :: String -> Maybe [Int]
147+ splitNumbers ns =
148+ case span isDigit ns of
149+ ("", _) ->
150+ Nothing
151+
152+ (numbers, []) ->
153+ Just [ read numbers ]
154+
155+ (numbers, '.':rest) ->
156+ (read numbers :) <$> splitNumbers rest
157+
158+ _ -> Nothing
159+
160+
161+instance Binary Version where
162+ get = Version <$> get <*> get <*> get
163+ put (Version major minor patch) =
164+ do put major
165+ put minor
166+ put patch
167+
168+
169+instance FromJSON Version where
170+ parseJSON (String text) =
171+ let string = T.unpack text in
172+ case versionFromString string of
173+ Just v -> return v
174+ Nothing ->
175+ fail $ unlines
176+ [ "Dependency file has an invalid version number: " ++ string
177+ , "Must have format MAJOR.MINOR.PATCH (e.g. 0.1.2)"
178+ ]
179+
180+ parseJSON _ =
181+ fail "Version number must be stored as a string."
182+
183+
184+instance ToJSON Version where
185+ toJSON version =
186+ toJSON (versionToString version)
187+
src/Elm/Utils.hs+4−3
@@ -20,6 +20,7 @@ import System.Process (readProcessWithExitCode)
20import qualified AST.Expression.Source as Source
20import qualified AST.Expression.Source as Source
21import qualified AST.Pattern as Pattern
21import qualified AST.Pattern as Pattern
22import qualified Elm.Compiler.Version as Version
22import qualified Elm.Compiler.Version as Version
23+import qualified Elm.Package as Pkg
23import qualified Parse.Helpers as Parse
24import qualified Parse.Helpers as Parse
24import qualified Parse.Expression as Parse
25import qualified Parse.Expression as Parse
25import qualified Reporting.Annotation as A
26import qualified Reporting.Annotation as A
@@ -127,8 +128,8 @@ errorNotFound name =
127 , ""
128 , ""
128 , " * On Mac it is /usr/local/share/elm"
129 , " * On Mac it is /usr/local/share/elm"
129 , " * On Windows it is one of the following:"
130 , " * On Windows it is one of the following:"
130− , " C:/Program Files/Elm Platform/" ++ Version.version ++ "/share"
131+ , " C:/Program Files/Elm Platform/" ++ (Pkg.versionToString Version.version) ++ "/share"
131− , " C:/Program Files (x86)/Elm Platform/" ++ Version.version ++ "/share"
132+ , " C:/Program Files (x86)/Elm Platform/" ++ (Pkg.versionToString Version.version) ++ "/share"
132 , ""
133 , ""
133 , "If you installed using npm, you have to set ELM_HOME to a certain directory"
134 , "If you installed using npm, you have to set ELM_HOME to a certain directory"
134 , "of the form .../node_modules/elm/share"
135 , "of the form .../node_modules/elm/share"
@@ -147,4 +148,4 @@ isDeclaration string =
147 Just (List.intercalate "$" (Pattern.boundVarList pattern))
148 Just (List.intercalate "$" (Pattern.boundVarList pattern))
148
149
149 _ ->
150 _ ->
150− Nothing
151+ Nothing
tests/Test/Compiler.hs+2−2
@@ -12,7 +12,7 @@ import Test.Framework.Providers.HUnit (testCase)
12import Test.HUnit (Assertion, assertFailure, assertBool)
12import Test.HUnit (Assertion, assertFailure, assertBool)
13
13
14import qualified Elm.Compiler as Compiler
14import qualified Elm.Compiler as Compiler
15−
15+import qualified Elm.Package as Package
16
16
17compilerTests :: Test
17compilerTests :: Test
18compilerTests =
18compilerTests =
@@ -54,7 +54,7 @@ testIf handleResult filePaths =
54 source <- readFile filePath
54 source <- readFile filePath
55
55
56 let context =
56 let context =
57− Compiler.Context "elm-lang" "core" True False
57+ Compiler.Context (Package.Name "elm-lang" "core") True False
58 let (dealiaser, _warnings, result) =
58 let (dealiaser, _warnings, result) =
59 Compiler.compile context source Map.empty
59 Compiler.compile context source Map.empty
60 let formatErrors errors =
60 let formatErrors errors =