packages feed

fourmolu 0.5.0.1 → 0.6.0.0

raw patch · 53 files changed

+408/−44 lines, 53 filesnew-uploaderPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Ormolu: [poImportExportCommaStyle] :: PrinterOpts f -> f CommaStyle
+ Ormolu.Config: [poImportExportCommaStyle] :: PrinterOpts f -> f CommaStyle
+ Ormolu.Printer: [poImportExportCommaStyle] :: PrinterOpts f -> f CommaStyle
+ Ormolu.Printer.Combinators: inciBy :: Int -> R () -> R ()
+ Ormolu.Utils: FirstAfterDocPos :: RelativePos
- Ormolu: PrinterOpts :: f Int -> f CommaStyle -> f Bool -> f Bool -> f Bool -> f Bool -> f HaddockPrintStyle -> f Int -> PrinterOpts f
+ Ormolu: PrinterOpts :: f Int -> f CommaStyle -> f CommaStyle -> f Bool -> f Bool -> f Bool -> f Bool -> f HaddockPrintStyle -> f Int -> PrinterOpts f
- Ormolu.Config: PrinterOpts :: f Int -> f CommaStyle -> f Bool -> f Bool -> f Bool -> f Bool -> f HaddockPrintStyle -> f Int -> PrinterOpts f
+ Ormolu.Config: PrinterOpts :: f Int -> f CommaStyle -> f CommaStyle -> f Bool -> f Bool -> f Bool -> f Bool -> f HaddockPrintStyle -> f Int -> PrinterOpts f
- Ormolu.Printer: PrinterOpts :: f Int -> f CommaStyle -> f Bool -> f Bool -> f Bool -> f Bool -> f HaddockPrintStyle -> f Int -> PrinterOpts f
+ Ormolu.Printer: PrinterOpts :: f Int -> f CommaStyle -> f CommaStyle -> f Bool -> f Bool -> f Bool -> f Bool -> f HaddockPrintStyle -> f Int -> PrinterOpts f

Files

CHANGELOG.md view
@@ -1,3 +1,10 @@+## Fourmolu 0.6.0.0++* Fixed regression in 0.5.0.0 with multiline tuples ([#162](https://github.com/fourmolu/fourmolu/pull/162))+* Fixed regression in 0.5.0.0 with multiline record types ([#160](https://github.com/fourmolu/fourmolu/pull/160))+* Fixed regression in 0.5.0.0 with indentation after a list comprehension ([#149](https://github.com/fourmolu/fourmolu/pull/149))+* Add `import-export-comma-style` configuration to allow leading commas in module import/export lists+ ## Fourmolu 0.5.0.0  * Fixed issue with leading commas in guards ([#123](https://github.com/fourmolu/fourmolu/pull/123))
README.md view
@@ -43,6 +43,7 @@ ```yaml indentation: 4 comma-style: leading # for lists, tuples etc. - can also be 'trailing'+import-export-comma-style: leading # for module import export lists - can also be 'trailing' record-brace-space: false # rec {x = 1} vs. rec{x = 1} indent-wheres: false # 'false' means save space by only half-indenting the 'where' keyword diff-friendly-import-export: true # 'false' uses Ormolu-style lists@@ -56,6 +57,7 @@ ```yaml indentation: 2 comma-style: trailing+import-export-comma-style: trailing record-brace-space: true indent-wheres: true diff-friendly-import-export: false
app/Main.hs view
@@ -333,6 +333,15 @@             <> showAllValues @CommaStyle             <> showDefaultValue poCommaStyle       ]+  poImportExportCommaStyle <-+    (optional . option parseBoundedEnum . mconcat)+      [ long "import-export-comma-style",+        metavar "IESTYLE",+        help $+          "How to place commas in multi-line import and export lists: "+            <> showAllValues @CommaStyle+            <> showDefaultValue poImportExportCommaStyle+      ]   poIndentWheres <-     (optional . option parseBoundedEnum . mconcat)       [ long "indent-wheres",
+ data/examples/import/comments-inside-imports-four-ie-out.hs view
@@ -0,0 +1,8 @@+import -- x+    Foo++import qualified -- x+    Bar++import qualified -- x+    Baz
+ data/examples/import/comments-per-import-four-ie-out.hs view
@@ -0,0 +1,4 @@+-- (1)+import Bar -- (2)+import Baz -- (3)+import Foo
+ data/examples/import/deduplication-bug-four-ie-out.hs view
@@ -0,0 +1,6 @@+import Foo1 (Bar1 (..), Baz1)+import Foo2 (Bar2 (..), Baz2)+import Foo3 (Bar3 (x1, x2, x3))+import Foo4 (Bar4 (x1, x2))+import Foo5 (Bar5 (x1))+import Foo6 (Bar6 (..))
+ data/examples/import/explicit-imports-four-ie-out.hs view
@@ -0,0 +1,12 @@+import qualified MegaModule as M+    ( Either+    , Maybe (Just, Nothing)+    , MaybeT (..)+    , Monad (return, (>>), (>>=))+    , MonadBaseControl+    , join+    , liftIO+    , void+    , (<<<)+    , (>>>)+    )
+ data/examples/import/explicit-imports-with-comments-four-ie-out.hs view
@@ -0,0 +1,7 @@+import qualified MegaModule as M+    ( -- (1)+      -- (2)+      Either -- (3)+    , (<<<)+    , (>>>)+    )
+ data/examples/import/explicit-prelude-four-ie-out.hs view
@@ -0,0 +1,3 @@+import Aaa+import Zzz+import Prelude
+ data/examples/import/merging-0-four-ie-out.hs view
@@ -0,0 +1,3 @@+import Foo+import Foo (bar, foo)+import Foo as F
+ data/examples/import/merging-1-four-ie-out.hs view
@@ -0,0 +1,2 @@+import "bar" Foo (bar)+import "foo" Foo (baz, foo)
+ data/examples/import/merging-2-four-ie-out.hs view
@@ -0,0 +1,2 @@+import Foo hiding (bar4, foo2)+import qualified Foo (bar3, foo1)
+ data/examples/import/misc-four-ie-out.hs view
@@ -0,0 +1,7 @@+import A hiding+    ( foobarbazqux+    )++import Name hiding ()++import {-# SOURCE #-} safe qualified Module as M hiding (a, b, c, d, e, f)
+ data/examples/import/nested-explicit-imports-four-ie-out.hs view
@@ -0,0 +1,10 @@+import qualified MegaModule as M+    ( Either+    , Monad+        ( return,+        (>>),+        (>>=)+        )+    , (<<<)+    , (>>>)+    )
+ data/examples/import/qualified-post-four-ie-out.hs view
@@ -0,0 +1,5 @@+{-# LANGUAGE ImportQualifiedPost #-}++import Data.Text qualified (a, b, c)+import Data.Text qualified hiding (a, b, c)+import Data.Text qualified as T
+ data/examples/import/qualified-prelude-four-ie-out.hs view
@@ -0,0 +1,4 @@+module P where++import Prelude hiding (id, (.))+import qualified Prelude
+ data/examples/import/simple-four-ie-out.hs view
@@ -0,0 +1,5 @@+import Data.Text+import Data.Text (a, b, c)+import Data.Text hiding (a, b, c)+import qualified Data.Text (a, b, c)+import qualified Data.Text as T
+ data/examples/import/sorted-export-list-four-ie-out.hs view
@@ -0,0 +1,1 @@+import Linear.Vector (Additive (..), (*^), (^*))
+ data/examples/import/sorted-four-ie-out.hs view
@@ -0,0 +1,3 @@+import A+import B+import C
+ data/examples/module-header/double-dot-with-names-four-ie-out.hs view
@@ -0,0 +1,17 @@+{-# LANGUAGE PatternSynonyms #-}++module ExportSyntax (A (.., NoA), Q (F, ..), G (T, .., U)) where++data A = A | B++pattern NoA = B++data Q a = Q a++pattern F a = Q a++data G = G | H++pattern T = G++pattern U = H
+ data/examples/module-header/double-shebangs-four-ie-out.hs view
@@ -0,0 +1,2 @@+#!/usr/bin/env stack+#!/usr/bin/env stack
+ data/examples/module-header/empty-four-ie-out.hs view
+ data/examples/module-header/empty-haddock-four-ie-out.hs view
@@ -0,0 +1,1 @@+module Test where
+ data/examples/module-header/leading-empty-line-four-ie-out.hs view
@@ -0,0 +1,12 @@+{- |+ Module      :  Text.Megaparsec+ Copyright   :  © 2015–2019 Megaparsec contributors+                © 2007 Paolo Martini+                © 1999–2001 Daan Leijen+ License     :  FreeBSD++ Maintainer  :  Mark Karpov <markkarpov92@gmail.com>+ Stability   :  experimental+ Portability :  portable+-}+module Main where
+ data/examples/module-header/multiline-empty-four-ie-out.hs view
@@ -0,0 +1,4 @@+module Foo+    (+    )+where
+ data/examples/module-header/multiline-four-ie-out.hs view
@@ -0,0 +1,6 @@+module Foo+    ( foo+    , bar+    , baz+    )+where
+ data/examples/module-header/multiline-with-comments-four-ie-out.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}++-- | Header.+module My.Module+    ( -- * Something+      foo+    , bar+      -- | A multiline+      -- comment here+    , bar2++      -- * Another thing+    , (<?>)+    {- some other thing -} , foo2 -- yet another+    , foo3 -- third one+    , baz+    , bar2 -- a multiline comment+    -- the second line+    , bar3+    , module Foo.Bar.Baz+    )+where++-- Wow
+ data/examples/module-header/multiline2-four-ie-out.hs view
@@ -0,0 +1,6 @@+module Foo+    ( foo+    , bar+    , baz+    )+where
+ data/examples/module-header/named-section-four-ie-out.hs view
@@ -0,0 +1,14 @@+module Magic+    ( -- * Something+      -- $explanation++      -- ** Another level+      foo+    , bar+    )+where++{- $explanation++ Here it goes.+-}
+ data/examples/module-header/preceding-comment-with-haddock-four-ie-out.hs view
@@ -0,0 +1,8 @@+{-+   Here we go.+-}++-- | This is the module's Haddock.+module Main (main) where++main = return ()
+ data/examples/module-header/shebang-four-ie-out.hs view
@@ -0,0 +1,6 @@+#! /usr/bin/env runhaskell++import Prelude++main :: IO ()+main = putStrLn "hello world"
+ data/examples/module-header/shebang-with-pragmas-four-ie-out.hs view
@@ -0,0 +1,5 @@+#!/usr/bin/env stack++{-# LANGUAGE OverloadedStrings #-}++main = pure ()
+ data/examples/module-header/simple-four-ie-out.hs view
@@ -0,0 +1,1 @@+module Main where
+ data/examples/module-header/simple-with-comments-four-ie-out.hs view
@@ -0,0 +1,4 @@+-- | Here we go.+module Main where++-- Wow.
+ data/examples/module-header/singleline-empty-four-ie-out.hs view
@@ -0,0 +1,2 @@+-- | This demonstrates a BUG.+module Foo () where
+ data/examples/module-header/singleline-four-ie-out.hs view
@@ -0,0 +1,1 @@+module Foo (foo, bar, baz) where
+ data/examples/module-header/stack-header-0-four-ie-out.hs view
@@ -0,0 +1,7 @@+-- stack runhaskell++{-# LANGUAGE OverloadedStrings #-}++main = return ()++-- stack runhaskell
+ data/examples/module-header/stack-header-1-four-ie-out.hs view
@@ -0,0 +1,8 @@+#!/usr/bin/env stack+-- stack runhaskell++{-# LANGUAGE OverloadedStrings #-}++main = return ()++-- stack runhaskell
+ data/examples/module-header/stack-header-2-four-ie-out.hs view
@@ -0,0 +1,12 @@+#!/usr/bin/env stack+{- stack+  script+  --resolver lts-6.25+  --package turtle+  --package "stm async"+  --package http-client,http-conduit+-}++{-# LANGUAGE OverloadedStrings #-}++main = return ()
+ data/examples/module-header/warning-pragma-four-ie-out.hs view
@@ -0,0 +1,5 @@+module Test+    {-# WARNING+        "This module is very internal"+        #-}+where
+ data/examples/module-header/warning-pragma-list-multiline-four-ie-out.hs view
@@ -0,0 +1,11 @@+module Test+    {-# DEPRECATED+        [ "This module is deprecated."+        , "Please use OtherModule instead."+        ]+        #-}+    ( foo+    , bar+    , baz+    )+where
+ data/examples/module-header/warning-pragma-multiline-four-ie-out.hs view
@@ -0,0 +1,6 @@+module Test+    {-# DEPRECATED "This module is unstable" #-}+    (foo, bar, baz)+where++import Blah
+ data/examples/module-header/warning-pragma-singleton-list-four-ie-out.hs view
@@ -0,0 +1,1 @@+module Test {-# WARNING "There's only one line here." #-} where
+ data/examples/other/empty-haddock-four-ie-out.hs view
@@ -0,0 +1,7 @@+module Test+  ( test+  )+where++test ::+  test
fourmolu.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.4 name:               fourmolu-version:            0.5.0.1+version:            0.6.0.0 license:            BSD-3-Clause license-file:       LICENSE.md maintainer:@@ -124,7 +124,7 @@         filepath >=1.2 && <1.5,         ghc-lib-parser >=9.2 && <9.3,         gitrev >=1.3 && <1.4,-        optparse-applicative >=0.14 && <0.17,+        optparse-applicative >=0.14 && <0.18,         text >=0.2 && <1.3      if flag(dev)
src/Ormolu/Config.hs view
@@ -126,6 +126,8 @@     poIndentation :: f Int,     -- | Whether to place commas at start or end of lines     poCommaStyle :: f CommaStyle,+    -- | Whether to place commas at start or end of import-export lines+    poImportExportCommaStyle :: f CommaStyle,     -- | Whether to indent `where` blocks     poIndentWheres :: f Bool,     -- | Leave space before opening record brace@@ -153,7 +155,7 @@   (<>) = fillMissingPrinterOpts  instance Monoid PrinterOptsPartial where-  mempty = PrinterOpts Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing+  mempty = PrinterOpts Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing  -- | A version of 'PrinterOpts' without empty fields. type PrinterOptsTotal = PrinterOpts Identity@@ -167,6 +169,7 @@   PrinterOpts     { poIndentation = pure 4,       poCommaStyle = pure Leading,+      poImportExportCommaStyle = pure Trailing,       poIndentWheres = pure False,       poRecordBraceSpace = pure False,       poDiffFriendlyImportExport = pure True,@@ -187,6 +190,7 @@   PrinterOpts     { poIndentation = fillField poIndentation,       poCommaStyle = fillField poCommaStyle,+      poImportExportCommaStyle = fillField poImportExportCommaStyle,       poIndentWheres = fillField poIndentWheres,       poRecordBraceSpace = fillField poRecordBraceSpace,       poDiffFriendlyImportExport = fillField poDiffFriendlyImportExport,
src/Ormolu/Printer/Combinators.hs view
@@ -22,6 +22,7 @@     newline,     declNewline,     inci,+    inciBy,     inciIf,     inciByFrac,     inciHalf,
src/Ormolu/Printer/Meat/Declaration/Data.hs view
@@ -157,7 +157,7 @@     mapM_ (p_hsDocString Pipe True) con_doc     let conDeclWithContextSpn =           [RealSrcSpan real Nothing | AddEpAnn AnnForall (EpaSpan real) <- epAnnAnns con_ext]-          <> fmap getLocA con_ex_tvs+            <> fmap getLocA con_ex_tvs             <> maybeToList (fmap getLocA con_mb_cxt)             <> conDeclSpn         conDeclSpn = getLocA con_name : conArgsSpans
src/Ormolu/Printer/Meat/Declaration/Value.hs view
@@ -44,7 +44,7 @@ import GHC.Types.SrcLoc import Ormolu.Config import Ormolu.Printer.Combinators-import Ormolu.Printer.Internal (inciBy, sitccIfTrailing)+import Ormolu.Printer.Internal (sitccIfTrailing) import Ormolu.Printer.Meat.Common import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration import Ormolu.Printer.Meat.Declaration.Signature@@ -525,6 +525,7 @@           FirstPos -> br           MiddlePos -> br           LastPos -> id+          FirstAfterDocPos -> br         p_item' (p, item) =           positionToBracing p $             withSpacing (either p_valDecl p_sigDecl) item@@ -719,9 +720,10 @@         isMissing = \case           Missing _ -> True           _ -> False-        p_arg = \case-          Present _ x -> located x p_hsExprListItem-          Missing _ -> pure ()+        p_arg =+          sitcc . \case+            Present _ x -> located x p_hsExprListItem+            Missing _ -> pure ()         parens' =           case boxity of             Boxed -> parens@@ -1379,13 +1381,22 @@                 p_op                 space                 p_y-          case x of-            -- This case prevents an operator from being indented past the start of a `do` block-            -- constituting its left operand, thus altering the AST.-            -- This is only relevant when the `do` block is on one line, as otherwise we will-            -- insert a newline after `do` anyway.-            OpNode (unLoc -> HsDo _ _ _) | isOneLineSpan (opTreeLoc x) -> breakpoint >> opAndRhs-            _ -> placeHanging placement opAndRhs+              -- distinguish do-block from list comprehensions, which are+              -- apparently parsed as `HsDo _ ListComp _`+              isActualDoBlock = \case+                OpNode (unLoc -> HsDo _ ctx _) ->+                  case ctx of+                    DoExpr _ -> True+                    MDoExpr _ -> True+                    _ -> False+                _ -> False+          -- This case prevents an operator from being indented past the start of a `do` block+          -- constituting its left operand, thus altering the AST.+          -- This is only relevant when the `do` block is on one line, as otherwise we will+          -- insert a newline after `do` anyway.+          if isActualDoBlock x && isOneLineSpan (opTreeLoc x)+            then breakpoint >> opAndRhs+            else placeHanging placement opAndRhs  pattern CmdTopCmd :: HsCmd GhcPs -> LHsCmdTop GhcPs pattern CmdTopCmd cmd <- (L _ (HsCmdTop _ (L _ cmd)))
src/Ormolu/Printer/Meat/ImportExport.hs view
@@ -16,11 +16,13 @@ import GHC.LanguageExtensions.Type import GHC.Types.SrcLoc import GHC.Unit.Types-import Ormolu.Config (poDiffFriendlyImportExport)+import Ormolu.Config (CommaStyle (..), PrinterOpts (poImportExportCommaStyle), poDiffFriendlyImportExport) import Ormolu.Printer.Combinators import Ormolu.Printer.Meat.Common import Ormolu.Utils (RelativePos (..), attachRelativePos) +{- HLINT ignore "Use camelCase" -}+ p_hsmodExports :: [LIE GhcPs] -> R () p_hsmodExports [] = do   txt "("@@ -32,7 +34,7 @@     sep       breakpoint       (\(p, l) -> sitcc (located l (p_lie layout p)))-      (attachRelativePos xs)+      (attachRelativePos' xs)  p_hsmodImport :: ImportDecl GhcPs -> R () p_hsmodImport ImportDecl {..} = do@@ -82,18 +84,17 @@  p_lie :: Layout -> RelativePos -> IE GhcPs -> R () p_lie encLayout relativePos = \case-  IEVar NoExtField l1 -> do-    located l1 p_ieWrappedName-    p_comma-  IEThingAbs _ l1 -> do-    located l1 p_ieWrappedName-    p_comma-  IEThingAll _ l1 -> do+  IEVar NoExtField l1 ->+    withComma $+      located l1 p_ieWrappedName+  IEThingAbs _ l1 ->+    withComma $+      located l1 p_ieWrappedName+  IEThingAll _ l1 -> withComma $ do     located l1 p_ieWrappedName     space     txt "(..)"-    p_comma-  IEThingWith _ l1 w xs -> sitcc $ do+  IEThingWith _ l1 w xs -> sitcc . withComma $ do     located l1 p_ieWrappedName     breakIfNotDiffFriendly     inci $ do@@ -105,32 +106,78 @@           IEWildcard n ->             let (before, after) = splitAt n names              in before ++ [txt ".."] ++ after-    p_comma-  IEModuleContents _ l1 -> do-    located l1 p_hsmodName-    p_comma+  IEModuleContents _ l1 -> withComma $ do+    indentDoc $ located l1 p_hsmodName   IEGroup NoExtField n str -> do     case relativePos of       SinglePos -> return ()       FirstPos -> return ()       MiddlePos -> newline       LastPos -> newline-    p_hsDocString (Asterisk n) False (noLoc str)+      FirstAfterDocPos -> newline+    indentDoc $ p_hsDocString (Asterisk n) False (noLoc str)   IEDoc NoExtField str ->-    p_hsDocString Pipe False (noLoc str)-  IEDocNamed NoExtField str -> txt $ "-- $" <> T.pack str+    indentDoc $+      p_hsDocString Pipe False (noLoc str)+  IEDocNamed NoExtField str -> indentDoc $ txt $ "-- $" <> T.pack str   where-    p_comma =+    -- Add a comma to a import-export list element+    withComma m =       case encLayout of         SingleLine ->           case relativePos of-            SinglePos -> return ()-            FirstPos -> comma-            MiddlePos -> comma-            LastPos -> return ()-        MultiLine -> comma+            SinglePos -> void m+            FirstPos -> m >> comma+            MiddlePos -> m >> comma+            LastPos -> void m+            FirstAfterDocPos -> m >> comma+        MultiLine -> do+          commaStyle <- getPrinterOpt poImportExportCommaStyle+          case commaStyle of+            Leading ->+              case relativePos of+                FirstPos -> m+                FirstAfterDocPos -> inciBy 2 m+                SinglePos -> m+                _ -> comma >> space >> m+            Trailing -> m >> comma+    indentDoc m = do+      commaStyle <- getPrinterOpt poImportExportCommaStyle+      case commaStyle of+        Trailing -> m+        Leading ->+          case relativePos of+            SinglePos -> m+            FirstPos -> m+            _ -> inciBy 2 m  ----------------------------------------------------------------------------++-- | Unlike the version in `Ormolu.Utils`, this version handles explicitly leading export documentation+attachRelativePos' :: [LIE GhcPs] -> [(RelativePos, LIE GhcPs)]+attachRelativePos' = \case+  [] -> []+  [x] -> [(SinglePos, x)]+  -- Check if leading export is a Doc+  (x@(L _ IEDoc {}) : xs) -> (FirstPos, x) : markDoc xs+  (x@(L _ IEGroup {}) : xs) -> (FirstPos, x) : markDoc xs+  (x@(L _ IEDocNamed {}) : xs) -> (FirstPos, x) : markDoc xs+  (x : xs) -> (FirstPos, x) : markLast xs+  where+    -- Mark leading documentation, making sure the first export gets assigned+    -- a `FirstPos`+    markDoc [] = []+    markDoc [x] = [(LastPos, x)]+    markDoc (x@(L _ IEDoc {}) : xs) = (FirstAfterDocPos, x) : markDoc xs+    markDoc (x@(L _ IEGroup {}) : xs) = (FirstAfterDocPos, x) : markDoc xs+    markDoc (x@(L _ IEDocNamed {}) : xs) = (FirstAfterDocPos, x) : markDoc xs+    -- First export after a Doc gets assigned a `FirstPos`+    markDoc (x : xs) = (FirstAfterDocPos, x) : markLast xs++    markLast [] = []+    markLast [x] = [(LastPos, x)]+    markLast (x : xs) = (MiddlePos, x) : markLast xs+ -- Unlike the versions in 'Ormolu.Printer.Combinators', these do not depend on -- whether 'leadingCommas' is set. This is useful here is we choose to keep -- import and export lists independent of that setting.@@ -156,9 +203,18 @@     body = vlayout singleLine multiLine     singleLine = m     multiLine = do-      space-      sitcc m-      newline+      commaStyle <- getPrinterOpt poImportExportCommaStyle+      case commaStyle of+        -- On leading commas, list elements are inline with the enclosing parentheses+        Leading -> do+          space+          m+          newline+        -- On trailing commas, list elements are indented+        Trailing -> do+          space+          sitcc m+          newline     trailingParen = if topLevelImport then txt " )" else txt ")"  breakIfNotDiffFriendly :: R ()
src/Ormolu/Printer/Meat/Type.hs view
@@ -259,7 +259,7 @@  p_conDeclFields :: [LConDeclField GhcPs] -> R () p_conDeclFields xs =-  braces N $ sep commaDel (located' p_conDeclField) xs+  braces N $ sep commaDel (sitcc . located' p_conDeclField) xs  p_conDeclField :: ConDeclField GhcPs -> R () p_conDeclField ConDeclField {..} = do@@ -276,7 +276,7 @@   breakpoint   sitcc . inci $ p_hsType (unLoc cd_fld_type)   when (commaStyle == Leading) $-    mapM_ ((newline >>) . p_hsDocString Caret False) cd_fld_doc+    mapM_ (inciByFrac (-1) . (newline >>) . p_hsDocString Caret False) cd_fld_doc  tyOpTree :: LHsType GhcPs -> OpTree (LHsType GhcPs) (LocatedN RdrName) tyOpTree (L _ (HsOpTy _ l op r)) =
src/Ormolu/Utils.hs view
@@ -38,6 +38,7 @@   | FirstPos   | MiddlePos   | LastPos+  | FirstAfterDocPos   deriving (Eq, Show)  -- | Attach 'RelativePos'es to elements of a given list.
tests/Ormolu/PrinterSpec.hs view
@@ -22,10 +22,12 @@ spec :: Spec spec = do   es <- runIO locateExamples+  ieEs <- runIO locateIEExamples   let ormoluOpts =         PrinterOpts           { poIndentation = pure 2,             poCommaStyle = pure Trailing,+            poImportExportCommaStyle = pure Trailing,             poIndentWheres = pure True,             poRecordBraceSpace = pure True,             poDiffFriendlyImportExport = pure False,@@ -33,7 +35,13 @@             poHaddockStyle = pure HaddockSingleLine,             poNewlinesBetweenDecls = pure 1           }+  let fourmoluIEOpts =+        defaultPrinterOpts+          { poImportExportCommaStyle = pure Leading,+            poDiffFriendlyImportExport = pure False+          }   sequence_ $ checkExample <$> [(ormoluOpts, "ormolu", ""), (defaultPrinterOpts, "fourmolu", "-four")] <*> es+  sequence_ $ checkExample <$> [(fourmoluIEOpts, "fourmolu-ie", "-four-ie")] <*> ieEs  -- | Check a single given example. checkExample :: (PrinterOptsTotal, String, String) -> Path Rel File -> Spec@@ -67,6 +75,11 @@ locateExamples =   filter isInput . snd <$> listDirRecurRel examplesDir +-- | Build list of examples for testing import export lists comma behaviour.+locateIEExamples :: IO [Path Rel File]+locateIEExamples = do+  filter isIEInput . snd <$> listDirRecurRel examplesDir+ -- | Does given path look like input path (as opposed to expected output -- path)? isInput :: Path Rel File -> Bool@@ -74,6 +87,13 @@   let s = fromRelFile path       (s', exts) = F.splitExtensions s    in exts `elem` [".hs", ".hsig"] && not ("-out" `isSuffixOf` s')++-- | Does the given path contain import export examples?+isIEInput :: Path Rel File -> Bool+isIEInput path =+  let isImportPath = "import/" `isSuffixOf` fromRelDir (parent path)+      isExportPath = "module-header/" `isSuffixOf` fromRelDir (parent path)+   in isInput path && (isImportPath || isExportPath)  -- | For given path of input file return expected name of output. deriveOutput :: String -> Path Rel File -> IO (Path Rel File)