Add compact version of import layout

Also let layoutLLIEs deal with comments
pull/83/head
sniperrifle2004 2017-12-21 23:51:27 +01:00
parent 82a5ffb3b3
commit 21c080572b
5 changed files with 144 additions and 129 deletions

View File

@ -704,6 +704,17 @@ import TestJustShortEnoughModuleNameLike hiding ( )
import TestJustAbitToLongModuleNameLikeTh import TestJustAbitToLongModuleNameLikeTh
hiding ( ) hiding ( )
import MoreThanSufficientlyLongModuleNameWithSome
( items
, that
, will
, not
, fit
, inA
, compact
, layout
)
import {-# SOURCE #-} safe qualified "qualifiers" AlsoAff ( ) import {-# SOURCE #-} safe qualified "qualifiers" AlsoAff ( )
import {-# SOURCE #-} safe qualified "qualifiers" AlsoAffe import {-# SOURCE #-} safe qualified "qualifiers" AlsoAffe
( ) ( )

View File

@ -685,7 +685,7 @@ import safe Data.List as L
import {-# SOURCE #-} Data.List () import {-# SOURCE #-} Data.List ()
#test simple-safe-qualified #test simple-safe-qualified
import safe qualified Data.Lis hiding ( nub ) import safe qualified Data.List hiding (nub)
#test simple-safe-qualified-source #test simple-safe-qualified-source
import {-# SOURCE #-} safe qualified Data.List import {-# SOURCE #-} safe qualified Data.List
@ -705,43 +705,37 @@ import qualified Data.List ( )
import Data.List (nub) import Data.List (nub)
#test several-elements #test several-elements
import Data.List ( nub import Data.List (nub, foldl', indexElem)
, foldl'
, indexElem
)
#test with-things #test with-things
import Test ( T import Test (T, T2(), T3(..), T4(T4), T5(T5, t5), T6((<|>)), (+))
, T2()
, T3(..)
, T4(T4)
, T5(T5, t5)
, T6((<|>))
, (+)
)
#test hiding #test hiding
import Test hiding () import Test hiding ()
import Test as T import Test as T hiding ()
hiding ( )
#test long-module-name #test long-module-name
import TestJustShortEnoughModuleNameLikeThisOne () import TestJustShortEnoughModuleNameLikeThisOne ()
import TestJustAbitToLongModuleNameLikeThisOneIs import TestJustAbitToLongModuleNameLikeThisOneIs ()
( )
import TestJustShortEnoughModuleNameLikeThisOn as T import TestJustShortEnoughModuleNameLikeThisOn as T
import TestJustAbitToLongModuleNameLikeThisOneI import TestJustAbitToLongModuleNameLikeThisOneI as T
as T
import TestJustShortEnoughModuleNameLike hiding () import TestJustShortEnoughModuleNameLike hiding ()
import TestJustAbitToLongModuleNameLikeTh import TestJustAbitToLongModuleNameLikeTh hiding ()
hiding ( ) import MoreThanSufficientlyLongModuleNameWithSome ( items
, that
, will
, not
, fit
, inA
, compact
, layout
)
#test import-with-comments #test import-with-comments
-- Test -- Test
import Data.List (nub) -- Test import Data.List (nub) -- Test
{- Test -} {- Test -}
import qualified Data.List as L import qualified Data.List as L (foldl') {- Test -}
( foldl' ) {- Test -}
#test import-with-comments-2 #test import-with-comments-2
@ -802,8 +796,7 @@ where
-- Test -- Test
import Data.List (nub) -- Test import Data.List (nub) -- Test
{- Test -} {- Test -}
import qualified Data.List as L import qualified Data.List as L (foldl') {- Test -}
( foldl' ) {- Test -}
-- Test -- Test
import Test (test) import Test (test)

View File

@ -47,12 +47,10 @@ layoutIE lie@(L _ ie) = docWrapNode lie $ case ie of
IEThingWith _ _ ns fs -> IEThingWith _ _ ns fs ->
docSeq docSeq
$ [ien, docLit $ Text.pack "("] $ [ien, docLit $ Text.pack "("]
++ ( intersperse docCommaSep ++ intersperse docCommaSep (map nameDoc ns ++ map prepareFL fs)
(map ((docLit =<<) . lrdrNameToTextAnn . prepareName) ns)
++ intersperse docCommaSep (map prepareFL fs)
)
++ [docLit $ Text.pack ")"] ++ [docLit $ Text.pack ")"]
where where
nameDoc = (docLit =<<) . lrdrNameToTextAnn . prepareName
prepareFL = docLit . Text.pack . FastString.unpackFS . flLabel . unLoc prepareFL = docLit . Text.pack . FastString.unpackFS . flLabel . unLoc
IEModuleContents n -> docSeq IEModuleContents n -> docSeq
[ docLit $ Text.pack "module" [ docLit $ Text.pack "module"
@ -64,8 +62,8 @@ layoutIE lie@(L _ ie) = docWrapNode lie $ case ie of
-- Helper function to deal with Located lists of LIEs. -- Helper function to deal with Located lists of LIEs.
-- In particular this will also associate documentation -- In particular this will also associate documentation
-- from the LIES that actually belongs to the last IE. -- from the located list that actually belongs to the last IE.
-- It also add docCommaSep to all but he last element -- It also adds docCommaSep to all but the first element
-- This configuration allows both vertical and horizontal -- This configuration allows both vertical and horizontal
-- handling of the resulting list. Adding parens is -- handling of the resulting list. Adding parens is
-- left to the caller since that is context sensitive -- left to the caller since that is context sensitive
@ -90,17 +88,25 @@ layoutAnnAndSepLLIEs llies@(L _ lies) = do
-- ... -- ...
-- , item -- , item
-- ) -- )
-- Empty lists will always be rendered as () -- If the llies contains comments the list will
-- always expand over multiple lines, even when empty:
-- () -- no comments
-- ( -- a comment
-- )
layoutLLIEs :: Located [LIE RdrName] -> ToBriDocM BriDocNumbered layoutLLIEs :: Located [LIE RdrName] -> ToBriDocM BriDocNumbered
layoutLLIEs llies = do layoutLLIEs llies = do
ieDs <- layoutAnnAndSepLLIEs llies ieDs <- layoutAnnAndSepLLIEs llies
hasComments <- hasAnyCommentsBelow llies
case ieDs of case ieDs of
[] -> docLit $ Text.pack "()" [] -> docAltFilter
(ieDsH:ieDsT) -> [ (not hasComments, docLit $ Text.pack "()")
docAlt , (otherwise, docPar (docSeq [docParenLSep, docWrapNode llies docEmpty])
[ docSeq $ docLit (Text.pack "("):ieDs ++ [docParenR] $ docLines [docParenR])
, docLines $ ]
docSeq [docParenLSep, ieDsH] (ieDsH:ieDsT) ->
: ieDsT docAltFilter
++ [docParenR] [ (not hasComments, docSeq $ docLit (Text.pack "("):ieDs ++ [docParenR])
, (otherwise, docPar (docSetBaseY $ docSeq [docParenLSep, ieDsH]) $
docLines $ ieDsT
++ [docParenR])
] ]

View File

@ -44,23 +44,23 @@ prepModName = id
layoutImport :: ToBriDoc ImportDecl layoutImport :: ToBriDoc ImportDecl
layoutImport limportD@(L _ importD) = docWrapNode limportD $ case importD of layoutImport limportD@(L _ importD) = docWrapNode limportD $ case importD of
ImportDecl _ (L _ modName) pkg src safe q False as mllies -> do ImportDecl _ (L _ modName) pkg src safe q False mas mllies -> do
importCol <- mAsk <&> _conf_layout .> _lconfig_importColumn .> confUnpack importCol <- mAsk <&> _conf_layout .> _lconfig_importColumn .> confUnpack
indentPolicy <- mAsk <&> _conf_layout .> _lconfig_indentPolicy .> confUnpack
-- NB we don't need to worry about sharing in the below code -- NB we don't need to worry about sharing in the below code
-- (docSharedWrapper etc.) because we do not use any docAlt nodes; all -- (docSharedWrapper etc.) because we do not use any docAlt nodes; all
-- "decisions" are made statically. -- "decisions" are made statically.
let let
compact = indentPolicy == IndentPolicyLeft
modNameT = Text.pack $ moduleNameString modName modNameT = Text.pack $ moduleNameString modName
pkgNameT = Text.pack . prepPkg . sl_st <$> pkg pkgNameT = Text.pack . prepPkg . sl_st <$> pkg
asT = Text.pack . moduleNameString . prepModName <$> as masT = Text.pack . moduleNameString . prepModName <$> mas
hiding = case mllies of hiding = maybe False fst mllies
Just (h, _) -> h
Nothing -> False
minQLength = length "import qualified " minQLength = length "import qualified "
qLengthReal = qLengthReal =
let qualifiedPart = if q then length "qualified " else 0 let qualifiedPart = if q then length "qualified " else 0
safePart = if safe then length "safe " else 0 safePart = if safe then length "safe " else 0
pkgPart = fromMaybe 0 ((+ 1) . Text.length <$> pkgNameT) pkgPart = maybe 0 ((+ 1) . Text.length) pkgNameT
srcPart = if src then length "{-# SOURCE #-} " else 0 srcPart = if src then length "{-# SOURCE #-} " else 0
in length "import " + srcPart + safePart + qualifiedPart + pkgPart in length "import " + srcPart + safePart + qualifiedPart + pkgPart
qLength = max minQLength qLengthReal qLength = max minQLength qLengthReal
@ -73,18 +73,23 @@ layoutImport limportD@(L _ importD) = docWrapNode limportD $ case importD of
, if src then appSep $ docLit $ Text.pack "{-# SOURCE #-}" else docEmpty , if src then appSep $ docLit $ Text.pack "{-# SOURCE #-}" else docEmpty
, if safe then appSep $ docLit $ Text.pack "safe" else docEmpty , if safe then appSep $ docLit $ Text.pack "safe" else docEmpty
, if q then appSep $ docLit $ Text.pack "qualified" else docEmpty , if q then appSep $ docLit $ Text.pack "qualified" else docEmpty
, fromMaybe docEmpty (appSep . docLit <$> pkgNameT) , maybe docEmpty (appSep . docLit) pkgNameT
] ]
indentName =
if compact then id else docEnsureIndent (BrIndentSpecial qLength)
modNameD = modNameD =
docEnsureIndent (BrIndentSpecial qLength) $ appSep $ docLit modNameT indentName $ appSep $ docLit modNameT
hidDoc = hidDoc =
if hiding then appSep $ docLit $ Text.pack "hiding" else docEmpty if hiding then appSep $ docLit $ Text.pack "hiding" else docEmpty
importHead = docSeq [importQualifiers, modNameD] importHead = docSeq [importQualifiers, modNameD]
bindingsD = case mllies of bindingsD = case mllies of
Nothing -> docSeq [docEmpty] Nothing -> docEmpty
Just (_, llies) -> do Just (_, llies) -> do
ieDs <- layoutAnnAndSepLLIEs llies
hasComments <- hasAnyCommentsBelow llies hasComments <- hasAnyCommentsBelow llies
if compact
then docSeq [hidDoc, layoutLLIEs llies]
else do
ieDs <- layoutAnnAndSepLLIEs llies
docWrapNodeRest llies $ case ieDs of docWrapNodeRest llies $ case ieDs of
-- ..[hiding].( ) -- ..[hiding].( )
[] -> if hasComments [] -> if hasComments
@ -106,15 +111,21 @@ layoutImport limportD@(L _ importD) = docWrapNode limportD $ case importD of
++ [docParenR] ++ [docParenR]
bindingLine = bindingLine =
docEnsureIndent (BrIndentSpecial (importCol - bindingCost)) bindingsD docEnsureIndent (BrIndentSpecial (importCol - bindingCost)) bindingsD
case asT of makeAsDoc asT =
docSeq [appSep $ docLit $ Text.pack "as", appSep $ docLit asT]
if compact
then
let asDoc = maybe docEmpty makeAsDoc masT
in docSeq [importHead, asDoc, docSetBaseY $ bindingsD]
else
case masT of
Just n | enoughRoom -> docLines [docSeq [importHead, asDoc], bindingLine] Just n | enoughRoom -> docLines [docSeq [importHead, asDoc], bindingLine]
| otherwise -> docLines [importHead, asDoc, bindingLine] | otherwise -> docLines [importHead, asDoc, bindingLine]
where where
enoughRoom = nameCost < importCol - asCost enoughRoom = nameCost < importCol - asCost
asDoc = asDoc =
docEnsureIndent (BrIndentSpecial (importCol - asCost)) docEnsureIndent (BrIndentSpecial (importCol - asCost))
$ docSeq $ makeAsDoc n
$ [appSep $ docLit $ Text.pack "as", docLit n]
Nothing | enoughRoom -> docSeq [importHead, bindingLine] Nothing | enoughRoom -> docSeq [importHead, bindingLine]
| otherwise -> docLines [importHead, bindingLine] | otherwise -> docLines [importHead, bindingLine]
where enoughRoom = nameCost < importCol - bindingCost where enoughRoom = nameCost < importCol - bindingCost

View File

@ -24,31 +24,25 @@ import Language.Haskell.Brittany.Internal.Utils
layoutModule :: ToBriDoc HsModule layoutModule :: ToBriDoc HsModule
layoutModule lmod@(L _ mod') = do layoutModule lmod@(L _ mod') =
case mod' of case mod' of
-- Implicit module Main -- Implicit module Main
HsModule Nothing _ imports _ _ _ -> docLines $ map layoutImport imports HsModule Nothing _ imports _ _ _ -> docLines $ map layoutImport imports
HsModule (Just n) les imports _ _ _ -> do HsModule (Just n) les imports _ _ _ -> do
let tn = Text.pack $ moduleNameString $ unLoc n let tn = Text.pack $ moduleNameString $ unLoc n
(hasComments, exportsDoc) <- case les of exportsDoc = maybe docEmpty layoutLLIEs les
Nothing -> return (False, docEmpty)
Just llies -> do
hasComments <- hasAnyCommentsBelow llies
exportsDoc <- docSharedWrapper layoutLLIEs llies
return (hasComments, exportsDoc)
docLines docLines
$ docSeq $ docSeq
[ docWrapNode lmod $ docEmpty [ docWrapNode lmod docEmpty
-- A pseudo node that serves merely to force documentation -- A pseudo node that serves merely to force documentation
-- before the node -- before the node
, docAlt , docAlt
( [ docSeq ( [ docForceSingleline $ docSeq
[ appSep $ docLit $ Text.pack "module" [ appSep $ docLit $ Text.pack "module"
, appSep $ docLit tn , appSep $ docLit tn
, appSep $ docForceSingleline exportsDoc , appSep exportsDoc
, docLit $ Text.pack "where" , docLit $ Text.pack "where"
] ]
| not hasComments
] ]
++ [ docLines ++ [ docLines
[ docAddBaseY BrIndentRegular $ docPar [ docAddBaseY BrIndentRegular $ docPar