From 33f23a65ec44d70aecde50dcdaf16b09a4f8c470 Mon Sep 17 00:00:00 2001
From: Lennart Spitzner <hexagoxel@hexagoxel.de>
Date: Thu, 21 Dec 2017 15:44:58 +0100
Subject: [PATCH] Refactor and Add missing docSharedWrapper

---
 .../Haskell/Brittany/Internal/Layouters/IE.hs | 15 +++--
 .../Brittany/Internal/Layouters/Import.hs     | 55 +++++++++----------
 .../Brittany/Internal/Layouters/Module.hs     | 11 ++--
 3 files changed, 41 insertions(+), 40 deletions(-)

diff --git a/src/Language/Haskell/Brittany/Internal/Layouters/IE.hs b/src/Language/Haskell/Brittany/Internal/Layouters/IE.hs
index 3daf877..926f642 100644
--- a/src/Language/Haskell/Brittany/Internal/Layouters/IE.hs
+++ b/src/Language/Haskell/Brittany/Internal/Layouters/IE.hs
@@ -71,12 +71,15 @@ layoutIE lie@(L _ ie) = docWrapNode lie $ case ie of
 -- left to the caller since that is context sensitive
 layoutAnnAndSepLLIEs :: (Located [LIE RdrName]) -> ToBriDocM [ToBriDocM BriDocNumbered]
 layoutAnnAndSepLLIEs llies@(L _ lies) = do
-  let makeIENode ie = docSeq [docCommaSep, ie]
-      layoutAnnAndSepLLIEs' ies = case ies of
-          [] -> []
-          [ie] -> [docWrapNode llies $ ie]
-          (ie:ies') -> ie:map makeIENode (List.init ies')
-                 ++ [makeIENode $ docWrapNode llies $ List.last ies']
+  let
+    makeIENode ie = docSeq [docCommaSep, ie]
+    layoutAnnAndSepLLIEs' ies = case splitFirstLast ies of
+      FirstLastEmpty        -> []
+      FirstLastSingleton ie -> [docWrapNodeRest llies $ ie]
+      FirstLast ie1 ieMs ieN ->
+        [ie1]
+          ++ map makeIENode ieMs
+          ++ [makeIENode $ docWrapNodeRest llies $ ieN]
   layoutAnnAndSepLLIEs' <$> mapM (docSharedWrapper layoutIE) lies
 
 -- Builds a complete layout for the given located
diff --git a/src/Language/Haskell/Brittany/Internal/Layouters/Import.hs b/src/Language/Haskell/Brittany/Internal/Layouters/Import.hs
index cc4172f..7aac868 100644
--- a/src/Language/Haskell/Brittany/Internal/Layouters/Import.hs
+++ b/src/Language/Haskell/Brittany/Internal/Layouters/Import.hs
@@ -46,13 +46,16 @@ layoutImport :: ToBriDoc ImportDecl
 layoutImport limportD@(L _ importD) = docWrapNode limportD $ case importD of
   ImportDecl _ (L _ modName) pkg src safe q False as mllies -> do
     importCol <- mAsk <&> _conf_layout .> _lconfig_importColumn .> confUnpack
+    -- NB we don't need to worry about sharing in the below code
+    -- (docSharedWrapper etc.) because we do not use any docAlt nodes; all
+    -- "decisions" are made statically.
     let
-      modNameT        = Text.pack $ moduleNameString modName
-      pkgNameT        = Text.pack . prepPkg . sl_st <$> pkg
-      asT             = Text.pack . moduleNameString . prepModName <$> as
-      hiding = case mllies of
+      modNameT = Text.pack $ moduleNameString modName
+      pkgNameT = Text.pack . prepPkg . sl_st <$> pkg
+      asT      = Text.pack . moduleNameString . prepModName <$> as
+      hiding   = case mllies of
         Just (h, _) -> h
-        Nothing             -> False
+        Nothing     -> False
       minQLength = length "import qualified "
       qLengthReal =
         let qualifiedPart = if q then length "qualified " else 0
@@ -76,37 +79,31 @@ layoutImport limportD@(L _ importD) = docWrapNode limportD $ case importD of
         docEnsureIndent (BrIndentSpecial qLength) $ appSep $ docLit modNameT
       hidDoc =
         if hiding then appSep $ docLit $ Text.pack "hiding" else docEmpty
-      importHead      = docSeq [importQualifiers, modNameD]
-      bindingsH = docParenLSep
-      bindingsT = [docSeq [docSeparator, docParenR]]
-      bindingsD = case mllies of
-        Nothing -> docSeq [docEmpty]
+      importHead = docSeq [importQualifiers, modNameD]
+      bindingsD  = case mllies of
+        Nothing         -> docSeq [docEmpty]
         Just (_, llies) -> do
-          ieDs <- layoutAnnAndSepLLIEs llies
+          ieDs        <- layoutAnnAndSepLLIEs llies
           hasComments <- hasAnyCommentsBelow llies
-          case ieDs of
+          docWrapNodeRest llies $ case ieDs of
             -- ..[hiding].( )
-            [] -> do
-              if hasComments
-              then
-                docWrapNodeRest llies $ docPar (docSeq [hidDoc, bindingsH, docWrapNode llies docEmpty]) $ docLines
-                  bindingsT
-              else
-                docWrapNodeRest llies $ docSeq $ hidDoc : bindingsH : bindingsT
+            [] -> if hasComments
+              then docPar
+                (docSeq [hidDoc, docParenLSep, docWrapNode llies docEmpty])
+                docParenR
+              else docSeq [hidDoc, docParenLSep, docSeparator, docParenR]
             -- ..[hiding].( b )
-            [ieD] ->  do
-              if hasComments
-              then
-                docWrapNodeRest llies $ docPar (docSeq [hidDoc, bindingsH, ieD ]) $ docLines $
-                  bindingsT
-              else
-                docWrapNodeRest llies $ docSeq $ hidDoc : bindingsH : ieD : bindingsT
+            [ieD] -> if hasComments
+              then docPar (docSeq [hidDoc, docParenLSep, ieD]) docParenR
+              else docSeq [hidDoc, docParenLSep, ieD, docSeparator, docParenR]
             -- ..[hiding].( b
             --            , b'
             --            )
-            (ieD:ieDs') -> do
-                docWrapNodeRest llies $ docPar (docSeq [hidDoc, docSetBaseY $ docSeq [bindingsH, ieD]])
-                  $ docLines $ ieDs' ++ bindingsT
+            (ieD:ieDs') ->
+              docPar (docSeq [hidDoc, docSetBaseY $ docSeq [docParenLSep, ieD]])
+                $  docLines
+                $  ieDs'
+                ++ [docParenR]
       bindingLine =
         docEnsureIndent (BrIndentSpecial (importCol - bindingCost)) bindingsD
     case asT of
diff --git a/src/Language/Haskell/Brittany/Internal/Layouters/Module.hs b/src/Language/Haskell/Brittany/Internal/Layouters/Module.hs
index 509b24a..c0f569b 100644
--- a/src/Language/Haskell/Brittany/Internal/Layouters/Module.hs
+++ b/src/Language/Haskell/Brittany/Internal/Layouters/Module.hs
@@ -30,11 +30,12 @@ layoutModule lmod@(L _ mod') = do
     HsModule Nothing  _   imports _ _ _ -> docLines $ map layoutImport imports
     HsModule (Just n) les imports _ _ _ -> do
       let tn = Text.pack $ moduleNameString $ unLoc n
-      (hasComments, es) <- case les of
-        Nothing               -> return (False, docEmpty)
+      (hasComments, exportsDoc) <- case les of
+        Nothing    -> return (False, docEmpty)
         Just llies -> do
           hasComments <- hasAnyCommentsBelow llies
-          return (hasComments, layoutLLIEs llies)
+          exportsDoc  <- docSharedWrapper layoutLLIEs llies
+          return (hasComments, exportsDoc)
       docLines
         $ docSeq
             [ docWrapNode lmod $ docEmpty
@@ -44,7 +45,7 @@ layoutModule lmod@(L _ mod') = do
               (  [ docSeq
                      [ appSep $ docLit $ Text.pack "module"
                      , appSep $ docLit tn
-                     , appSep $ docForceSingleline es
+                     , appSep $ docForceSingleline exportsDoc
                      , docLit $ Text.pack "where"
                      ]
                  | not hasComments
@@ -54,7 +55,7 @@ layoutModule lmod@(L _ mod') = do
                        ( docSeq
                          [appSep $ docLit $ Text.pack "module", docLit tn]
                        )
-                       (docForceMultiline es)
+                       (docForceMultiline exportsDoc)
                      , docLit $ Text.pack "where"
                      ]
                  ]