1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings, QuasiQuotes #-}
9import Control.Concurrent (readMVar)
10import Control.Monad (liftM2, msum)
11import qualified Data.ByteString as B
12import qualified Data.ByteString.Builder as B
13import qualified Data.ByteString.Lazy as LBS
14import qualified Data.HashSet as HashSet
15import qualified Data.Map as Map
16import qualified Data.Map.Utils as Map
17import qualified Data.Name as N
18import qualified Data.NonEmptyList as NE
19import qualified Data.OneOrMore as OneOrMore
20import Network.URI (parseURI)
22import Snap.Http.Server
23import Snap.Util.CORS (CORSOptions(..), HashableMethod(..), OriginList(Origins), applyCORS, mkOriginSet)
24import Snap.Util.FileUploads
25import qualified System.Directory as Dir
26import qualified System.IO.Streams as Stream
27import Text.RawString.QQ (r)
29import qualified AST.Source as Src
30import qualified AST.Canonical as Can
31import qualified AST.Optimized as Opt
32import qualified BackgroundWriter as BW
34import qualified Compile
35import qualified Elm.Details as Details
36import qualified Elm.Interface as I
37import qualified Elm.ModuleName as ModuleName
38import qualified Elm.Package as Pkg
40import qualified Generate
41import qualified Generate.Html as Html
42import qualified Generate.JavaScript as Generate
43import qualified Generate.Mode as Mode
44import qualified Json.Encode as Encode
45import qualified Parse.Module as Parse
46import qualified Reporting
47import qualified Reporting.Annotation as A
48import qualified Reporting.Error as Error
49import qualified Reporting.Error.Import as Import
50import qualified Reporting.Exit as Exit
51import qualified Reporting.Task as Task
60 do artifacts <- loadArtifacts
61 errorJS <- compileErrorViewer
62 httpServe config $ msum $
63 [ path "compile" $ compile artifacts
64 , path "compile/errors.js" $ writeBS errorJS
69config :: Config Snap a
73 |> setAccessLog ConfigNoLog
74 |> setErrorLog ConfigNoLog
77(|>) :: a -> (a -> b) -> b
88 do modifyResponse $ setResponseStatus 404 "Not Found"
89 modifyResponse $ setContentType "text/html; charset=utf-8"
97compile :: Artifacts -> Snap ()
99 applyCORS corsOptions $ method POST $
100 do result <- foldMultipart defaultUploadPolicy ignoreFile 0
102 ([("code",source)], 0) ->
103 do modifyResponse $ setContentType "text/html; charset=utf-8"
104 case compileToBuilder artifacts source of
105 Right builder -> writeBuilder builder
106 Left exit -> writeBuilder (exitToHtmlBuilder exit)
109 do modifyResponse $ setResponseStatus 400 "Bad Request"
110 modifyResponse $ setContentType "text/html; charset=utf-8"
112 "<p>Unexpected request format. This should not be possible!</p>\
113 \<p>Please report this\
114 \ <a href=\"https://github.com/elm/compiler/issues\">here</a>\
115 \ along with the URL and your browser version.</p>"
118ignoreFile :: PartInfo -> Stream.InputStream B.ByteString -> Int -> IO Int
119ignoreFile _ _ count =
123exitToHtmlBuilder :: Exit.Worker -> B.Builder
124exitToHtmlBuilder exit =
127 Encode.encodeUgly $ Exit.toJson $ Exit.workerToReport exit
132 <meta charset="UTF-8">
133 <style>body { padding: 0; margin: 0; background-color: black; }</style>
134 <script src="http://localhost:8000/compile/errors.js"></script>
137 <script>Elm.Errors.init({flags:|] <> json <> [r|});</script>
146compileToBuilder :: Artifacts -> B.ByteString -> Either Exit.Worker B.Builder
147compileToBuilder (Artifacts interfaces objects) source =
148 case Parse.fromByteString Pkg.dummyName source of
150 Left $ toInputError N._Main source (Error.BadSyntax err)
152 Right modul@(Src.Module _ _ _ imports _ _ _ _ _) ->
153 case checkImports interfaces imports of
155 Left $ toInputError (Src.getName modul) source (Error.BadImports err)
158 case Compile.compile Pkg.dummyName ifaces modul of
160 Left $ toInputError (Src.getName modul) source err
162 Right (Compile.Artifacts canModule _ locals) ->
164 Opt.LocalGraph Nothing _ _ ->
165 Left Exit.WorkerNoMain
167 Opt.LocalGraph (Just main_) _ _ ->
169 mode = Mode.Dev Nothing
170 home = Can._name canModule
171 name = ModuleName._module home
172 mains = Map.singleton home main_
173 graph = Opt.addLocalGraph locals objects
175 Right $ Html.sandwich name $ Generate.generate mode graph mains
178checkImports :: Map.Map ModuleName.Raw I.Interface -> [Src.Import] -> Either (NE.List Import.Error) (Map.Map ModuleName.Raw I.Interface)
179checkImports interfaces imports =
181 importDict = Map.fromValues Src.getImportName imports
182 missing = Map.difference importDict interfaces
184 case Map.elems missing of
186 Right (Map.intersection interfaces importDict)
190 unimported = Map.keysSet (Map.difference interfaces importDict)
191 toError (Src.Import (A.At region name) _ _) =
192 Import.Error region name unimported Import.NotFound
194 Left (fmap toError (NE.List i is))
197toInputError :: ModuleName.Raw -> B.ByteString -> Error.Error -> Exit.Worker
198toInputError name source err =
199 Exit.WorkerInputError $
200 Error.Module name "/try" File.zeroTime source err
204-- COMPILE ERROR VIEWER
207compileErrorViewer :: IO B.ByteString
214 Left _ -> error "problem building reactor/src/Errors.elm"
216 Dir.withCurrentDirectory "../reactor" $ BW.withScope $ \scope ->
218 details <- run $ Details.load Reporting.silent scope root
219 artifacts <- run $ Build.fromMains Reporting.silent root details (NE.List "src/Errors.elm" [])
220 javascript <- run $ Task.run $ Generate.prod root details artifacts
221 return $ LBS.toStrict $ B.toLazyByteString javascript
228corsOptions :: (Monad m) => CORSOptions m
231 allowedOrigins = toOriginList [ "https://elm-lang.org", "https://package.elm-lang.org" ]
232 allowedMethods = HashSet.singleton (HashableMethod POST)
235 { corsAllowOrigin = return allowedOrigins
236 , corsAllowCredentials = return True
237 , corsExposeHeaders = return HashSet.empty
238 , corsAllowedMethods = return allowedMethods
239 , corsAllowedHeaders = return
243toOriginList :: [String] -> OriginList
244toOriginList origins =
245 Origins $ mkOriginSet $
246 case traverse parseURI origins of
248 Nothing -> error "invalid entry given to toOriginList list"
257 { _ifaces :: Map.Map ModuleName.Raw I.Interface
258 , _graph :: Opt.GlobalGraph
262loadArtifacts :: IO Artifacts
264 BW.withScope $ \scope ->
265 do style <- Reporting.terminal
266 root <- Dir.getCurrentDirectory
267 result <- Details.load style scope root
270 error "Ran into some problem loading elm.json details"
273 do omvar <- Details.loadObjects root details
274 imvar <- Details.loadInterfaces root details
275 mdeps <- readMVar imvar
276 mobjs <- readMVar omvar
277 case liftM2 (,) mdeps mobjs of
279 error "Ran into some weird problem loading elm.json details"
282 return $ Artifacts (toInterfaces deps) objs
285toInterfaces :: Map.Map ModuleName.Canonical I.DependencyInterface -> Map.Map ModuleName.Raw I.Interface
287 Map.mapMaybe toUnique $ Map.fromListWith OneOrMore.more $
288 Map.elems (Map.mapMaybeWithKey getPublic deps)
291getPublic :: ModuleName.Canonical -> I.DependencyInterface -> Maybe (ModuleName.Raw, OneOrMore.OneOrMore I.Interface)
292getPublic (ModuleName.Canonical _ name) dep =
294 I.Public iface -> Just (name, OneOrMore.one iface)
295 I.Private _ _ _ -> Nothing
298toUnique :: OneOrMore.OneOrMore a -> Maybe a
301 OneOrMore.One value -> Just value
302 OneOrMore.More _ _ -> Nothing
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list