Skip to content

Commit 956e11d

Browse files
serrascocreature
andcommitted
Enhancements to Haddock -> Markdown conversion (#344)
* Enhancements to Haddock -> Markdown conversion * Add tests for Haddock -> Markdown conversion * Make HLint happy * Let Haddock tests compile also in 8.4 * Fix build for 8.4 * Fix test for haddock-library 1.8.0 * Fix CPP problem * Make tests a bit more readable Co-authored-by: Moritz Kiefer <[email protected]>
1 parent ea50c27 commit 956e11d

File tree

3 files changed

+82
-8
lines changed

3 files changed

+82
-8
lines changed

ghcide.cabal

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ library
112112
Development.IDE.LSP.LanguageServer
113113
Development.IDE.LSP.Protocol
114114
Development.IDE.LSP.Server
115+
Development.IDE.Spans.Common
115116
Development.IDE.Types.Diagnostics
116117
Development.IDE.Types.Location
117118
Development.IDE.Types.Logger
@@ -134,7 +135,6 @@ library
134135
Development.IDE.LSP.Outline
135136
Development.IDE.Spans.AtPoint
136137
Development.IDE.Spans.Calculate
137-
Development.IDE.Spans.Common
138138
Development.IDE.Spans.Documentation
139139
Development.IDE.Spans.Type
140140
Development.IDE.Plugin.Completions.Logic
@@ -217,6 +217,7 @@ test-suite ghcide-tests
217217
--------------------------------------------------------------
218218
ghcide,
219219
ghc-typelits-knownnat,
220+
haddock-library,
220221
haskell-lsp-types,
221222
lens,
222223
lsp-test >= 0.8,

src/Development/IDE/Spans/Common.hs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module Development.IDE.Spans.Common (
1212
, SpanDoc(..)
1313
, emptySpanDoc
1414
, spanDocToMarkdown
15+
, spanDocToMarkdownForTest
1516
) where
1617

1718
import Data.Data
@@ -27,11 +28,9 @@ import DataCon
2728
import Var
2829
#endif
2930

30-
#if MIN_GHC_API_VERSION(8,6,0)
3131
import Data.Char (isSpace)
3232
import qualified Documentation.Haddock.Parser as H
3333
import qualified Documentation.Haddock.Types as H
34-
#endif
3534

3635
showGhc :: Outputable a => a -> String
3736
showGhc = showPpr unsafeGlobalDynFlags
@@ -81,15 +80,22 @@ spanDocToMarkdown (SpanDocString _)
8180
#endif
8281
spanDocToMarkdown (SpanDocText txt) = txt
8382

84-
#if MIN_GHC_API_VERSION(8,6,0)
83+
spanDocToMarkdownForTest :: String -> String
84+
spanDocToMarkdownForTest
85+
#if MIN_VERSION_haddock_library(1,6,0)
86+
= haddockToMarkdown . H.toRegular . H._doc . H.parseParas Nothing
87+
#else
88+
= haddockToMarkdown . H.toRegular . H._doc . H.parseParas
89+
#endif
90+
8591
-- Simple (and a bit hacky) conversion from Haddock markup to Markdown
8692
haddockToMarkdown
8793
:: H.DocH String String -> String
8894

8995
haddockToMarkdown H.DocEmpty
9096
= ""
9197
haddockToMarkdown (H.DocAppend d1 d2)
92-
= haddockToMarkdown d1 Prelude.<> haddockToMarkdown d2
98+
= haddockToMarkdown d1 ++ " " ++ haddockToMarkdown d2
9399
haddockToMarkdown (H.DocString s)
94100
= s
95101
haddockToMarkdown (H.DocParagraph p)
@@ -138,9 +144,9 @@ haddockToMarkdown (H.DocHeader (H.Header level title))
138144
= replicate level '#' ++ " " ++ haddockToMarkdown title
139145

140146
haddockToMarkdown (H.DocUnorderedList things)
141-
= '\n' : (unlines $ map (\thing -> "+ " ++ dropWhile isSpace (haddockToMarkdown thing)) things)
147+
= '\n' : (unlines $ map (("+ " ++) . dropWhile isSpace . splitForList . haddockToMarkdown) things)
142148
haddockToMarkdown (H.DocOrderedList things)
143-
= '\n' : (unlines $ map (\thing -> "1. " ++ dropWhile isSpace (haddockToMarkdown thing)) things)
149+
= '\n' : (unlines $ map (("1. " ++) . dropWhile isSpace . splitForList . haddockToMarkdown) things)
144150
haddockToMarkdown (H.DocDefList things)
145151
= '\n' : (unlines $ map (\(term, defn) -> "+ **" ++ haddockToMarkdown term ++ "**: " ++ haddockToMarkdown defn) things)
146152

@@ -157,4 +163,9 @@ haddockToMarkdown (H.DocTable _t)
157163
-- things I don't really know how to handle
158164
haddockToMarkdown (H.DocProperty _)
159165
= "" -- don't really know what to do
160-
#endif
166+
167+
splitForList :: String -> String
168+
splitForList s
169+
= case lines s of
170+
[] -> ""
171+
(first:rest) -> unlines $ first : map ((" " ++) . dropWhile isSpace) rest

test/exe/Main.hs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import Data.Foldable
1717
import Data.List
1818
import Development.IDE.GHC.Util
1919
import qualified Data.Text as T
20+
import Development.IDE.Spans.Common
2021
import Development.IDE.Test
2122
import Development.IDE.Test.Runfiles
2223
import Development.IDE.Types.Location
@@ -53,6 +54,7 @@ main = defaultMain $ testGroup "HIE"
5354
, preprocessorTests
5455
, thTests
5556
, unitTests
57+
, haddockTests
5658
]
5759

5860
initializeResponseTests :: TestTree
@@ -1638,6 +1640,66 @@ data Expect
16381640

16391641
mkR :: Int -> Int -> Int -> Int -> Expect
16401642
mkR startLine startColumn endLine endColumn = ExpectRange $ mkRange startLine startColumn endLine endColumn
1643+
1644+
haddockTests :: TestTree
1645+
haddockTests
1646+
= testGroup "haddock"
1647+
[ testCase "Num" $ checkHaddock
1648+
(unlines
1649+
[ "However, '(+)' and '(*)' are"
1650+
, "customarily expected to define a ring and have the following properties:"
1651+
, ""
1652+
, "[__Associativity of (+)__]: @(x + y) + z@ = @x + (y + z)@"
1653+
, "[__Commutativity of (+)__]: @x + y@ = @y + x@"
1654+
, "[__@fromInteger 0@ is the additive identity__]: @x + fromInteger 0@ = @x@"
1655+
]
1656+
)
1657+
(unlines
1658+
[ ""
1659+
, ""
1660+
#if MIN_VERSION_haddock_library(1,8,0)
1661+
, "However, `(+)` and `(*)` are"
1662+
#else
1663+
, "However, '(+)' and '(*)' are"
1664+
#endif
1665+
, "customarily expected to define a ring and have the following properties: "
1666+
, "+ ****Associativity of (+)****: `(x + y) + z` = `x + (y + z)`"
1667+
, "+ ****Commutativity of (+)****: `x + y` = `y + x`"
1668+
, "+ ****`fromInteger 0` is the additive identity****: `x + fromInteger 0` = `x`"
1669+
]
1670+
)
1671+
, testCase "unsafePerformIO" $ checkHaddock
1672+
(unlines
1673+
[ "may require"
1674+
, "different precautions:"
1675+
, ""
1676+
, " * Use @{\\-\\# NOINLINE foo \\#-\\}@ as a pragma on any function @foo@"
1677+
, " that calls 'unsafePerformIO'. If the call is inlined,"
1678+
, " the I\\/O may be performed more than once."
1679+
, ""
1680+
, " * Use the compiler flag @-fno-cse@ to prevent common sub-expression"
1681+
, " elimination being performed on the module."
1682+
, ""
1683+
]
1684+
)
1685+
(unlines
1686+
[ ""
1687+
, ""
1688+
, "may require"
1689+
, "different precautions: "
1690+
, "+ Use `{-# NOINLINE foo #-}` as a pragma on any function `foo` "
1691+
, " that calls `unsafePerformIO` . If the call is inlined,"
1692+
, " the I/O may be performed more than once."
1693+
, ""
1694+
, "+ Use the compiler flag `-fno-cse` to prevent common sub-expression"
1695+
, " elimination being performed on the module."
1696+
, ""
1697+
]
1698+
)
1699+
]
1700+
where
1701+
checkHaddock s txt = spanDocToMarkdownForTest s @?= txt
1702+
16411703
----------------------------------------------------------------------
16421704
-- Utils
16431705

0 commit comments

Comments
 (0)