@@ -2,30 +2,50 @@
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Elm.Docs
3module Elm.Docs
4 ( Documentation
4 ( Documentation
7− , decoder
6+ , Module(..)
8− , encode
7+ , fromCanonical
9 , Union(..)
8 , Union(..)
10 , Alias(..)
9 , Alias(..)
11 , Value(..)
10 , Value(..)
12 , Binop(..)
11 , Binop(..)
13 , Binop.Associativity(..)
12 , Binop.Associativity(..)
14 , Binop.Precedence(..)
13 , Binop.Precedence(..)
20+import Control.Monad (foldM)
21+import qualified Data.ByteString as B
22+import qualified Data.List as List
19import qualified Data.Map as Map
24import qualified Data.Map as Map
25+import qualified Data.Text as Text
20−import Data.Text (Text)
26+import qualified Data.Text.Encoding as Text
28+import qualified AST.Canonical as Can
29+import qualified AST.Module.Name as ModuleName
22import qualified AST.Utils.Binop as Binop
30import qualified AST.Utils.Binop as Binop
31+import qualified Data.OneOrMore as OneOrMore
23import qualified Elm.Compiler.Module as Module
32import qualified Elm.Compiler.Module as Module
24import qualified Elm.Compiler.Type as Type
33import qualified Elm.Compiler.Type as Type
34+import qualified Elm.Compiler.Type.Extract as Extract
25import qualified Elm.Name as N
35import qualified Elm.Name as N
26import qualified Json.Decode as Decode
36import qualified Json.Decode as Decode
27import qualified Json.Encode as Encode
37import qualified Json.Encode as Encode
28import Json.Encode ((==>))
38import Json.Encode ((==>))
39+import qualified Reporting.Annotation as A
40+import qualified Reporting.Error as Error
41+import qualified Reporting.Error.Docs as E
42+import qualified Reporting.Region as R
43+import qualified Reporting.Result as Result
44+import Parse.Primitives (Parser)
45+import qualified Parse.Primitives as P
46+import qualified Parse.Primitives.Symbol as Symbol
47+import qualified Parse.Primitives.Variable as Var
48+import qualified Parse.Primitives.Whitespace as W
@@ -54,7 +74,7 @@ toPair modul@(Module name _ _ _ _ _) =
54data Module =
74data Module =
56 { _name :: N.Name
76 { _name :: N.Name
57− , _comment :: Text
77+ , _comment :: Comment
58 , _unions :: Map.Map N.Name Union
78 , _unions :: Map.Map N.Name Union
59 , _aliases :: Map.Map N.Name Alias
79 , _aliases :: Map.Map N.Name Alias
60 , _values :: Map.Map N.Name Value
80 , _values :: Map.Map N.Name Value
@@ -62,14 +82,17 @@ data Module =
65−data Alias = Alias Text [N.Name] Type.Type
85+type Comment = Text.Text
66−data Union = Union Text [N.Name] [(N.Name, [Type.Type])]
67−data Value = Value Text Type.Type
68−data Binop = Binop Text Type.Type Binop.Associativity Binop.Precedence
88+data Alias = Alias Comment [N.Name] Type.Type
89+data Union = Union Comment [N.Name] [(N.Name, [Type.Type])]
90+data Value = Value Comment Type.Type
91+data Binop = Binop Comment Type.Type Binop.Associativity Binop.Precedence
72−-- ENCODE
95+-- JSON ENCODE / DECODE
75encode :: Module -> Encode.Value
98encode :: Module -> Encode.Value
@@ -84,10 +107,6 @@ encode (Module name comment unions aliases values binops) =
91decoder :: Decode.Decoder Module
110decoder :: Decode.Decoder Module
@@ -112,7 +131,7 @@ named entryDecoder =
115−-- UNION
134+-- UNION JSON
118encodeUnion :: (N.Name, Union) -> Encode.Value
137encodeUnion :: (N.Name, Union) -> Encode.Value
@@ -133,10 +152,6 @@ union =
133 <*> Decode.field "cases" (Decode.list caseDecoder)
152 <*> Decode.field "cases" (Decode.list caseDecoder)
140encodeCase :: ( N.Name, [Type.Type] ) -> Encode.Value
155encodeCase :: ( N.Name, [Type.Type] ) -> Encode.Value
141encodeCase ( tag, args ) =
156encodeCase ( tag, args ) =
142 Encode.list id [ Encode.text tag, Encode.list Type.encode args ]
157 Encode.list id [ Encode.text tag, Encode.list Type.encode args ]
@@ -150,7 +165,7 @@ caseDecoder =
153−-- ALIAS
168+-- ALIAS JSON
156encodeAlias :: (N.Name, Alias) -> Encode.Value
171encodeAlias :: (N.Name, Alias) -> Encode.Value
@@ -172,7 +187,7 @@ alias =
175−-- ENCODE VALUE
190+-- VALUE JSON
178encodeValue :: (N.Name, Value) -> Encode.Value
193encodeValue :: (N.Name, Value) -> Encode.Value
@@ -192,7 +207,7 @@ value =
195−-- BINOP
210+-- BINOP JSON
198encodeBinop :: (N.Name, Binop) -> Encode.Value
213encodeBinop :: (N.Name, Binop) -> Encode.Value
@@ -216,7 +231,7 @@ binop =
219−-- ASSOCIATIVITY
234+-- ASSOCIATIVITY JSON
222encodeAssoc :: Binop.Associativity -> Encode.Value
237encodeAssoc :: Binop.Associativity -> Encode.Value
@@ -238,7 +253,7 @@ assocDecoder =
241−-- PRECEDENCE
256+-- PRECEDENCE JSON
244encodePrec :: Binop.Precedence -> Encode.Value
259encodePrec :: Binop.Precedence -> Encode.Value
@@ -249,3 +264,257 @@ encodePrec (Binop.Precedence n) =
249precDecoder :: Decode.Decoder Binop.Precedence
264precDecoder :: Decode.Decoder Binop.Precedence
250precDecoder =
265precDecoder =
251 Binop.Precedence <$> Decode.int
266 Binop.Precedence <$> Decode.int
273+fromCanonical :: Can.Module -> Result.Result i w Error.Error Module
274+fromCanonical (Can.Module name docs exports decls unions aliases binops effects) =
276+ Can.ExportEverything ->
277+ Result.throw $ Error.Docs $ E.ImplicitExposing
279+ Can.Export exportDict ->
282+ Result.throw $ Error.Docs $ E.NoDocs
284+ Just (A.At region (Can.Docs overview comments)) ->
285+ do names <- parseOverview region overview
286+ Result.mapError Error.Docs $
287+ do checkNames exportDict names
288+ let types = gatherTypes decls Map.empty
290+ (addExport (Info comments types unions aliases binops effects))
291+ (emptyModule name overview)
292+ (Map.toList exportDict)
295+emptyModule :: ModuleName.Canonical -> B.ByteString -> Module
296+emptyModule (ModuleName.Canonical _ name) overview =
297+ Module name (Text.decodeUtf8 overview) Map.empty Map.empty Map.empty Map.empty
304+type LName = A.Located N.Name
307+parseOverview :: R.Region -> B.ByteString -> Result.Result i w Error.Error [LName]
308+parseOverview (R.Region (R.Position row col) _) overview =
309+ case P.runAt row (col + 3) (chompOverview []) overview of
311+ Result.throw (Error.Syntax err)
317+chompOverview :: [LName] -> Parser [LName]
318+chompOverview names =
319+ do isDocs <- W.chompUntilDocs
321+ then chompOverviewHelp names
325+chompOverviewHelp :: [LName] -> Parser [LName]
326+chompOverviewHelp names =
327+ do pos <- P.getPosition
328+ (W.SPos spos) <- W.whitespace
330+ then chompOverview names
331+ else chompOverview =<< chompDocs names
334+chompDocs :: [LName] -> Parser [LName]
336+ do name <- P.addLocation (P.oneOf [ Var.lower, Var.upper, chompBinop ])
337+ spos <- W.whitespace
339+ [ do P.checkSpace spos
342+ chompDocs (name:names)
343+ , return (name:names)
347+chompBinop :: Parser N.Name
350+ name <- Symbol.binop
360+ Result.Result i w E.Error a
364+ Map.Map N.Name (OneOrMore.OneOrMore R.Region)
367+checkNames :: Map.Map N.Name (A.Located Can.Export) -> [LName] -> Result i w ()
368+checkNames exports names =
369+ do docs <- Map.traverseWithKey isUnique (List.foldl' addName Map.empty names)
370+ let overlap = Map.size (Map.intersection docs exports)
371+ if Map.size exports == overlap && overlap == Map.size docs
374+ do _ <- Map.traverseWithKey onlyInDocs (Map.difference docs exports)
375+ _ <- Map.traverseWithKey onlyInExports (Map.difference exports docs)
379+addName :: Dups -> LName -> Dups
380+addName dict (A.At region name) =
381+ Map.insertWith OneOrMore.more name (OneOrMore.one region) dict
384+isUnique :: N.Name -> OneOrMore.OneOrMore R.Region -> Result i w R.Region
385+isUnique name regions =
387+ OneOrMore.One region ->
390+ OneOrMore.More _ _ ->
391+ let (r1:r2:_) = OneOrMore.toList regions in
392+ Result.throw (E.Duplicate name r1 r2)
395+onlyInDocs :: N.Name -> R.Region -> Result i w a
396+onlyInDocs name region =
397+ Result.throw $ E.OnlyInDocs name region
400+onlyInExports :: N.Name -> A.Located Can.Export -> Result i w a
401+onlyInExports name (A.At region _) =
402+ Result.throw $ E.OnlyInExports name region
411+ { _iComments :: Map.Map N.Name Comment
413+ , _iUnions :: Map.Map N.Name Can.Union
414+ , _iAliases :: Map.Map N.Name Can.Alias
415+ , _iBinops :: Map.Map N.Name Can.Binop
416+ , _iEffects :: Can.Effects
420+addExport :: Info -> Module -> (N.Name, A.Located Can.Export) -> Result i w Module
421+addExport info (Module n c us as_ vs bs) (name, A.At region export) =
424+ do tipe <- getType region name info
425+ comment <- getComment region name info
427+ let newValues = Map.insert name (Value comment tipe) vs
428+ Result.ok $ Module n c us as_ newValues bs
431+ do let (Can.Binop_ assoc prec realName) = _iBinops info ! name
432+ tipe <- getType region realName info
433+ comment <- getComment region realName info
435+ let newBinops = Map.insert name (Binop comment tipe assoc prec) bs
436+ Result.ok $ Module n c us as_ vs newBinops
439+ do let (Can.Alias tvars tipe _) = _iAliases info ! name
440+ comment <- getComment region name info
442+ let newAliases = Map.insert name (Alias comment tvars (Extract.fromType tipe)) as_
443+ Result.ok $ Module n c us newAliases vs bs
445+ Can.ExportUnionOpen ->
446+ do let (Can.Union tvars ctors) = _iUnions info ! name
447+ comment <- getComment region name info
449+ let newUnions = Map.insert name (Union comment tvars (map dector ctors)) us
450+ Result.ok $ Module n c newUnions as_ vs bs
452+ Can.ExportUnionClosed ->
453+ do let (Can.Union tvars _) = _iUnions info ! name
454+ comment <- getComment region name info
456+ let newUnions = Map.insert name (Union comment tvars []) us
457+ Result.ok $ Module n c newUnions as_ vs bs
463+getComment :: R.Region -> N.Name -> Info -> Result i w Comment
464+getComment region name info =
465+ case Map.lookup name (_iComments info) of
467+ Result.throw (E.NoComment name region)
473+getType :: R.Region -> N.Name -> Info -> Result i w Type.Type
474+getType exportRegion name info =
475+ case _iValues info ! name of
476+ A.At defRegion Nothing ->
477+ Result.throw (E.NoAnnotation name exportRegion defRegion)
479+ A.At _ (Just tipe) ->
480+ Result.ok (Extract.fromType tipe)
483+dector :: (N.Name, [Can.Type]) -> (N.Name, [Type.Type])
484+dector (name, args) =
485+ ( name, map Extract.fromType args )
493+ Map.Map N.Name (A.Located (Maybe Can.Type))
496+gatherTypes :: Can.Decls -> Types -> Types
497+gatherTypes decls types =
499+ Can.Declare def subDecls ->
500+ gatherTypes subDecls (addDef types def)
502+ Can.DeclareRec defs subDecls ->
503+ gatherTypes subDecls (List.foldl' addDef types defs)
505+ Can.SaveTheEnvironment ->
509+addDef :: Types -> Can.Def -> Types
512+ Can.Def (A.At region name) _ _ ->
513+ Map.insert name (A.At region Nothing) types
515+ Can.TypedDef (A.At region name) _ typedArgs _ resultType ->
518+ foldr Can.TLambda resultType (map snd typedArgs)
520+ Map.insert name (A.At region (Just tipe)) types