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 +7/−0
- README.md +2/−0
- app/Main.hs +9/−0
- data/examples/import/comments-inside-imports-four-ie-out.hs +8/−0
- data/examples/import/comments-per-import-four-ie-out.hs +4/−0
- data/examples/import/deduplication-bug-four-ie-out.hs +6/−0
- data/examples/import/explicit-imports-four-ie-out.hs +12/−0
- data/examples/import/explicit-imports-with-comments-four-ie-out.hs +7/−0
- data/examples/import/explicit-prelude-four-ie-out.hs +3/−0
- data/examples/import/merging-0-four-ie-out.hs +3/−0
- data/examples/import/merging-1-four-ie-out.hs +2/−0
- data/examples/import/merging-2-four-ie-out.hs +2/−0
- data/examples/import/misc-four-ie-out.hs +7/−0
- data/examples/import/nested-explicit-imports-four-ie-out.hs +10/−0
- data/examples/import/qualified-post-four-ie-out.hs +5/−0
- data/examples/import/qualified-prelude-four-ie-out.hs +4/−0
- data/examples/import/simple-four-ie-out.hs +5/−0
- data/examples/import/sorted-export-list-four-ie-out.hs +1/−0
- data/examples/import/sorted-four-ie-out.hs +3/−0
- data/examples/module-header/double-dot-with-names-four-ie-out.hs +17/−0
- data/examples/module-header/double-shebangs-four-ie-out.hs +2/−0
- data/examples/module-header/empty-four-ie-out.hs +0/−0
- data/examples/module-header/empty-haddock-four-ie-out.hs +1/−0
- data/examples/module-header/leading-empty-line-four-ie-out.hs +12/−0
- data/examples/module-header/multiline-empty-four-ie-out.hs +4/−0
- data/examples/module-header/multiline-four-ie-out.hs +6/−0
- data/examples/module-header/multiline-with-comments-four-ie-out.hs +25/−0
- data/examples/module-header/multiline2-four-ie-out.hs +6/−0
- data/examples/module-header/named-section-four-ie-out.hs +14/−0
- data/examples/module-header/preceding-comment-with-haddock-four-ie-out.hs +8/−0
- data/examples/module-header/shebang-four-ie-out.hs +6/−0
- data/examples/module-header/shebang-with-pragmas-four-ie-out.hs +5/−0
- data/examples/module-header/simple-four-ie-out.hs +1/−0
- data/examples/module-header/simple-with-comments-four-ie-out.hs +4/−0
- data/examples/module-header/singleline-empty-four-ie-out.hs +2/−0
- data/examples/module-header/singleline-four-ie-out.hs +1/−0
- data/examples/module-header/stack-header-0-four-ie-out.hs +7/−0
- data/examples/module-header/stack-header-1-four-ie-out.hs +8/−0
- data/examples/module-header/stack-header-2-four-ie-out.hs +12/−0
- data/examples/module-header/warning-pragma-four-ie-out.hs +5/−0
- data/examples/module-header/warning-pragma-list-multiline-four-ie-out.hs +11/−0
- data/examples/module-header/warning-pragma-multiline-four-ie-out.hs +6/−0
- data/examples/module-header/warning-pragma-singleton-list-four-ie-out.hs +1/−0
- data/examples/other/empty-haddock-four-ie-out.hs +7/−0
- fourmolu.cabal +2/−2
- src/Ormolu/Config.hs +5/−1
- src/Ormolu/Printer/Combinators.hs +1/−0
- src/Ormolu/Printer/Meat/Declaration/Data.hs +1/−1
- src/Ormolu/Printer/Meat/Declaration/Value.hs +22/−11
- src/Ormolu/Printer/Meat/ImportExport.hs +83/−27
- src/Ormolu/Printer/Meat/Type.hs +2/−2
- src/Ormolu/Utils.hs +1/−0
- tests/Ormolu/PrinterSpec.hs +20/−0
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)