1{-# LANGUAGE OverloadedStrings, QuasiQuotes #-}
8import Control.Applicative ((<|>))
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
24import Snap.Util.FileServe (serveFile)
25import Snap.Util.FileUploads
26import qualified System.Directory as Dir
27import qualified System.Exit as Exit
28import qualified System.IO.Streams as Stream
29import Text.RawString.QQ (r)
31import qualified AST.Source as Src
32import qualified AST.Canonical as Can
33import qualified AST.Optimized as Opt
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.Html as Html
41import qualified Generate.JavaScript as Generate
42import qualified Generate.Mode as Mode
43import qualified Json.Encode as Encode
44import qualified Parse.Module as Parse
45import qualified Reporting
46import qualified Reporting.Annotation as A
47import qualified Reporting.Error as Error
48import qualified Reporting.Error.Import as Import
49import qualified Reporting.Exit as Exit
58 do artifacts <- loadArtifacts
59 errorJS <- compileErrorViewer artifacts
60 httpServe config $ msum $
61 [ path "compile" $ compile artifacts
62 , path "compile/error.js" $ writeBS errorJS
67config :: Config Snap a
72 |> setAccessLog ConfigNoLog
73 |> setErrorLog ConfigNoLog
76(|>) :: a -> (a -> b) -> b
87 do modifyResponse $ setResponseStatus 404 "Not Found"
88 modifyResponse $ setContentType "text/html; charset=utf-8"
96compile :: Artifacts -> Snap ()
98 applyCORS corsOptions $ method POST $
99 do parts <- handleMultipart defaultUploadPolicy handlePart
102 case compileToBuilder artifacts source of
103 Right builder -> writeBuilder builder
104 Left exit -> writeBuilder (exitToHtmlBuilder exit)
110handlePart :: PartInfo -> Stream.InputStream B.ByteString -> IO (Maybe B.ByteString)
111handlePart info stream =
112 if partFieldName info == "code" && partDisposition info == DispositionFormData
113 then Just . LBS.toStrict <$> storeAsLazyByteString stream
117exitToHtmlBuilder :: Exit.Worker -> B.Builder
118exitToHtmlBuilder exit =
121 Encode.encodeUgly $ Exit.toJson $ Exit.workerToReport exit
126 <meta charset="UTF-8">
127 <style>body { padding: 0; margin: 0; }</style>
128 <script src="https://worker.elm-lang.org/compile/error.js"></script>
129 <script>Elm.Error.init({flags:|] <> json <> [r|})</script>
139compileToBuilder :: Artifacts -> B.ByteString -> Either Exit.Worker B.Builder
140compileToBuilder (Artifacts interfaces objects) source =
141 case Parse.fromByteString Pkg.dummyName source of
143 Left $ toInputError N._Main source (Error.BadSyntax err)
145 Right modul@(Src.Module _ _ _ imports _ _ _ _ _) ->
146 case checkImports interfaces imports of
148 Left $ toInputError (Src.getName modul) source (Error.BadImports err)
151 case Compile.compile Pkg.dummyName ifaces modul of
153 Left $ toInputError (Src.getName modul) source err
155 Right artifacts@(Compile.Artifacts modul _ locals) ->
157 Opt.LocalGraph Nothing _ _ ->
158 Left Exit.WorkerNoMain
160 Opt.LocalGraph (Just main) _ _ ->
162 mode = Mode.Dev Nothing
163 home = Can._name modul
164 name = ModuleName._module home
165 mains = Map.singleton home main
166 graph = Opt.addLocalGraph locals objects
168 Right $ Html.sandwich name $ Generate.generate mode graph mains
171checkImports :: Map.Map ModuleName.Raw I.Interface -> [Src.Import] -> Either (NE.List Import.Error) (Map.Map ModuleName.Raw I.Interface)
172checkImports interfaces imports =
174 importDict = Map.fromValues Src.getImportName imports
175 missing = Map.difference importDict interfaces
177 case Map.elems missing of
179 Right (Map.intersection interfaces importDict)
183 unimported = Map.keysSet (Map.difference interfaces importDict)
184 toError (Src.Import (A.At region name) _ _) =
185 Import.Error region name unimported Import.NotFound
187 Left (fmap toError (NE.List i is))
190toInputError :: ModuleName.Raw -> B.ByteString -> Error.Error -> Exit.Worker
191toInputError name source err =
192 Exit.WorkerInputError $
193 Error.Module name "/try" File.zeroTime source err
197-- COMPILE ERROR VIEWER
200compileErrorViewer :: Artifacts -> IO B.ByteString
201compileErrorViewer artifacts =
202 do source <- File.readUtf8 "src/Error.elm"
203 case compileToBuilder artifacts source of
205 do putStrLn "Problem in src/Error.elm"
206 Exit.toStderr (Exit.workerToReport exit)
210 return (LBS.toStrict (B.toLazyByteString builder))
217corsOptions :: (Monad m) => CORSOptions m
220 allowedOrigins = toOriginList [ "https://elm-lang.org", "https://package.elm-lang.org" ]
221 allowedMethods = HashSet.singleton (HashableMethod POST)
224 { corsAllowOrigin = return allowedOrigins
225 , corsAllowCredentials = return True
226 , corsExposeHeaders = return HashSet.empty
227 , corsAllowedMethods = return allowedMethods
228 , corsAllowedHeaders = return
232toOriginList :: [String] -> OriginList
233toOriginList origins =
234 Origins $ mkOriginSet $
235 case traverse parseURI origins of
237 Nothing -> error "invalid entry given to toOriginList list"
246 { _ifaces :: Map.Map ModuleName.Raw I.Interface
247 , _graph :: Opt.GlobalGraph
251loadArtifacts :: IO Artifacts
253 do style <- Reporting.terminal
254 root <- Dir.getCurrentDirectory
255 result <- Details.load style root
258 error "Ran into some problem loading elm.json details"
261 do omvar <- Details.loadObjects root details
262 imvar <- Details.loadInterfaces root details
263 mdeps <- readMVar imvar
264 mobjs <- readMVar omvar
265 case liftM2 (,) mdeps mobjs of
267 error "Ran into some weird problem loading elm.json details"
270 return $ Artifacts (toInterfaces deps) objs
273toInterfaces :: Map.Map ModuleName.Canonical I.DependencyInterface -> Map.Map ModuleName.Raw I.Interface
275 Map.mapMaybe toUnique $ Map.fromListWith OneOrMore.more $
276 Map.elems (Map.mapMaybeWithKey getPublic deps)
279getPublic :: ModuleName.Canonical -> I.DependencyInterface -> Maybe (ModuleName.Raw, OneOrMore.OneOrMore I.Interface)
280getPublic (ModuleName.Canonical _ name) dep =
282 I.Public iface -> Just (name, OneOrMore.one iface)
283 I.Private _ _ _ -> Nothing
286toUnique :: OneOrMore.OneOrMore a -> Maybe a
289 OneOrMore.One value -> Just value
290 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