never executed always true always false
1
2 {-# LANGUAGE DeriveDataTypeable #-}
3
4 module GHC.Hs.Doc
5 ( HsDocString
6 , LHsDocString
7 , mkHsDocString
8 , mkHsDocStringUtf8ByteString
9 , isEmptyDocString
10 , unpackHDS
11 , hsDocStringToByteString
12 , ppr_mbDoc
13
14 , appendDocs
15 , concatDocs
16
17 , DeclDocMap(..)
18 , emptyDeclDocMap
19
20 , ArgDocMap(..)
21 , emptyArgDocMap
22
23 , ExtractedTHDocs(..)
24 ) where
25
26 import GHC.Prelude
27
28 import GHC.Utils.Binary
29 import GHC.Utils.Encoding
30 import GHC.Types.Name
31 import GHC.Utils.Outputable as Outputable
32 import GHC.Types.SrcLoc
33
34 import Data.ByteString (ByteString)
35 import qualified Data.ByteString as BS
36 import qualified Data.ByteString.Char8 as C8
37 import Data.Data
38 import Data.IntMap (IntMap)
39 import qualified Data.IntMap as IntMap
40 import Data.Map (Map)
41 import qualified Data.Map as Map
42 import Data.Maybe
43
44 -- | Haskell Documentation String
45 --
46 -- Internally this is a UTF8-Encoded 'ByteString'.
47 newtype HsDocString = HsDocString ByteString
48 -- There are at least two plausible Semigroup instances for this type:
49 --
50 -- 1. Simple string concatenation.
51 -- 2. Concatenation as documentation paragraphs with newlines in between.
52 --
53 -- To avoid confusion, we pass on defining an instance at all.
54 deriving (Eq, Show, Data)
55
56 -- | Located Haskell Documentation String
57 type LHsDocString = Located HsDocString
58
59 instance Binary HsDocString where
60 put_ bh (HsDocString bs) = put_ bh bs
61 get bh = HsDocString <$> get bh
62
63 instance Outputable HsDocString where
64 ppr = doubleQuotes . text . unpackHDS
65
66 isEmptyDocString :: HsDocString -> Bool
67 isEmptyDocString (HsDocString bs) = BS.null bs
68
69 mkHsDocString :: String -> HsDocString
70 mkHsDocString s = HsDocString (utf8EncodeString s)
71
72 -- | Create a 'HsDocString' from a UTF8-encoded 'ByteString'.
73 mkHsDocStringUtf8ByteString :: ByteString -> HsDocString
74 mkHsDocStringUtf8ByteString = HsDocString
75
76 unpackHDS :: HsDocString -> String
77 unpackHDS = utf8DecodeByteString . hsDocStringToByteString
78
79 -- | Return the contents of a 'HsDocString' as a UTF8-encoded 'ByteString'.
80 hsDocStringToByteString :: HsDocString -> ByteString
81 hsDocStringToByteString (HsDocString bs) = bs
82
83 ppr_mbDoc :: Maybe LHsDocString -> SDoc
84 ppr_mbDoc (Just doc) = ppr doc
85 ppr_mbDoc Nothing = empty
86
87 -- | Join two docstrings.
88 --
89 -- Non-empty docstrings are joined with two newlines in between,
90 -- resulting in separate paragraphs.
91 appendDocs :: HsDocString -> HsDocString -> HsDocString
92 appendDocs x y =
93 fromMaybe
94 (HsDocString BS.empty)
95 (concatDocs [x, y])
96
97 -- | Concat docstrings with two newlines in between.
98 --
99 -- Empty docstrings are skipped.
100 --
101 -- If all inputs are empty, 'Nothing' is returned.
102 concatDocs :: [HsDocString] -> Maybe HsDocString
103 concatDocs xs =
104 if BS.null b
105 then Nothing
106 else Just (HsDocString b)
107 where
108 b = BS.intercalate (C8.pack "\n\n")
109 . filter (not . BS.null)
110 . map hsDocStringToByteString
111 $ xs
112
113 -- | Docs for declarations: functions, data types, instances, methods etc.
114 newtype DeclDocMap = DeclDocMap (Map Name HsDocString)
115
116 instance Binary DeclDocMap where
117 put_ bh (DeclDocMap m) = put_ bh (Map.toList m)
118 -- We can't rely on a deterministic ordering of the `Name`s here.
119 -- See the comments on `Name`'s `Ord` instance for context.
120 get bh = DeclDocMap . Map.fromList <$> get bh
121
122 instance Outputable DeclDocMap where
123 ppr (DeclDocMap m) = vcat (map pprPair (Map.toAscList m))
124 where
125 pprPair (name, doc) = ppr name Outputable.<> colon $$ nest 2 (ppr doc)
126
127 emptyDeclDocMap :: DeclDocMap
128 emptyDeclDocMap = DeclDocMap Map.empty
129
130 -- | Docs for arguments. E.g. function arguments, method arguments.
131 newtype ArgDocMap = ArgDocMap (Map Name (IntMap HsDocString))
132
133 instance Binary ArgDocMap where
134 put_ bh (ArgDocMap m) = put_ bh (Map.toList (IntMap.toAscList <$> m))
135 -- We can't rely on a deterministic ordering of the `Name`s here.
136 -- See the comments on `Name`'s `Ord` instance for context.
137 get bh = ArgDocMap . fmap IntMap.fromDistinctAscList . Map.fromList <$> get bh
138
139 instance Outputable ArgDocMap where
140 ppr (ArgDocMap m) = vcat (map pprPair (Map.toAscList m))
141 where
142 pprPair (name, int_map) =
143 ppr name Outputable.<> colon $$ nest 2 (pprIntMap int_map)
144 pprIntMap im = vcat (map pprIPair (IntMap.toAscList im))
145 pprIPair (i, doc) = ppr i Outputable.<> colon $$ nest 2 (ppr doc)
146
147 emptyArgDocMap :: ArgDocMap
148 emptyArgDocMap = ArgDocMap Map.empty
149
150 -- | Maps of docs that were added via Template Haskell's @putDoc@.
151 data ExtractedTHDocs =
152 ExtractedTHDocs
153 { ethd_mod_header :: Maybe HsDocString
154 -- ^ The added module header documentation, if it exists.
155 , ethd_decl_docs :: DeclDocMap
156 -- ^ The documentation added to declarations.
157 , ethd_arg_docs :: ArgDocMap
158 -- ^ The documentation added to function arguments.
159 , ethd_inst_docs :: DeclDocMap
160 -- ^ The documentation added to class and family instances.
161 }