aboutsummaryrefslogtreecommitdiff
path: root/src/Haddock/Backends/Xhtml/Names.hs
blob: 1bd2cbc46ee2bdd68b87f209a88a75dce0a09f6e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
-----------------------------------------------------------------------------
-- |
-- Module      :  Haddock.Backends.Html.Names
-- Copyright   :  (c) Simon Marlow   2003-2006,
--                    David Waern    2006-2009,
--                    Mark Lentczner 2010
-- License     :  BSD-like
--
-- Maintainer  :  haddock@projects.haskell.org
-- Stability   :  experimental
-- Portability :  portable
-----------------------------------------------------------------------------
module Haddock.Backends.Xhtml.Names (
  ppName, ppDocName, ppLDocName, ppRdrName, ppUncheckedLink,
  ppBinder, ppBinderInfix, ppBinder',
  ppModule, ppModuleRef,
  ppIPName,
  linkId
) where


import Haddock.Backends.Xhtml.Utils
import Haddock.GhcUtils
import Haddock.Types
import Haddock.Utils

import Text.XHtml hiding ( name, title, p, quote )
import qualified Data.Map as M
import qualified Data.List as List

import GHC
import Name
import RdrName
import FastString (unpackFS)


ppOccName :: OccName -> Html
ppOccName = toHtml . occNameString


ppRdrName :: RdrName -> Html
ppRdrName = ppOccName . rdrNameOcc

ppIPName :: HsIPName -> Html
ppIPName = toHtml . unpackFS . hsIPNameFS


ppUncheckedLink :: Qualification -> (ModuleName, OccName) -> Html
ppUncheckedLink _ (mdl, occ) = linkIdOcc' mdl (Just occ) << ppOccName occ -- TODO: apply ppQualifyName


-- The Bool indicates if it is to be rendered in infix notation
ppLDocName :: Qualification -> Maybe Bool -> Located DocName -> Html
ppLDocName qual is_infix (L _ d) = ppDocName qual is_infix d


-- The Bool indicates if it is to be rendered in infix notation
-- Nothing means print it raw, i.e. don't force it to either infix or prefix
-- TODO: instead of Maybe Bool, add a bespoke datatype
ppDocName :: Qualification -> Maybe Bool -> DocName -> Html
ppDocName qual is_infix docName =
  case docName of
    Documented name mdl ->
      linkIdOcc mdl (Just (nameOccName name)) << ppQualifyName qual is_infix name mdl
    Undocumented name
      | isExternalName name || isWiredInName name ->
          ppQualifyName qual is_infix name (nameModule name)
      | otherwise -> ppName is_infix name


-- | Render a name depending on the selected qualification mode
ppQualifyName :: Qualification -> Maybe Bool -> Name -> Module -> Html
ppQualifyName qual is_infix name mdl =
  case qual of
    NoQual   -> ppName is_infix name
    FullQual -> ppFullQualName is_infix mdl name
    LocalQual localmdl ->
      if moduleString mdl == moduleString localmdl
        then ppName is_infix name
        else ppFullQualName is_infix mdl name
    RelativeQual localmdl ->
      case List.stripPrefix (moduleString localmdl) (moduleString mdl) of
        -- local, A.x -> x
        Just []      -> ppName is_infix name
        -- sub-module, A.B.x -> B.x
        Just ('.':m) -> toHtml $ m ++ '.' : getOccString name
        -- some module with same prefix, ABC.x -> ABC.x
        Just _       -> ppFullQualName is_infix mdl name
        -- some other module, D.x -> D.x
        Nothing      -> ppFullQualName is_infix mdl name
    AliasedQual aliases localmdl ->
      case (moduleString mdl == moduleString localmdl,
            M.lookup mdl aliases) of
        (False, Just alias) -> ppQualName is_infix alias name
        _ -> ppName is_infix name


ppFullQualName :: Maybe Bool -> Module -> Name -> Html
ppFullQualName is_infix mdl name = wrapInfix is_infix (getOccName name) qname
  where
    qname = toHtml $ moduleString mdl ++ '.' : getOccString name

ppQualName :: Maybe Bool -> ModuleName -> Name -> Html
ppQualName is_infix mdlName name = wrapInfix is_infix (getOccName name) qname
  where
    qname = toHtml $ moduleNameString mdlName ++ '.' : getOccString name

ppName :: Maybe Bool -> Name -> Html
ppName is_infix name = wrapInfix is_infix (getOccName name) $ toHtml (getOccString name)


ppBinder :: Bool -> OccName -> Html
-- The Bool indicates whether we are generating the summary, in which case
-- the binder will be a link to the full definition.
ppBinder True n = linkedAnchor (nameAnchorId n) << ppBinder' False n
ppBinder False n = namedAnchor (nameAnchorId n) ! [theclass "def"]
                        << ppBinder' False n

ppBinderInfix :: Bool -> OccName -> Html
ppBinderInfix True n = linkedAnchor (nameAnchorId n) << ppBinder' True n
ppBinderInfix False n = namedAnchor (nameAnchorId n) ! [theclass "def"]
                             << ppBinder' True n

ppBinder' :: Bool -> OccName -> Html
-- The Bool indicates if it is to be rendered in infix notation
ppBinder' is_infix n = wrapInfix (Just is_infix) n $ ppOccName n

wrapInfix :: Maybe Bool -> OccName -> Html -> Html
wrapInfix Nothing _ = id
wrapInfix (Just is_infix) n | is_star_kind = id
                            | is_infix && not is_sym = quote
                            | not is_infix && is_sym = parens
                            | otherwise = id
  where
    is_sym = isSymOcc n
    is_star_kind = isTcOcc n && occNameString n == "*"

linkId :: Module -> Maybe Name -> Html -> Html
linkId mdl mbName = linkIdOcc mdl (fmap nameOccName mbName)


linkIdOcc :: Module -> Maybe OccName -> Html -> Html
linkIdOcc mdl mbName = anchor ! [href url]
  where
    url = case mbName of
      Nothing   -> moduleUrl mdl
      Just name -> moduleNameUrl mdl name


linkIdOcc' :: ModuleName -> Maybe OccName -> Html -> Html
linkIdOcc' mdl mbName = anchor ! [href url]
  where
    url = case mbName of
      Nothing   -> moduleHtmlFile' mdl
      Just name -> moduleNameUrl' mdl name


ppModule :: Module -> Html
ppModule mdl = anchor ! [href (moduleUrl mdl)]
               << toHtml (moduleString mdl)


ppModuleRef :: ModuleName -> String -> Html
ppModuleRef mdl ref = anchor ! [href (moduleHtmlFile' mdl ++ ref)]
                      << toHtml (moduleNameString mdl)
    -- NB: The ref parameter already includes the '#'.
    -- This function is only called from markupModule expanding a
    -- DocModule, which doesn't seem to be ever be used.