@@ -7,7 +7,7 @@
7-- | Rendering of declarations.
7-- | Rendering of declarations.
8module Ormolu.Printer.Meat.Declaration
8module Ormolu.Printer.Meat.Declaration
9 ( p_hsDecls,
9 ( p_hsDecls,
10− hasSeparatedDecls,
10+ p_hsDeclsRespectGrouping,
@@ -36,18 +36,52 @@ import Ormolu.Printer.Meat.Type
36import Ormolu.Utils
36import Ormolu.Utils
37import RdrName (rdrNameOcc)
37import RdrName (rdrNameOcc)
40+ = -- | Always put newlines where we think they should be
42+ | -- | Respect user preferences regarding grouping
39p_hsDecls :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
46p_hsDecls :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
47+p_hsDecls = p_hsDecls' Disregard
49+-- | Like 'p_hsDecls' but respects user choices regarding grouping. If the
50+-- user omits newlines between declarations, we also omit them in most
51+-- cases, except when said declarations have associated Haddocks.
53+-- Does some normalization (compress subsequent newlines into a single one)
54+p_hsDeclsRespectGrouping :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
55+p_hsDeclsRespectGrouping = p_hsDecls' Respect
57+p_hsDecls' :: UserGrouping -> FamilyStyle -> [LHsDecl GhcPs] -> R ()
40−p_hsDecls style decls = sepSemi id $
58+p_hsDecls' grouping style decls = sepSemi id $
41 -- Return a list of rendered declarations, adding a newline to separate
59 -- Return a list of rendered declarations, adding a newline to separate
42 -- groups.
60 -- groups.
43 case groupDecls decls of
61 case groupDecls decls of
45− (x : xs) ->
63+ (x : xs) -> renderGroup x ++ concat (zipWith renderGroupWithPrev (x : xs) xs)
46− NE.toList (renderGroup x)
47− ++ concatMap (NE.toList . separateGroup . renderGroup) xs
49− renderGroup = fmap (located' $ dontUseBraces . p_hsDecl style)
65+ renderGroup = NE.toList . fmap (located' $ dontUseBraces . p_hsDecl style)
50− separateGroup (x :| xs) = (breakpoint' >> x) :| xs
66+ renderGroupWithPrev prev curr =
67+ -- We can omit a blank line when the user didn't add one, but we must
68+ -- ensure we always add blank lines around documented declarations
70+ [ grouping == Disregard,
71+ separatedByBlank getLoc prev curr,
75+ then breakpoint : renderGroup curr
76+ else renderGroup curr
78+-- | Is a declaration group documented?
79+isDocumented :: NonEmpty (LHsDecl GhcPs) -> Bool
80+isDocumented = any (isHaddock . unLoc)
82+ isHaddock DocNext = True
83+ isHaddock DocPrev = True
52-- | Group relevant declarations together.
86-- | Group relevant declarations together.
@@ -139,6 +173,9 @@ groupedDecls ::
139 HsDecl GhcPs ->
173 HsDecl GhcPs ->
141groupedDecls (TypeSignature ns) (FunctionBody ns') = ns `intersects` ns'
175groupedDecls (TypeSignature ns) (FunctionBody ns') = ns `intersects` ns'
176+groupedDecls (TypeSignature ns) (DefaultSignature ns') = ns `intersects` ns'
177+groupedDecls (DefaultSignature ns) (TypeSignature ns') = ns `intersects` ns'
178+groupedDecls (DefaultSignature ns) (FunctionBody ns') = ns `intersects` ns'
142groupedDecls x (FunctionBody ns) | Just ns' <- isPragma x = ns `intersects` ns'
179groupedDecls x (FunctionBody ns) | Just ns' <- isPragma x = ns `intersects` ns'
143groupedDecls (FunctionBody ns) x | Just ns' <- isPragma x = ns `intersects` ns'
180groupedDecls (FunctionBody ns) x | Just ns' <- isPragma x = ns `intersects` ns'
144groupedDecls x (DataDeclaration n) | Just ns <- isPragma x = n `elem` ns
181groupedDecls x (DataDeclaration n) | Just ns <- isPragma x = n `elem` ns
@@ -149,6 +186,7 @@ groupedDecls x y | Just ns <- isPragma x, Just ns' <- isPragma y = ns `intersect
149groupedDecls x (TypeSignature ns) | Just ns' <- isPragma x = ns `intersects` ns'
186groupedDecls x (TypeSignature ns) | Just ns' <- isPragma x = ns `intersects` ns'
150groupedDecls (TypeSignature ns) x | Just ns' <- isPragma x = ns `intersects` ns'
187groupedDecls (TypeSignature ns) x | Just ns' <- isPragma x = ns `intersects` ns'
151groupedDecls (PatternSignature ns) (Pattern n) = n `elem` ns
188groupedDecls (PatternSignature ns) (Pattern n) = n `elem` ns
189+-- This looks only at Haddocks, normal comments are handled elsewhere
152groupedDecls DocNext _ = True
190groupedDecls DocNext _ = True
153groupedDecls _ DocPrev = True
191groupedDecls _ DocPrev = True
154groupedDecls _ _ = False
192groupedDecls _ _ = False
@@ -164,13 +202,6 @@ intersects a b = go (sort a) (sort b)
164 | x > y = go (x : xs) ys
202 | x > y = go (x : xs) ys
165 | otherwise = True
203 | otherwise = True
167−-- | Checks if given list of declarations contain a pair which should
168−-- be separated by a blank line.
169−hasSeparatedDecls :: [LHsDecl GhcPs] -> Bool
170−hasSeparatedDecls xs = case groupDecls xs of
174isPragma ::
205isPragma ::
175 HsDecl GhcPs ->
206 HsDecl GhcPs ->
176 Maybe [RdrName]
207 Maybe [RdrName]
@@ -206,11 +237,13 @@ pattern DataDeclaration n <- TyClD NoExt (DataDecl NoExt (L _ n) _ _ _)
208 TypeSignature,
239 TypeSignature,
209 FunctionBody,
241 FunctionBody,
210 PatternSignature,
242 PatternSignature,
211 WarningPragma ::
243 WarningPragma ::
212 [RdrName] -> HsDecl GhcPs
244 [RdrName] -> HsDecl GhcPs
213pattern TypeSignature n <- (sigRdrNames -> Just n)
245pattern TypeSignature n <- (sigRdrNames -> Just n)
246+pattern DefaultSignature n <- (defSigRdrNames -> Just n)
214pattern FunctionBody n <- (funRdrNames -> Just n)
247pattern FunctionBody n <- (funRdrNames -> Just n)
215pattern PatternSignature n <- (patSigRdrNames -> Just n)
248pattern PatternSignature n <- (patSigRdrNames -> Just n)
216pattern WarningPragma n <- (warnSigRdrNames -> Just n)
249pattern WarningPragma n <- (warnSigRdrNames -> Just n)
@@ -225,6 +258,10 @@ sigRdrNames (SigD NoExt (ClassOpSig NoExt _ ns _)) = Just $ map unLoc ns
225sigRdrNames (SigD NoExt (PatSynSig NoExt ns _)) = Just $ map unLoc ns
258sigRdrNames (SigD NoExt (PatSynSig NoExt ns _)) = Just $ map unLoc ns
226sigRdrNames _ = Nothing
259sigRdrNames _ = Nothing
261+defSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
262+defSigRdrNames (SigD NoExt (ClassOpSig NoExt True ns _)) = Just $ map unLoc ns
263+defSigRdrNames _ = Nothing
228funRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
265funRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
229funRdrNames (ValD NoExt (FunBind NoExt (L _ n) _ _ _)) = Just [n]
266funRdrNames (ValD NoExt (FunBind NoExt (L _ n) _ _ _)) = Just [n]
230funRdrNames (ValD NoExt (PatBind NoExt n _ _)) = Just $ patBindNames n
267funRdrNames (ValD NoExt (PatBind NoExt n _ _)) = Just $ patBindNames n