@@ -1,3 +1,6 @@
1+{-# LANGUAGE RecordWildCards #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE TupleSections #-}
2module Language.PureScript.Docs.Types
5module Language.PureScript.Docs.Types
3 ( module Language.PureScript.Docs.Types
6 ( module Language.PureScript.Docs.Types
@@ -5,24 +8,47 @@ module Language.PureScript.Docs.Types
11+import Control.Arrow (first, (***))
12+import Control.Applicative ((<$>), (<*>))
14+import Data.Maybe (mapMaybe)
8import Data.Version
15import Data.Version
16+import Data.Aeson ((.=))
17+import qualified Data.Aeson as A
18+import Data.Aeson.BetterErrors
19+import Text.ParserCombinators.ReadP (readP_to_S)
20+import Data.Text (Text)
21+import qualified Data.Text as T
23+import Web.Bower.PackageMeta hiding (Version)
9import qualified Language.PureScript as P
25import qualified Language.PureScript as P
11−import Language.PureScript.Docs.RenderedCode as ReExports (RenderedCode, ContainingModule(..))
27+import Language.PureScript.Docs.RenderedCode as ReExports
28+ (RenderedCode, asRenderedCode,
29+ ContainingModule(..), asContainingModule,
30+ RenderedCodeElement(..), asRenderedCodeElement)
13−data RenderedPackage = RenderedPackage
32+--------------------
14− { rpName :: String
33+-- Types
35+data UploadedPackage = UploadedPackage
36+ { pkgMeta :: PackageMeta
15− , rpVersion :: Version
37+ , pkgVersion :: Version
16− , rpModules :: [RenderedModule]
38+ , pkgModules :: [RenderedModule]
39+ , pkgBookmarks :: [Bookmark]
40+ , pkgResolvedDependencies :: [(PackageName, Version)]
41+ , pkgGithub :: (GithubUser, GithubRepo)
42+ , pkgUploader :: Maybe GithubUser
18− deriving (Show)
44+ deriving (Show, Eq, Ord)
20data RenderedModule = RenderedModule
46data RenderedModule = RenderedModule
21 { rmName :: String
47 { rmName :: String
22 , rmComments :: Maybe String
48 , rmComments :: Maybe String
23 , rmDeclarations :: [RenderedDeclaration]
49 , rmDeclarations :: [RenderedDeclaration]
25− deriving (Show)
51+ deriving (Show, Eq, Ord)
27data RenderedDeclaration = RenderedDeclaration
53data RenderedDeclaration = RenderedDeclaration
28 { rdTitle :: String
54 { rdTitle :: String
@@ -31,7 +57,7 @@ data RenderedDeclaration = RenderedDeclaration
31 , rdSourceSpan :: Maybe P.SourceSpan
57 , rdSourceSpan :: Maybe P.SourceSpan
32 , rdChildren :: [RenderedChildDeclaration]
58 , rdChildren :: [RenderedChildDeclaration]
34− deriving (Show)
60+ deriving (Show, Eq, Ord)
36data RenderedChildDeclaration = RenderedChildDeclaration
62data RenderedChildDeclaration = RenderedChildDeclaration
37 { rcdTitle :: String
63 { rcdTitle :: String
@@ -40,10 +66,213 @@ data RenderedChildDeclaration = RenderedChildDeclaration
40 , rcdSourceSpan :: Maybe P.SourceSpan
66 , rcdSourceSpan :: Maybe P.SourceSpan
41 , rcdType :: RenderedChildDeclarationType
67 , rcdType :: RenderedChildDeclarationType
43− deriving (Show)
69+ deriving (Show, Eq, Ord)
45data RenderedChildDeclarationType
71data RenderedChildDeclarationType
46 = ChildInstance
72 = ChildInstance
47 | ChildDataConstructor
73 | ChildDataConstructor
48 | ChildTypeClassMember
74 | ChildTypeClassMember
75+ deriving (Show, Eq, Ord, Bounded, Enum)
77+childDeclTypeToString :: RenderedChildDeclarationType -> String
78+childDeclTypeToString = withHead toLower . drop 5 . show
80+ withHead f (x:xs) = f x : xs
83+childDeclarationTypes :: [(String, RenderedChildDeclarationType)]
84+childDeclarationTypes =
85+ map (\t -> (childDeclTypeToString t, t)) [minBound .. maxBound]
88+ = GithubUser { runGithubUser :: String }
89+ deriving (Show, Eq, Ord)
92+ = GithubRepo { runGithubRepo :: String }
49 deriving (Show, Eq, Ord)
93 deriving (Show, Eq, Ord)
95+data UploadedPackageError
96+ = ErrorInPackageMeta BowerError
98+ | InvalidDeclarationType
99+ | InvalidRenderedCode String
100+ deriving (Show, Eq, Ord)
102+type Bookmark = InPackage (P.ModuleName, String)
106+ | FromDep PackageName a
107+ deriving (Show, Eq, Ord)
109+instance Functor InPackage where
110+ fmap f (Local x) = Local (f x)
111+ fmap f (FromDep pkgName x) = FromDep pkgName (f x)
113+takeLocal :: InPackage a -> Maybe a
114+takeLocal (Local a) = Just a
115+takeLocal _ = Nothing
117+takeLocals :: [InPackage a] -> [a]
118+takeLocals = mapMaybe takeLocal
120+ignorePackage :: InPackage a -> a
121+ignorePackage (Local x) = x
122+ignorePackage (FromDep _ x) = x
124+----------------------
127+asUploadedPackage :: Parse UploadedPackageError UploadedPackage
129+ UploadedPackage <$> key "packageMeta" asPackageMeta .! ErrorInPackageMeta
130+ <*> key "version" asVersion
131+ <*> key "modules" (eachInArray asRenderedModule)
132+ <*> key "bookmarks" asBookmarks .! ErrorInPackageMeta
133+ <*> key "resolvedDependencies" asResolvedDependencies
134+ <*> key "github" asGithub
135+ <*> keyMay "uploader" (GithubUser <$> asString)
137+asVersion :: Parse UploadedPackageError Version
138+asVersion = withString (maybe (Left InvalidVersion) Right . parseVersion')
140+parseVersion' :: String -> Maybe Version
142+ case filter (null . snd) $ readP_to_S parseVersion str of
143+ [(vers, "")] -> Just vers
146+asRenderedModule :: Parse UploadedPackageError RenderedModule
148+ RenderedModule <$> key "name" asString
149+ <*> key "comments" (perhaps asString)
150+ <*> key "declarations" (eachInArray asDeclaration)
152+asDeclaration :: Parse UploadedPackageError RenderedDeclaration
154+ RenderedDeclaration <$> key "title" asString
155+ <*> key "comments" (perhaps asString)
156+ <*> key "code" asRenderedCode .! InvalidRenderedCode
157+ <*> key "sourceSpan" (perhaps asSourceSpan)
158+ <*> key "children" (eachInArray asRenderedChildDeclaration)
160+asRenderedChildDeclaration :: Parse UploadedPackageError RenderedChildDeclaration
161+asRenderedChildDeclaration =
162+ RenderedChildDeclaration <$> key "title" asString
163+ <*> key "comments" (perhaps asString)
164+ <*> key "code" asRenderedCode .! InvalidRenderedCode
165+ <*> key "sourceSpan" (perhaps asSourceSpan)
166+ <*> key "type" asRenderedChildDeclarationType .!! InvalidDeclarationType
168+ p .!! err = p .! const err
170+asRenderedChildDeclarationType :: Parse UploadedPackageError RenderedChildDeclarationType
171+asRenderedChildDeclarationType =
172+ withString (maybe (Left InvalidDeclarationType) Right .
173+ flip lookup childDeclarationTypes)
175+asSourcePos :: Parse e P.SourcePos
176+asSourcePos = P.SourcePos <$> nth 0 asIntegral
177+ <*> nth 1 asIntegral
179+asBookmarks :: Parse BowerError [Bookmark]
180+asBookmarks = eachInArray asBookmark
182+asBookmark :: Parse BowerError Bookmark
184+ build <$> key "package" (perhaps (withString parsePackageName))
185+ <*> key "item" ((,) <$> nth 0 (P.moduleNameFromString <$> asString)
188+ build Nothing = Local
189+ build (Just pn) = FromDep pn
191+asResolvedDependencies :: Parse UploadedPackageError [(PackageName, Version)]
192+asResolvedDependencies =
193+ eachInObjectWithKey (mapLeft ErrorInPackageMeta . parsePackageName . T.unpack) asVersion
195+ mapLeft f (Left x) = Left (f x)
196+ mapLeft _ (Right x) = Right x
198+asGithub :: Parse e (GithubUser, GithubRepo)
199+asGithub = (,) <$> nth 0 (GithubUser <$> asString)
200+ <*> nth 1 (GithubRepo <$> asString)
202+asSourceSpan :: Parse e P.SourceSpan
203+asSourceSpan = P.SourceSpan <$> key "name" asString
204+ <*> key "start" asSourcePos
205+ <*> key "end" asSourcePos
207+---------------------
210+instance A.ToJSON UploadedPackage where
211+ toJSON UploadedPackage{..} =
213+ [ "packageMeta" .= pkgMeta
214+ , "version" .= showVersion pkgVersion
215+ , "modules" .= pkgModules
216+ , "bookmarks" .= map (fmap (first P.runModuleName)) pkgBookmarks
217+ , "resolvedDependencies" .= assocListToJSON (T.pack . runPackageName)
218+ (T.pack . showVersion)
219+ pkgResolvedDependencies
220+ , "github" .= pkgGithub
221+ ] ++ case pkgUploader of
222+ Just u -> [ "uploader" .= u ]
225+instance A.ToJSON RenderedModule where
226+ toJSON RenderedModule{..} =
227+ A.object [ "name" .= rmName
228+ , "comments" .= rmComments
229+ , "declarations" .= rmDeclarations
232+instance A.ToJSON RenderedDeclaration where
233+ toJSON RenderedDeclaration{..} =
234+ A.object [ "title" .= rdTitle
235+ , "comments" .= rdComments
237+ , "sourceSpan" .= rdSourceSpan
238+ , "children" .= rdChildren
241+instance A.ToJSON RenderedChildDeclaration where
242+ toJSON RenderedChildDeclaration{..} =
243+ A.object [ "title" .= rcdTitle
244+ , "comments" .= rcdComments
246+ , "sourceSpan" .= rcdSourceSpan
250+instance A.ToJSON RenderedChildDeclarationType where
251+ toJSON = A.toJSON . childDeclTypeToString
253+instance A.ToJSON GithubUser where
254+ toJSON = A.toJSON . runGithubUser
256+instance A.ToJSON GithubRepo where
257+ toJSON = A.toJSON . runGithubRepo
259+-- | Given a function for turning association list keys into JSON object keys,
260+-- and a function for turning association list values to JSON string values,
261+-- turns an association list into a JSON object.
264+-- @assocListToJSON T.pack T.pack [("a", "b")]@ will give @{"a": "b"}@.
265+assocListToJSON :: (a -> Text) -> (b -> Text) -> [(a, b)] -> A.Value
266+assocListToJSON f g xs = A.object (map (uncurry (.=) . (f *** g)) xs)
268+instance A.ToJSON a => A.ToJSON (InPackage a) where
271+ Local y -> withPackage (Nothing :: Maybe ()) y
272+ FromDep pn y -> withPackage (Just pn) y
274+ withPackage :: (A.ToJSON p, A.ToJSON x) => p -> x -> A.Value
276+ A.object [ "package" .= p