brittany/source/library/Language/Haskell/Brittany/Internal/ToBriDoc/Expr.hs

1273 lines
49 KiB
Haskell

{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MonadComprehensions #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Language.Haskell.Brittany.Internal.ToBriDoc.Expr where
import qualified Data.Sequence as Seq
import qualified Data.Text as Text
import GHC (GenLocated(L), RdrName(..))
import qualified GHC.Data.FastString as FastString
import GHC.Types.SourceText
(IntegralLit(IL), FractionalLit(FL), SourceText(SourceText))
import GHC.Hs
import qualified GHC.Types.SrcLoc as GHC
import qualified GHC.OldList as List
import GHC.Types.Basic
import GHC.Types.Name
import Language.Haskell.Brittany.Internal.Config.Types
import Language.Haskell.Brittany.Internal.S3_ToBriDocTools
import Language.Haskell.Brittany.Internal.ToBriDoc.Decl
import Language.Haskell.Brittany.Internal.ToBriDoc.Pattern
import {-# SOURCE #-} Language.Haskell.Brittany.Internal.ToBriDoc.Stmt
import Language.Haskell.Brittany.Internal.ToBriDoc.Type
import Language.Haskell.Brittany.Internal.Prelude
import Language.Haskell.Brittany.Internal.Types
import Language.Haskell.Brittany.Internal.Utils
import Language.Haskell.Brittany.Internal.Components.BriDoc
layoutExpr :: ToBriDoc HsExpr
layoutExpr lexpr@(L _ expr) = do
indentPolicy <- mAsk <&> _conf_layout .> _lconfig_indentPolicy .> confUnpack
let allowFreeIndent = indentPolicy == IndentPolicyFree
docHandleComms lexpr $ case expr of
HsVar NoExtField vname -> docHandleComms lexpr $ do
docLit =<< lrdrNameToTextAnn vname
HsUnboundVar epAnn oname -> docHandleComms epAnn $ do
docLit $ Text.pack $ occNameString oname
HsRecFld{} -> docHandleComms lexpr $ do
-- TODO
briDocByExactInlineOnly "HsRecFld" lexpr
HsOverLabel _ext name -> -- TODO92
let label = FastString.unpackFS name in docLit . Text.pack $ '#' : label
HsIPVar _ext (HsIPName name) -> -- TODO92
let label = FastString.unpackFS name in docLit . Text.pack $ '?' : label
HsOverLit epAnn olit -> docHandleComms epAnn $ do
allocateNode $ overLitValBriDoc $ ol_val olit
HsLit epAnn lit -> docHandleComms epAnn $ do
allocateNode $ litBriDoc lit
HsLam _ (MG _ (L _ [(L _ match)]) _)
| pats <- m_pats match
, GRHSs _ [lgrhs] llocals <- m_grhss match
, EmptyLocalBinds{} <- llocals
, L _ (GRHS epAnn [] body) <- lgrhs
-> do
patDocs <- zip (True : repeat False) pats `forM` \(isFirst, p) ->
fmap return $ do
-- this code could be as simple as `colsWrapPat =<< layoutPat p`
-- if it was not for the following two cases:
-- \ !x -> x
-- \ ~x -> x
-- These make it necessary to special-case an additional separator.
-- (TODO: we create a BDCols here, but then make it ineffective
-- by wrapping it in docSeq below. We _could_ add alignments for
-- stuff like lists-of-lambdas. Nothing terribly important..)
let
shouldPrefixSeparator = case p of
L _ LazyPat{} -> isFirst
L _ BangPat{} -> isFirst
_ -> False
patDocSeq <- layoutPat p
fixed <- case Seq.viewl patDocSeq of
p1 Seq.:< pr | shouldPrefixSeparator -> do
p1' <- docSeq [docSeparator, pure p1]
pure (p1' Seq.<| pr)
_ -> pure patDocSeq
colsWrapPat fixed
bodyDoc <- shareDoc
$ docAddBaseY BrIndentRegular
$ docHandleComms epAnn $ layoutExpr body
let
funcPatternPartLine = docCols
ColCasePattern
(patDocs <&> (\p -> docSeq [docForceSingleline p, docSeparator]))
docAlt
[ -- single line
docSeq
[ docLit $ Text.pack "\\"
, docForceSingleline funcPatternPartLine
, appSep $ docLit $ Text.pack "->"
, docForceSingleline bodyDoc
]
-- double line
, docSetParSpacing $ docAddBaseY BrIndentRegular $ docPar
(docSeq
[ docLit $ Text.pack "\\"
, appSep $ docForceSingleline
funcPatternPartLine
, docLit $ Text.pack "->"
]
)
(docForceSingleline bodyDoc)
-- wrapped par spacing
, docSetParSpacing $ docSeq
[ docLit $ Text.pack "\\"
, docForceSingleline funcPatternPartLine
, appSep $ docLit $ Text.pack "->"
, docForceParSpacing bodyDoc
]
-- conservative
, docSetParSpacing $ docAddBaseY BrIndentRegular $ docPar
(docSeq
[ docLit $ Text.pack "\\"
, appSep $ docForceSingleline
funcPatternPartLine
, docLit $ Text.pack "->"
]
)
(docNonBottomSpacing bodyDoc)
]
HsLam{} -> unknownNodeError "HsLam too complex" lexpr
HsLamCase _ (MG _ (L _ []) _) -> do
docSetParSpacing
$ docAddBaseY BrIndentRegular
$ (docLit $ Text.pack "\\case {}")
HsLamCase _ (MG _ _lmatches@(L _ matches) _) -> do
binderDoc <- docLit $ Text.pack "->"
funcPatDocs <-
-- docWrapNode lmatches
layoutPatternBind Nothing binderDoc
`mapM` matches
docSetParSpacing $ docAddBaseY BrIndentRegular $ docPar
(docLit $ Text.pack "\\case")
(docSetBaseAndIndent
$ docNonBottomSpacing
$ docLines
$ return
<$> funcPatDocs
)
HsApp _ exp1 _ -> do
let gather
:: [(EpAnnCO, LHsExpr GhcPs)]
-> LHsExpr GhcPs
-> (LHsExpr GhcPs, [(EpAnnCO, LHsExpr GhcPs)])
gather list = \case
L _ (HsApp epAnn l r) -> gather ((epAnn, r) : list) l
x -> (x, list)
let (headE, paramEs) = gather [] lexpr
let colsOrSequence = case headE of
L _ (HsVar _ (L _ (Unqual occname))) ->
docCols (ColApp $ Text.pack $ occNameString occname)
_ -> docSeq
headDoc <- shareDoc $ layoutExpr headE
paramDocs <- forM paramEs $ \(epAnn, e) ->
shareDoc $ docHandleComms epAnn $ layoutExpr e
let hasComments = hasAnyCommentsConnected exp1
runFilteredAlternative $ do
-- foo x y
addAlternativeCond (not hasComments)
$ colsOrSequence
$ appSep (docForceSingleline headDoc)
: spacifyDocs (docForceSingleline <$> paramDocs)
-- foo x do
-- a
-- b
-- foo x \meow -> do
-- a
-- b
addAlternativeCond (not hasComments) $ docSetParSpacing $ docSeq
[ appSep (docForceSingleline headDoc)
, case splitFirstLast paramDocs of
FirstLastEmpty -> docEmpty
FirstLastSingleton e1 -> docForceParSpacing e1
FirstLast e1 ems eN ->
docSeq
( spacifyDocs (docForceSingleline <$> (e1:ems))
++ [docSeparator, docForceParSpacing eN]
)
]
-- foo x
-- y
addAlternativeCond allowFreeIndent $ docSeq
[ appSep (docForceSingleline headDoc)
, docSetBaseY
$ docAddBaseY BrIndentRegular
$ docLines
$ docForceSingleline
<$> paramDocs
]
-- foo
-- x
-- y
addAlternative $ do
let checkAllowPar = \case
(_, L _ ExplicitTuple{}) -> True
(_, L _ ExplicitList{}) -> True
(_, L _ HsPar{}) -> True
_ -> False
let wrap = if all checkAllowPar paramEs then docSetParSpacing else id
wrap $ docAddBaseY BrIndentRegular $ docPar
(docForceSingleline headDoc)
(docNonBottomSpacing $ docLines paramDocs)
-- ( multi
-- line
-- function
-- )
-- x
-- y
addAlternative $ docAddBaseY BrIndentRegular $ docPar
headDoc
(docNonBottomSpacing $ docLines paramDocs)
HsAppType _ exp1 (HsWC _ ty1) -> do
t <- shareDoc $ layoutType ty1
e <- shareDoc $ layoutExpr exp1
docAlt
[ docSeq
[ docForceSingleline e
, docSeparator
, docLit $ Text.pack "@"
, docForceSingleline t
]
, docPar e (docSeq [docLit $ Text.pack "@", t])
]
OpApp _topEpAnn expLeft@(L _ OpApp{}) expOp expRight -> do
let
allowPar = case (expOp, expRight) of
(L _ (HsVar _ (L _ (Unqual occname))), _)
| occNameString occname == "$" -> True
(_, L _ (HsApp _ _ (L _ HsVar{}))) -> False
_ -> True
let
gather
:: Bool
-> [(ToBriDocM BriDocNumbered, ToBriDocM BriDocNumbered, Bool)]
-> LHsExpr GhcPs
-> ( ToBriDocM BriDocNumbered
, [(ToBriDocM BriDocNumbered, ToBriDocM BriDocNumbered, Bool)]
)
gather last opExprList = \case
(L _ (OpApp epAnn l1 op1 r1)) ->
gather
False
( ( docHandleComms epAnn $ layoutExpr op1
, layoutExpr r1
, last
)
: opExprList
)
l1
final -> (layoutExpr final, opExprList)
(leftOperand, appList) = gather True [] lexpr
leftOperandDoc <- shareDoc leftOperand
appListDocs <- appList `forM` \(x, y, last) ->
[ (xD, yD, last)
| xD <- shareDoc x
, yD <- shareDoc y
]
let allowSinglelinePar = not (hasAnyCommentsConnected expLeft)
&& not (hasAnyCommentsConnected expOp)
runFilteredAlternative $ do
-- > one + two + three
-- or
-- > one + two + case x of
-- > _ -> three
addAlternativeCond allowSinglelinePar $ docSeq
[ appSep $ docForceSingleline leftOperandDoc
, docSeq $ appListDocs <&> \(od, ed, last) -> docSeq
[ appSep $ docForceSingleline od
, if last
then if allowPar
then docForceParSpacing ed
else docForceSingleline ed
else appSep $ docForceSingleline ed
]
]
-- this case rather leads to some unfortunate layouting than to anything
-- useful; disabling for now. (it interfers with cols stuff.)
-- addAlternative
-- $ docSetBaseY
-- $ docPar
-- leftOperandDoc
-- ( docLines
-- $ (appListDocs <&> \(od, ed) -> docCols ColOpPrefix [appSep od, docSetBaseY ed])
-- ++ [docCols ColOpPrefix [appSep opLastDoc, docSetBaseY expLastDoc]]
-- )
-- > one
-- > + two
-- > + three
addAlternative $ docPar
leftOperandDoc
(docLines $ appListDocs <&> \(od, ed, _) ->
docCols ColOpPrefix [appSep od, docSetBaseY ed]
)
OpApp epAnn expLeft expOp expRight -> docHandleComms epAnn $ do
expDocLeft <- shareDoc $ layoutExpr expLeft
expDocOp <- shareDoc $ layoutExpr expOp
expDocRight <- shareDoc $ layoutExpr expRight
let
allowPar = case (expOp, expRight) of
(L _ (HsVar _ (L _ (Unqual occname))), _)
| occNameString occname == "$" -> True
(_, L _ (HsApp _ _ (L _ HsVar{}))) -> False
_ -> True
let
leftIsDoBlock = case expLeft of
L _ HsDo{} -> True
_ -> False
runFilteredAlternative $ do
-- one-line
addAlternative $ docSeq
[ appSep $ docForceSingleline expDocLeft
, appSep $ docForceSingleline expDocOp
, docForceSingleline expDocRight
]
-- -- line + freely indented block for right expression
-- addAlternative
-- $ docSeq
-- [ appSep $ docForceSingleline expDocLeft
-- , appSep $ docForceSingleline expDocOp
-- , docSetBaseY $ docAddBaseY BrIndentRegular expDocRight
-- ]
-- two-line
addAlternative $ do
let
expDocOpAndRight = docForceSingleline $ docCols
ColOpPrefix
[appSep $ expDocOp, docSetBaseY expDocRight]
if leftIsDoBlock
then docLines [expDocLeft, expDocOpAndRight]
else docAddBaseY BrIndentRegular
$ docPar expDocLeft expDocOpAndRight
-- TODO: in both cases, we don't force expDocLeft to be
-- single-line, which has certain.. interesting consequences.
-- At least, the "two-line" label is not entirely
-- accurate.
-- one-line + par
addAlternativeCond allowPar $ docSeq
[ appSep $ docForceSingleline expDocLeft
, appSep $ docForceSingleline expDocOp
, docForceParSpacing expDocRight
]
-- more lines
addAlternative $ do
let
expDocOpAndRight =
docCols ColOpPrefix [appSep expDocOp, docSetBaseY expDocRight]
if leftIsDoBlock
then docLines [expDocLeft, expDocOpAndRight]
else docAddBaseY BrIndentRegular
$ docPar expDocLeft expDocOpAndRight
NegApp _ op _ -> do
opDoc <- shareDoc $ layoutExpr op
docSeq [docLit $ Text.pack "-", opDoc]
HsPar epAnn innerExp -> docHandleComms epAnn $ do
let AnnParen _ spanOpen spanClose = anns epAnn
let wrapOpen = docHandleComms spanOpen
let wrapClose = docHandleComms spanClose
innerExpDoc <- shareDoc $ layoutExpr innerExp
docAlt
[ docSeq
[ wrapOpen $ docLit $ Text.pack "("
, docForceSingleline innerExpDoc
, wrapClose $ docLit $ Text.pack ")"
]
, docSetBaseY $ docLines
[ docCols
ColOpPrefix
[ wrapOpen $ docLit $ Text.pack "("
, docAddBaseY (BrIndentSpecial 2) innerExpDoc
]
, wrapClose $ docLit $ Text.pack ")"
]
]
SectionL _ left op -> do -- TODO: add to testsuite
leftDoc <- shareDoc $ layoutExpr left
opDoc <- shareDoc $ layoutExpr op
docSeq [leftDoc, docSeparator, opDoc]
SectionR _ op right -> do -- TODO: add to testsuite
opDoc <- shareDoc $ layoutExpr op
rightDoc <- shareDoc $ layoutExpr right
docSeq [opDoc, docSeparator, rightDoc]
ExplicitTuple epAnn args boxity -> docHandleComms epAnn $ do
let (wrapOpen, wrapClose) = case anns epAnn of
[open, close] -> case boxity of
Boxed ->
( docHandleComms $ obtainAnnPos open AnnOpenP
, docHandleComms $ obtainAnnPos close AnnCloseP
)
Unboxed ->
( docHandleComms $ obtainAnnPos open AnnOpenPH
, docHandleComms $ obtainAnnPos close AnnClosePH
)
_ -> (id, id)
argDocs <- forM args $ \case
Present _ e -> shareDoc $ docHandleListElemComms layoutExpr e
Missing missingEpAnn -> shareDoc $ docHandleComms missingEpAnn docEmpty
-- let ((c1, argsWithC, c2), cRemain) = case epAnn of
-- EpAnn _ [open, close] comms ->
-- enterCommentsSplitC comms $ do
-- comms1 <- getCommentsBeforeKW open AnnOpenP
-- elems' <- args `forM` \arg -> case arg of
-- Present _ e@(L (SrcSpanAnn elEpAnn loc) _) -> do
-- commsB <- case loc of
-- GHC.RealSrcSpan span _ -> getCommentsBeforeSpan span
-- _ -> pure []
-- case elEpAnn of
-- EpAnn _ (AnnListItem items) _ -> do
-- commsA <- items `forM` \case
-- AddCommaAnn span ->
-- getCommentsBeforeEpaLocation span
-- ann1 ->
-- error $ "unexpected TrailingAnn: "
-- ++ showSDocUnsafe (ppr ann1)
-- pure $ docWrapNode (commsB, join commsA) $ layoutExpr e
-- EpAnnNotUsed -> do
-- pure $ prependComments commsB $ layoutExpr e
-- Missing (EpAnn _ epa _) -> do
-- commsB <- getCommentsBeforeEpaLocation epa
-- pure $ prependComments commsB docEmpty
-- Missing EpAnnNotUsed -> pure $ docEmpty
-- comm2 <- getCommentsBeforeKW close AnnCloseP
-- pure (comms1, elems', comm2)
-- EpAnn _ _ _ -> error "unexpected ExplicitTuple ann!"
-- EpAnnNotUsed ->
-- let argsDocs = [ case arg of
-- Present _ e -> layoutExpr e
-- Missing _ -> docEmpty
-- | arg <- args ]
-- in (([], argsDocs, []), [])
let hasComments = hasAnyCommentsBelow lexpr -- TODO92 this is slightly
-- overzealous for comments before open & after close
let
(openLit, closeLit) = case boxity of
Boxed ->
( wrapOpen $ docLit $ Text.pack "("
, wrapClose $ docLit $ Text.pack ")"
)
Unboxed ->
( wrapOpen $ docParenHashLSep
, wrapClose $ docParenHashRSep
)
case splitFirstLast argDocs of
FirstLastEmpty ->
docSeq [openLit, closeLit]
FirstLastSingleton e -> docAlt
[ docCols
ColTuple
[ openLit
, docForceSingleline e
, closeLit
]
, docSetBaseY $ docLines
[ docSeq
[ openLit
, docForceSingleline e
]
, closeLit
]
]
FirstLast e1 ems eN -> runFilteredAlternative $ do
addAlternativeCond (not hasComments)
$ docCols ColTuple
$ [docSeq [openLit, docForceSingleline e1]]
++ (ems <&> \e -> docSeq [docCommaSep, docForceSingleline e])
++ [ docSeq
[ docCommaSep
, -- TODO92 docNodeAnnKW lexpr (Just AnnOpenP)
(docForceSingleline eN)
, closeLit
]
]
addAlternative
$ let
start = docCols ColTuples [appSep openLit, e1]
linesM = ems <&> \d -> docCols ColTuples [docCommaSep, d]
lineN = docCols
ColTuples
[docCommaSep, -- TODO92 docNodeAnnKW lexpr (Just AnnOpenP)
eN]
end = closeLit
in docSetBaseY $ docLines $ [start] ++ linesM ++ [lineN, end]
HsCase epAnn cExp (MG _ (L _ []) _) -> docHandleComms epAnn $ do
cExpDoc <- shareDoc $ layoutExpr cExp
docAlt
[ docAddBaseY BrIndentRegular $ docSeq
[ appSep $ docLit $ Text.pack "case"
, appSep $ docForceSingleline cExpDoc
, docLit $ Text.pack "of {}"
]
, docPar
(docAddBaseY BrIndentRegular
$ docPar (docLit $ Text.pack "case") cExpDoc
)
(docLit $ Text.pack "of {}")
]
HsCase epAnn cExp (MG _ lmatches@(L _ matches) _) -> docHandleComms epAnn $ do
cExpDoc <- shareDoc $ layoutExpr cExp
binderDoc <- docLit $ Text.pack "->"
funcPatDocs <-
-- docWrapNode lmatches
layoutPatternBind Nothing binderDoc
`mapM` matches
docAlt
[ docSetParSpacing $ docAddBaseY BrIndentRegular $ docPar
(docSeq
[ appSep $ docLit $ Text.pack "case"
, appSep $ docForceSingleline cExpDoc
, docLit $ Text.pack "of"
]
)
(docSetBaseAndIndent
$ docNonBottomSpacing
$ docHandleComms lmatches
$ docLines
$ return
<$> funcPatDocs
)
, docPar
(docAddBaseY BrIndentRegular
$ docPar (docLit $ Text.pack "case") cExpDoc
)
(docAddBaseY BrIndentRegular $ docPar
(docLit $ Text.pack "of")
(docSetBaseAndIndent
$ docNonBottomSpacing
$ docHandleComms lmatches
$ docLines
$ return
<$> funcPatDocs
)
)
]
HsIf epAnn ifExpr thenExpr elseExpr -> docHandleComms epAnn $ do
let AnnsIf spanIf spanThen spanElse _ _ = anns epAnn
let ifDoc = docHandleComms spanIf $ docLit $ Text.pack "if"
let thenDoc = docHandleComms spanThen $ docLit $ Text.pack "then"
let elseDoc = docHandleComms spanElse $ docLit $ Text.pack "else"
ifExprDoc <- shareDoc $ layoutExpr ifExpr
thenExprDoc <- shareDoc $ layoutExpr thenExpr
elseExprDoc <- shareDoc $ layoutExpr elseExpr
let hasComments = hasAnyCommentsBelow lexpr
let
maySpecialIndent = case indentPolicy of
IndentPolicyLeft -> BrIndentRegular
IndentPolicyMultiple -> BrIndentRegular
IndentPolicyFree -> BrIndentSpecial 3
-- TODO: some of the alternatives (especially last and last-but-one)
-- overlap.
docSetIndentLevel $ runFilteredAlternative $ do
-- if _ then _ else _
addAlternativeCond (not hasComments) $ docSeq
[ appSep $ ifDoc
, appSep $ docForceSingleline ifExprDoc
, appSep $ thenDoc
, appSep $ docForceSingleline thenExprDoc
, appSep $ elseDoc
, docForceSingleline elseExprDoc
]
-- either
-- if expr
-- then foo
-- bar
-- else foo
-- bar
-- or
-- if expr
-- then
-- stuff
-- else
-- stuff
-- note that this has par-spacing
addAlternative $ docSetParSpacing $ docAddBaseY BrIndentRegular $ docPar
(docSeq
[ -- TODO92 docNodeAnnKW lexpr Nothing $
appSep $ ifDoc
, -- TODO92 docNodeAnnKW lexpr (Just AnnIf) $
docForceSingleline ifExprDoc
]
)
(docLines
[ docAddBaseY BrIndentRegular
-- TODO92 $ docNodeAnnKW lexpr (Just AnnThen)
$ docNonBottomSpacing
$ docAlt
[ docSeq
[ appSep $ thenDoc
, docForceParSpacing thenExprDoc
]
, docAddBaseY BrIndentRegular
$ docPar (thenDoc) thenExprDoc
]
, docAddBaseY BrIndentRegular $ docNonBottomSpacing $ docAlt
[ docSeq
[ appSep $ elseDoc
, docForceParSpacing elseExprDoc
]
, docAddBaseY BrIndentRegular
$ docPar elseDoc elseExprDoc
]
]
)
-- either
-- if multi
-- line
-- condition
-- then foo
-- bar
-- else foo
-- bar
-- or
-- if multi
-- line
-- condition
-- then
-- stuff
-- else
-- stuff
-- note that this does _not_ have par-spacing
addAlternative $ docAddBaseY BrIndentRegular $ docPar
(docAddBaseY maySpecialIndent $ docSeq
[ -- TODO92 docNodeAnnKW lexpr Nothing $
appSep $ ifDoc
, -- TODO92 docNodeAnnKW lexpr (Just AnnIf) $
ifExprDoc
]
)
(docLines
[ docAddBaseY BrIndentRegular
-- TODO92 $ docNodeAnnKW lexpr (Just AnnThen)
$ docAlt
[ docSeq
[ appSep $ thenDoc
, docForceParSpacing thenExprDoc
]
, docAddBaseY BrIndentRegular
$ docPar (thenDoc) thenExprDoc
]
, docAddBaseY BrIndentRegular $ docAlt
[ docSeq
[ appSep $ elseDoc
, docForceParSpacing elseExprDoc
]
, docAddBaseY BrIndentRegular
$ docPar elseDoc elseExprDoc
]
]
)
addAlternative $ docSetBaseY $ docLines
[ docAddBaseY maySpecialIndent $ docSeq
[ -- TODO92 docNodeAnnKW lexpr Nothing $
appSep $ ifDoc
, -- TODO92 docNodeAnnKW lexpr (Just AnnIf) $
ifExprDoc
]
, -- TODO92 docNodeAnnKW lexpr (Just AnnThen) $
docAddBaseY BrIndentRegular
$ docPar (thenDoc) thenExprDoc
, docAddBaseY BrIndentRegular
$ docPar elseDoc elseExprDoc
]
HsMultiIf epAnn cases -> do
binderDoc <- docLit $ Text.pack "->"
let hasComments =
hasAnyCommentsBelow epAnn
|| any (\(L _ (GRHS gEpAnn _ _)) -> hasAnyCommentsBelow gEpAnn) cases
let posIf = obtainAnnPos epAnn AnnIf
docSetParSpacing $ docAddBaseY BrIndentRegular $ docPar
(docHandleComms posIf $ docLit $ Text.pack "if")
(layoutPatternBindFinal
Nothing
binderDoc
Nothing
(Right cases)
Nothing
hasComments
)
HsLet epAnn binds exp1 -> docHandleComms epAnn $ do
let AnnsLet spanLet spanIn = anns epAnn
let hasComments = hasAnyCommentsBelow lexpr
let wrapLet = docHandleComms spanLet
let wrapIn = docHandleComms spanIn
mBindDocs <- layoutLocalBinds binds
let
ifIndentFreeElse :: a -> a -> a
ifIndentFreeElse x y = case indentPolicy of
IndentPolicyLeft -> y
IndentPolicyMultiple -> y
IndentPolicyFree -> x
expDoc1 <- shareDoc $ layoutExpr exp1
-- this `docSetBaseAndIndent` might seem out of place (especially the
-- Indent part; setBase is necessary due to the use of docLines below),
-- but is here due to ghc-exactprint's DP handling of "let" in
-- particular.
-- Just pushing another indentation level is a straightforward approach
-- to making brittany idempotent, even though the result is non-optimal
-- if "let" is moved horizontally as part of the transformation, as the
-- comments before the first let item are moved horizontally with it.
letDoc <- shareDoc $ wrapLet $ docLit $ Text.pack "let"
inDoc <- shareDoc $ wrapIn $ docLit $ Text.pack "in"
docSetBaseAndIndent $ case fmap snd mBindDocs of
Just [bindDoc] -> runFilteredAlternative $ do
addAlternativeCond (not hasComments) $ docSeq
[ appSep $ letDoc
, appSep $ docForceSingleline (pure bindDoc)
, appSep $ inDoc
, docForceSingleline expDoc1
]
addAlternative $ docLines
[ docAlt
[ docSeq
[ appSep $ letDoc
, ifIndentFreeElse docSetBaseAndIndent docForceSingleline
$ pure bindDoc
]
, docAddBaseY BrIndentRegular $ docPar
(letDoc)
(docSetBaseAndIndent $ pure bindDoc)
]
, docAlt
[ docSeq
[ appSep $ wrapIn $ docLit $ Text.pack $ ifIndentFreeElse "in " "in"
, ifIndentFreeElse
docSetBaseAndIndent
docForceSingleline
expDoc1
]
, docAddBaseY BrIndentRegular
$ docPar (inDoc) (docSetBaseY expDoc1)
]
]
Just bindDocs@(_ : _) -> runFilteredAlternative $ do
--either
-- let
-- a = b
-- c = d
-- in foo
-- bar
-- baz
--or
-- let
-- a = b
-- c = d
-- in
-- fooooooooooooooooooo
let
noHangingBinds =
[ docNonBottomSpacing $ docAddBaseY BrIndentRegular $ docPar
(letDoc)
(docSetBaseAndIndent $ docLines $ pure <$> bindDocs)
, docSeq
[ wrapIn $ docLit $ Text.pack "in "
, docAddBaseY BrIndentRegular $ docForceParSpacing expDoc1
]
]
addAlternative $ case indentPolicy of
IndentPolicyLeft -> docLines noHangingBinds
IndentPolicyMultiple -> docLines noHangingBinds
IndentPolicyFree -> docLines
[ -- TODO92 docNodeAnnKW lexpr (Just AnnLet) $
docSeq
[ appSep $ letDoc
, docSetBaseAndIndent $ docLines $ pure <$> bindDocs
]
, docSeq [appSep $ wrapIn $ docLit $ Text.pack "in ", docSetBaseY expDoc1]
]
addAlternative $ docLines
[ -- TODO92 docNodeAnnKW lexpr (Just AnnLet) $
docAddBaseY BrIndentRegular
$ docPar
(letDoc)
(docSetBaseAndIndent $ docLines $ pure <$> bindDocs)
, docAddBaseY BrIndentRegular
$ docPar (inDoc) (docSetBaseY $ expDoc1)
]
_ -> docSeq
[ docForceSingleline $ docSeq
[ letDoc
, docSeparator
, inDoc
]
, docSeparator
, expDoc1
]
-- docSeq [appSep $ docLit "let in", expDoc1]
HsDo epAnn stmtCtx (L (SrcSpanAnn stmtEpAnn _) stmts) ->
docHandleComms epAnn $ do
case stmtCtx of
DoExpr _ -> do
stmtDocs <- docHandleComms stmtEpAnn $ do
stmts `forM` docHandleListElemComms layoutStmt
docSetParSpacing $ docAddBaseY BrIndentRegular $ docPar
(docLit $ Text.pack "do")
(docSetBaseAndIndent
$ docNonBottomSpacing
$ docLines
$ pure <$> stmtDocs
)
MDoExpr _ -> do
stmtDocs <- docHandleComms stmtEpAnn $ do
stmts `forM` docHandleListElemComms layoutStmt
docSetParSpacing $ docAddBaseY BrIndentRegular $ docPar
(docLit $ Text.pack "mdo")
(docSetBaseAndIndent
$ docNonBottomSpacing
$ docLines
$ pure <$> stmtDocs
)
x
| case x of
ListComp -> True
MonadComp -> True
_ -> False
-> do
stmtDocs <- docHandleComms stmtEpAnn $
stmts `forM` docHandleListElemComms layoutStmt
let hasComments = hasAnyCommentsBelow lexpr
runFilteredAlternative $ do
addAlternativeCond (not hasComments) $ docSeq
[ -- TODO92 docNodeAnnKW lexpr Nothing $
appSep $ docLit $ Text.pack "["
, -- TODO92 docNodeAnnKW lexpr (Just AnnOpenS) $
appSep
$ docForceSingleline
$ pure (List.last stmtDocs)
, appSep $ docLit $ Text.pack "|"
, docSeq
$ List.intersperse docCommaSep
$ (docForceSingleline . pure) <$> List.init stmtDocs
, docLit $ Text.pack " ]"
]
addAlternative
$ let
start = docCols
ColListComp
[ -- TODO92 docNodeAnnKW lexpr Nothing $
appSep $ docLit $ Text.pack "["
, docSetBaseY
-- TODO92 $ docNodeAnnKW lexpr (Just AnnOpenS)
$ pure (List.last stmtDocs)
]
(s1, sM) = case List.init stmtDocs of
(a: b) -> (a, b)
_ -> error "layoutExp: stmtDocs list too short"
line1 =
docCols ColListComp [appSep $ docLit $ Text.pack "|", pure s1]
lineM = sM <&> \d -> docCols ColListComp [docCommaSep, pure d]
end = docLit $ Text.pack "]"
in docSetBaseY $ docLines $ [start, line1] ++ lineM ++ [end]
_ -> do
-- TODO
unknownNodeError "HsDo{} unknown stmtCtx" lexpr
ExplicitList listEpAnn elems@(_ : _) -> docHandleComms listEpAnn $ do
let posOpen = obtainAnnPos listEpAnn AnnOpenS
let posClose = obtainAnnPos listEpAnn AnnCloseS
let openDoc = docHandleComms posOpen $ docLitS "["
let closeDoc = docHandleComms posClose $ docLitS "]"
elemDocs <- elems `forM` (shareDoc . docHandleListElemComms layoutExpr)
let hasComments = hasAnyCommentsBelow lexpr
case splitFirstLast elemDocs of
FirstLastEmpty -> docSeq
[ docLit $ Text.pack "["
, closeDoc
]
FirstLastSingleton e -> docAlt
[ docSeq
[ openDoc
, docForceSingleline e
, closeDoc
]
, docSetBaseY $ docLines
[ docSeq
[ openDoc
, docSeparator
, docSetBaseY $ e
]
, closeDoc
]
]
FirstLast e1 ems eN -> runFilteredAlternative $ do
addAlternativeCond (not hasComments)
$ docSeq
$ [openDoc]
++ List.intersperse
docCommaSep
(docForceSingleline
<$> (e1 : ems ++ [eN])
)
++ [closeDoc]
addAlternative
$ let
start = docCols ColList [appSep $ openDoc, e1]
linesM = ems <&> \d -> docCols ColList [docCommaSep, d]
lineN = docCols
ColList
[docCommaSep, eN]
in docSetBaseY $
docLines $ [start] ++ linesM ++ [lineN] ++ [closeDoc]
ExplicitList epAnn [] -> docHandleComms epAnn $ docLit $ Text.pack "[]"
RecordCon epAnn lname fields -> docHandleComms epAnn $ do
let (wrapOpen, wrapClose) = case epAnn of
EpAnn _ [open, close] _ ->
( docHandleComms (obtainAnnPos open AnnOpenC)
, docHandleComms (obtainAnnPos close AnnCloseC)
)
_ -> (id, id)
fieldLayouter = \case
FieldOcc _ lnameF -> docLit (lrdrNameToText lnameF)
XFieldOcc _ -> error "XFieldOcc"
case fields of
HsRecFields fs Nothing -> do
let nameDoc = docHandleComms lname $ docLit $ lrdrNameToText lname
recordExpression False wrapOpen id wrapClose indentPolicy lexpr nameDoc fieldLayouter fs
HsRecFields [] (Just (L dotdotLoc 0)) -> do
let wrapDotDot = docHandleComms dotdotLoc
let t = lrdrNameToText lname
docHandleComms lname $ docSeq
[ docLit t
, docSeparator
, wrapOpen $ docLitS "{"
, docSeparator
, wrapDotDot $ docLitS ".."
, docSeparator
, wrapClose $ docLitS "}"
]
HsRecFields fs@(_ : _) (Just (L dotdotLoc dotdoti)) | dotdoti == length fs -> do
let nameDoc = docHandleComms lname $ docLit $ lrdrNameToText lname
let wrapDotDot = docHandleComms dotdotLoc
recordExpression True wrapOpen wrapDotDot wrapClose indentPolicy lexpr nameDoc fieldLayouter fs
_ -> unknownNodeError "RecordCon with puns" lexpr
RecordUpd epAnn rExpr (Left fields) -> docHandleComms epAnn $ do
let (wrapOpen, wrapClose) = case epAnn of
EpAnn _ [open, close] _ ->
( docHandleComms $ obtainAnnPos open AnnOpenC
, docHandleComms $ obtainAnnPos close AnnCloseC
)
_ -> (id, id)
let fieldLayouter = \case
Unambiguous _ n -> docLit (lrdrNameToText n)
Ambiguous _ n -> docLit (lrdrNameToText n)
XAmbiguousFieldOcc _ -> error "XAmbiguousFieldOcc"
rExprDoc <- shareDoc $ layoutExpr rExpr
recordExpression False wrapOpen id wrapClose indentPolicy lexpr rExprDoc fieldLayouter fields
RecordUpd epAnn rExpr (Right fields) -> do
let (wrapOpen, wrapClose) = case epAnn of
EpAnn _ [open, close] _ ->
( docHandleComms $ obtainAnnPos open AnnOpenC
, docHandleComms $ obtainAnnPos close AnnCloseC
)
_ -> (id, id)
rExprDoc <- shareDoc $ layoutExpr rExpr
let labelLayouter label = case label of
L flAnn (HsFieldLabel _ (L _ n)) ->
docHandleComms flAnn $ docLitS $ FastString.unpackFS n
L _ann (XHsFieldLabel _) -> error "XHsFieldLabel"
let fieldLayouter = \case
FieldLabelStrings [] -> docEmpty
FieldLabelStrings [label] -> labelLayouter label
FieldLabelStrings labels -> docSeq
$ List.intersperse docCommaSep
$ map labelLayouter labels
recordExpression False wrapOpen id wrapClose indentPolicy lexpr rExprDoc fieldLayouter fields
ExprWithTySig _ exp1 (HsWC _ typ1) -> do
expDoc <- shareDoc $ layoutExpr exp1
typDoc <- shareDoc $ layoutSigType typ1
docSeq [appSep expDoc, appSep $ docLit $ Text.pack "::", typDoc]
ArithSeq _ Nothing info -> case info of
From e1 -> do
e1Doc <- shareDoc $ layoutExpr e1
docSeq
[ docLit $ Text.pack "["
, appSep $ docForceSingleline e1Doc
, docLit $ Text.pack "..]"
]
FromThen e1 e2 -> do
e1Doc <- shareDoc $ layoutExpr e1
e2Doc <- shareDoc $ layoutExpr e2
docSeq
[ docLit $ Text.pack "["
, docForceSingleline e1Doc
, appSep $ docLit $ Text.pack ","
, appSep $ docForceSingleline e2Doc
, docLit $ Text.pack "..]"
]
FromTo e1 eN -> do
e1Doc <- shareDoc $ layoutExpr e1
eNDoc <- shareDoc $ layoutExpr eN
docSeq
[ docLit $ Text.pack "["
, appSep $ docForceSingleline e1Doc
, appSep $ docLit $ Text.pack ".."
, docForceSingleline eNDoc
, docLit $ Text.pack "]"
]
FromThenTo e1 e2 eN -> do
e1Doc <- shareDoc $ layoutExpr e1
e2Doc <- shareDoc $ layoutExpr e2
eNDoc <- shareDoc $ layoutExpr eN
docSeq
[ docLit $ Text.pack "["
, docForceSingleline e1Doc
, appSep $ docLit $ Text.pack ","
, appSep $ docForceSingleline e2Doc
, appSep $ docLit $ Text.pack ".."
, docForceSingleline eNDoc
, docLit $ Text.pack "]"
]
HsGetField _epAnn _exp1 _field -> do
let
labelLayouter label = case label of
L flAnn (HsFieldLabel _ (L _ n)) ->
docHandleComms flAnn $ docLitS $ FastString.unpackFS n
L _ann (XHsFieldLabel _) -> error "XHsFieldLabel"
gather
:: [ToBriDocM BriDocNumbered]
-> LHsExpr GhcPs
-> (LHsExpr GhcPs, [ToBriDocM BriDocNumbered])
gather list = \case
L _ (HsGetField epAnn l r) -> gather
(docHandleComms epAnn $ labelLayouter r : list) l
x -> (x, list)
let (headE, paramEs) = gather
[]
lexpr
expDoc <- shareDoc $ layoutExpr headE
-- this only has single-line layout, afaik
docForceSingleline $ docSeq $ intersperse (docLitS ".") (expDoc: paramEs)
HsProjection epAnn (f1 :| fR) -> do
let
labelLayouter label = case label of
L flAnn (HsFieldLabel _ (L _ n)) ->
docHandleComms flAnn $ docLitS $ FastString.unpackFS n
L _ann (XHsFieldLabel _) -> error "XHsFieldLabel"
docForceSingleline $ docHandleComms epAnn $ docSeq
( [ docLitS "(" ]
++ [ doc | f <- f1:fR, doc <- [docLitS ".", labelLayouter f] ]
++ [ docLitS ")" ]
)
ArithSeq{} -> briDocByExactInlineOnly "ArithSeq" lexpr
HsBracket{} -> do
-- TODO
briDocByExactInlineOnly "HsBracket{}" lexpr
HsRnBracketOut{} -> do
-- TODO
briDocByExactInlineOnly "HsRnBracketOut{}" lexpr
HsTcBracketOut{} -> do
-- TODO
briDocByExactInlineOnly "HsTcBracketOut{}" lexpr
HsSpliceE _ (HsQuasiQuote _ _ quoter _loc content) -> do
allocateNode $ BDPlain
(Text.pack
$ "["
++ showOutputable quoter
++ "|"
++ showOutputable content
++ "|]"
)
HsSpliceE{} -> do
-- TODO
briDocByExactInlineOnly "HsSpliceE{}" lexpr
HsProc{} -> do
-- TODO
briDocByExactInlineOnly "HsProc{}" lexpr
HsStatic{} -> do
-- TODO
briDocByExactInlineOnly "HsStatic{}" lexpr
HsTick{} -> do
-- TODO
briDocByExactInlineOnly "HsTick{}" lexpr
HsBinTick{} -> do
-- TODO
briDocByExactInlineOnly "HsBinTick{}" lexpr
HsConLikeOut{} -> do
-- TODO
briDocByExactInlineOnly "HsWrap{}" lexpr
ExplicitSum{} -> do
-- TODO
briDocByExactInlineOnly "ExplicitSum{}" lexpr
HsPragE{} -> do
-- TODO
briDocByExactInlineOnly "HsPragE{}" lexpr
recordExpression
:: Bool
-> (ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered)
-> (ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered)
-> (ToBriDocM BriDocNumbered -> ToBriDocM BriDocNumbered)
-> IndentPolicy
-> LocatedA lExpr
-> ToBriDocM BriDocNumbered
-> (field -> ToBriDocM BriDocNumbered)
-- -> [LHsFieldBind GhcPs (LFieldOcc p) (LHsExpr GhcPs)]
-> [LHsRecField' GhcPs field (LHsExpr GhcPs)]
-> ToBriDocM BriDocNumbered
recordExpression False wrapO _wrapDD wrapC _ _lexpr nameDoc _ [] = docSeq
[ -- TODO92 docNodeAnnKW lexpr (Just AnnOpenC) $
docSeq [nameDoc, wrapO $ docLit $ Text.pack "{"]
, wrapC $ docLit $ Text.pack "}"
]
recordExpression True wrapO wrapDD wrapC _ _lexpr nameDoc _ [] = docSeq -- this case might still be incomplete, and is probably not used
-- atm anyway.
[ nameDoc
, wrapO $ docLit $ Text.pack "{"
, docSeparator
, wrapDD $ docLitS ".."
, docSeparator
, wrapC $ docLit $ Text.pack "}"
]
recordExpression dotdot wrapO wrapDD wrapC indentPolicy _lexpr nameDoc nameLayouter (rF1 : rFr) = do
let mkFieldTuple = \case
L srcSpan (HsRecField fEpAnn (L _ nameThing) rFExpr pun) -> do
let (posStart, _posSomething) = case fEpAnn of -- TODO92 not sure what posSomething is
EpAnn anch [AddEpAnn _ span] _ ->
( Just $ GHC.realSrcSpanStart $ anchor anch
, Just $ epaLocationRealSrcSpanStart span
)
_ -> (Nothing, Nothing)
let posComma = case srcSpan of
SrcSpanAnn (EpAnn _ (AnnListItem items) _) _ -> case items of
[AddCommaAnn span] -> Just $ epaLocationRealSrcSpanStart span
_ -> Nothing
SrcSpanAnn EpAnnNotUsed _ -> Nothing
fnameDoc <- shareDoc $ nameLayouter nameThing
if pun
then pure $ Left (posStart, fnameDoc)
else do
expDoc <- shareDoc $ docFlushCommsPost posComma $ layoutExpr rFExpr
pure $ Right (posStart, fnameDoc, expDoc)
fieldTuple1 <- mkFieldTuple rF1
fieldTupleR <- rFr `forM` mkFieldTuple
let fieldWiths
:: a
-> a
-> ( a
-> Either
(Maybe GHC.RealSrcLoc, ToBriDocM BriDocNumbered)
( Maybe GHC.RealSrcLoc
, ToBriDocM BriDocNumbered
, ToBriDocM BriDocNumbered
)
-> ToBriDocM BriDocNumbered
)
-> [ToBriDocM BriDocNumbered]
fieldWiths extra1 extraR f =
f extra1 fieldTuple1 : map (f extraR) fieldTupleR
runFilteredAlternative $ do
-- container { fieldA = blub, fieldB = blub }
addAlternative $ docSeq
[ -- TODO92 docNodeAnnKW lexpr Nothing $
appSep $ docForceSingleline nameDoc
, appSep $ wrapO $ docLit $ Text.pack "{"
, docSeq
$ List.intersperse docCommaSep
$ fieldWiths () () $ \() -> \case
Left (pos, fnameDoc) -> docHandleComms pos $ fnameDoc
Right (pos, fnameDoc, expDoc) -> docHandleComms pos $ docSeq
[ appSep $ fnameDoc
, appSep $ docLit $ Text.pack "="
, docForceSingleline $ expDoc
]
, if dotdot
then docSeq [docCommaSep, wrapDD $ docLit $ Text.pack "..", docSeparator]
else docSeparator
, wrapC $ docLit $ Text.pack "}"
]
-- hanging single-line fields
-- container { fieldA = blub
-- , fieldB = blub
-- }
addAlternativeCond (indentPolicy == IndentPolicyFree) $ docSeq
[ -- TODO92 docNodeAnnKW lexpr Nothing $
docForceSingleline $ appSep nameDoc
, docSetBaseY
$ docLines
$ let
fieldLines = fieldWiths
(appSep $ wrapO $ docLit $ Text.pack "{")
docCommaSep
$ \prep -> \case
Left (pos, fnameDoc) -> docCols
ColRec
[ prep
, docHandleComms pos $ fnameDoc
]
Right (pos, fnameDoc, expDoc) -> docCols
ColRec
[ prep
, docHandleComms pos $ appSep $ fnameDoc
, docSeq
[appSep $ docLit $ Text.pack "=", docForceSingleline expDoc]
]
dotdotLine = if dotdot
then docCols
ColRec
[ -- TODO92 docNodeAnnKW lexpr (Just AnnOpenC)
docCommaSep
, wrapDD $ docLit $ Text.pack ".."
]
else -- TODO92 docNodeAnnKW lexpr (Just AnnOpenC)
docEmpty
lineN = wrapC $ docLit $ Text.pack "}"
in fieldLines ++ [dotdotLine, lineN]
]
-- non-hanging with expressions placed to the right of the names
-- container
-- { fieldA = blub
-- , fieldB = potentially
-- multiline
-- }
addAlternative $ docSetParSpacing $ docAddBaseY BrIndentRegular $ docPar
(-- TODO92 docNodeAnnKW lexpr Nothing
nameDoc)
(docNonBottomSpacing
$ docLines
$ let
fieldLines = fieldWiths
(appSep $ wrapO $ docLit $ Text.pack "{")
docCommaSep
$ \prep -> \case
Left (pos, fnameDoc) -> docCols ColRec
[ prep
, docHandleComms pos $ fnameDoc
]
Right (pos, fnameDoc, expDoc) -> docCols ColRec
[ prep
, docHandleComms pos $ appSep $ fnameDoc
, runFilteredAlternative $ do
addAlternativeCond (indentPolicy == IndentPolicyFree) $ do
docSeq [appSep $ docLit $ Text.pack "=", docSetBaseY expDoc]
addAlternative $ do
docSeq
[appSep $ docLit $ Text.pack "=", docForceParSpacing expDoc]
addAlternative $ do
docAddBaseY BrIndentRegular
$ docPar (docLit $ Text.pack "=") expDoc
]
dotdotLine = if dotdot
then docCols
ColRec
[ -- TODO92 docNodeAnnKW lexpr (Just AnnOpenC)
docCommaSep
, wrapDD $ docLit $ Text.pack ".."
]
else -- TODO92 docNodeAnnKW lexpr (Just AnnOpenC)
docEmpty
lineN = wrapC $ docLit $ Text.pack "}"
in fieldLines ++ [dotdotLine, lineN]
)
litBriDoc :: HsLit GhcPs -> BriDocWrapped
litBriDoc = \case
HsChar (SourceText t) _c -> BDLit $ Text.pack t -- BDLit $ Text.pack $ ['\'', c, '\'']
HsCharPrim (SourceText t) _c -> BDLit $ Text.pack t -- BDLit $ Text.pack $ ['\'', c, '\'']
HsString (SourceText t) _fastString -> BDLit $ Text.pack t -- BDLit $ Text.pack $ FastString.unpackFS fastString
HsStringPrim (SourceText t) _byteString -> BDLit $ Text.pack t -- BDLit $ Text.pack $ Data.ByteString.Char8.unpack byteString
HsInt _ (IL (SourceText t) _ _) -> BDLit $ Text.pack t -- BDLit $ Text.pack $ show i
HsIntPrim (SourceText t) _i -> BDLit $ Text.pack t -- BDLit $ Text.pack $ show i
HsWordPrim (SourceText t) _i -> BDLit $ Text.pack t -- BDLit $ Text.pack $ show i
HsInt64Prim (SourceText t) _i -> BDLit $ Text.pack t -- BDLit $ Text.pack $ show i
HsWord64Prim (SourceText t) _i -> BDLit $ Text.pack t -- BDLit $ Text.pack $ show i
HsInteger (SourceText t) _i _type -> BDLit $ Text.pack t -- BDLit $ Text.pack $ show i
HsRat _ (FL (SourceText t) _ _ _ _) _type -> BDLit $ Text.pack t
HsFloatPrim _ (FL (SourceText t) _ _ _ _) -> BDLit $ Text.pack t
HsDoublePrim _ (FL (SourceText t) _ _ _ _) -> BDLit $ Text.pack t
_ -> error "litBriDoc: literal with no SourceText"
overLitValBriDoc :: OverLitVal -> BriDocWrapped
overLitValBriDoc = \case
HsIntegral (IL (SourceText t) _ _) -> BDLit $ Text.pack t
HsFractional (FL (SourceText t) _ _ _ _) -> BDLit $ Text.pack t
HsIsString (SourceText t) _ -> BDLit $ Text.pack t
_ -> error "overLitValBriDoc: literal with no SourceText"