packages feed

ormolu 0.1.0.0 → 0.1.1.0

raw patch · 72 files changed

+760/−396 lines, 72 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Ormolu.Imports: sortImports :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]
+ Ormolu.Imports: instance GHC.Classes.Eq Ormolu.Imports.IEWrappedNameOrd
+ Ormolu.Imports: instance GHC.Classes.Eq Ormolu.Imports.ImportId
+ Ormolu.Imports: instance GHC.Classes.Ord Ormolu.Imports.IEWrappedNameOrd
+ Ormolu.Imports: instance GHC.Classes.Ord Ormolu.Imports.ImportId
+ Ormolu.Imports: normalizeImports :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]
+ Ormolu.Parser.Result: [prIndent] :: ParseResult -> Int
+ Ormolu.Printer.Combinators: commaDel :: R ()
+ Ormolu.Printer.Combinators: inciIf :: Bool -> R () -> R ()
+ Ormolu.Printer.Combinators: instance GHC.Classes.Eq Ormolu.Printer.Combinators.BracketStyle
+ Ormolu.Printer.Combinators: instance GHC.Show.Show Ormolu.Printer.Combinators.BracketStyle
+ Ormolu.Printer.Meat.Declaration.Value: instance GHC.Show.Show Ormolu.Printer.Meat.Declaration.Value.Placement
+ Ormolu.Utils: removeIndentation :: String -> (String, Int)
- Ormolu.Parser.Result: ParseResult :: HsModule GhcPs -> Anns -> Maybe (RealLocated Comment) -> [Shebang] -> [([RealLocated Comment], Pragma)] -> CommentStream -> Bool -> Bool -> Text -> Text -> ParseResult
+ Ormolu.Parser.Result: ParseResult :: HsModule GhcPs -> Anns -> Maybe (RealLocated Comment) -> [Shebang] -> [([RealLocated Comment], Pragma)] -> CommentStream -> Bool -> Bool -> Text -> Text -> Int -> ParseResult
- Ormolu.Printer.Meat.Common: p_infixDefHelper :: Bool -> (R () -> R ()) -> R () -> [R ()] -> R ()
+ Ormolu.Printer.Meat.Common: p_infixDefHelper :: Bool -> Bool -> R () -> [R ()] -> R ()
- Ormolu.Processing.Postprocess: postprocess :: Text -> Text
+ Ormolu.Processing.Postprocess: postprocess :: Int -> Text -> Text

Files

CHANGELOG.md view
@@ -1,3 +1,41 @@+## Ormolu 0.1.1.0++* Imports in a import lists are now normalized: duplicate imports are+  combined/eliminated intelligently.++* Import declarations that can be merged are now automatically merged.+  [Issue 414](https://github.com/tweag/ormolu/issues/414).++* The magic comments for disabling and enabling Ormolu now can encompass any+  fragment of code provided that the remaining code after exclusion of the+  disabled part is still syntactically correct. [Issue+  601](https://github.com/tweag/ormolu/issues/601).++* Improved sorting of operators in imports. [Issue+  602](https://github.com/tweag/ormolu/issues/602).++* Fixed a bug related to trailing space in multiline comments in certain+  cases. [Issue 603](https://github.com/tweag/ormolu/issues/602).++* Added support for formatting linked lists with `(:)` as line terminator.+  [Issue 478](https://github.com/tweag/ormolu/issues/478).++* Fixed rendering of function arguments in multiline layout. [Issue+  609](https://github.com/tweag/ormolu/issues/609).++* Blank lines between definitions in `let` and `while` bindings are now+  preserved. [Issue 554](https://github.com/tweag/ormolu/issues/554).++* Fixed the bug when type applications stuck to the `$` of TH splices that+  followed them. [Issue 613](https://github.com/tweag/ormolu/issues/613).++* Improved region formatting so that indented fragments—such as definitions+  inside of `where` clauses—can be formatted. [Issue+  572](https://github.com/tweag/ormolu/issues/572).++* Fixed the bug related to the de-association of pragma comments. [Issue+  619](https://github.com/tweag/ormolu/issues/619).+ ## Ormolu 0.1.0.0  * Fixed rendering of type signatures concerning several identifiers. [Issue@@ -6,7 +44,7 @@ * Fixed an idempotence issue with inline comments in tuples and parentheses.   [Issue 450](https://github.com/tweag/ormolu/issues/450). -* Fixed an idempotence issue when certain comments where picked up as+* Fixed an idempotence issue when certain comments were picked up as   “continuation” of a series of comments [Issue   449](https://github.com/tweag/ormolu/issues/449). @@ -25,7 +63,7 @@   multiple blank lines in a row. [Issue   518](https://github.com/tweag/ormolu/issues/518). -* Fixed rendering of comment around if expressions. [Issue+* Fixed rendering of comments around if expressions. [Issue   458](https://github.com/tweag/ormolu/issues/458).  * Unnamed fields of data constructors are now documented using the `-- ^`
README.md view
@@ -45,11 +45,12 @@  ```console $ cat stack.yaml-resolver: lts-14.3+resolver: lts-16.0 packages: - '.' -$ stack build+$ stack build -- to build+$ stack install -- to install ```  To use Ormolu directly from GitHub with Nix, this snippet may come in handy:
+ data/examples/declaration/value/function/arg-breakpoints-out.hs view
@@ -0,0 +1,3 @@+foo+  bar =+    body
+ data/examples/declaration/value/function/arg-breakpoints.hs view
@@ -0,0 +1,3 @@+foo+  bar =+    body
+ data/examples/declaration/value/function/blank-lines-let-out.hs view
@@ -0,0 +1,6 @@+foo =+  let x = 10++      y = 11+      z = 12+   in x + y + z
+ data/examples/declaration/value/function/blank-lines-let.hs view
@@ -0,0 +1,9 @@+foo =+  let++    x = 10++    y = 11+    z = 12++  in x + y + z
+ data/examples/declaration/value/function/blank-lines-where-out.hs view
@@ -0,0 +1,6 @@+foo = x + y + z+  where+    x = 10++    y = 11+    z = 12
+ data/examples/declaration/value/function/blank-lines-where.hs view
@@ -0,0 +1,7 @@+foo = x + y + z+  where++    x = 10++    y = 11+    z = 12
data/examples/declaration/value/function/infix/dollar-chains-out.hs view
@@ -13,9 +13,9 @@     throwIO (OrmoluCppEnabled path)  foo =-  bar-    $ baz-    $ quux+  bar $+    baz $+      quux  x =   case l of { A -> B } $
data/examples/declaration/value/function/infix/hanging-out.hs view
@@ -17,6 +17,7 @@     `catch` \case       a -> a -foo = bar-  ++ case foo of-    a -> a+foo =+  bar+    ++ case foo of+      a -> a
data/examples/declaration/value/function/infix/lenses-out.hs view
@@ -1,11 +1,12 @@ lenses =-  Just $ M.fromList $-    "type" .= ("user.connection" :: Text)-      # "connection" .= uc-      # "user" .= case name of-        Just n -> Just $ object ["name" .= n]-        Nothing -> Nothing-      # []+  Just $+    M.fromList $+      "type" .= ("user.connection" :: Text)+        # "connection" .= uc+        # "user" .= case name of+          Just n -> Just $ object ["name" .= n]+          Nothing -> Nothing+        # []  foo =   a
+ data/examples/declaration/value/function/list-notation-0-out.hs view
@@ -0,0 +1,5 @@+foo =+  testCase "Foo" testFoo :+  testCase "Bar" testBar :+  testCase "Baz" testBaz :+  []
+ data/examples/declaration/value/function/list-notation-0.hs view
@@ -0,0 +1,5 @@+foo =+  testCase "Foo" testFoo :+  testCase "Bar" testBar :+  testCase "Baz" testBaz :+  []
+ data/examples/declaration/value/function/list-notation-1-out.hs view
@@ -0,0 +1,8 @@+instance A.ToJSON UpdateTable where+  toJSON a =+    A.object $+      "TableName" .= updateTableName a :+      "ProvisionedThroughput" .= updateProvisionedThroughput a :+      case updateGlobalSecondaryIndexUpdates a of+        [] -> []+        l -> ["GlobalSecondaryIndexUpdates" .= l]
+ data/examples/declaration/value/function/list-notation-1.hs view
@@ -0,0 +1,7 @@+instance A.ToJSON UpdateTable where+    toJSON a = A.object+        $ "TableName" .= updateTableName a+        : "ProvisionedThroughput" .= updateProvisionedThroughput a+        : case updateGlobalSecondaryIndexUpdates a of+            [] -> []+            l -> [ "GlobalSecondaryIndexUpdates" .= l ]
+ data/examples/declaration/value/function/list-notation-2-out.hs view
@@ -0,0 +1,6 @@+-- A list of the element and all its parents up to the root node.+getPath tree t =+  t :+  case Map.lookup (getId t) tree of+    Nothing -> []+    Just parent -> getPath tree parent
+ data/examples/declaration/value/function/list-notation-2.hs view
@@ -0,0 +1,5 @@+-- A list of the element and all its parents up to the root node.+getPath tree t = t :+    case Map.lookup (getId t) tree of+        Nothing     -> []+        Just parent -> getPath tree parent
+ data/examples/declaration/value/function/list-notation-3-out.hs view
@@ -0,0 +1,12 @@+foo =+  reportSDoc "tc.cc" 30 $+    sep $ do+      (prettyTCM q <+> " before compilation") : do+        map (prettyTCM . map unArg . clPats) cls++foo =+  reportSDoc "tc.cc" 30 $+    sep $ do+      (prettyTCM q <+> " before compilation") :+        do+          map (prettyTCM . map unArg . clPats) cls
+ data/examples/declaration/value/function/list-notation-3.hs view
@@ -0,0 +1,10 @@+foo =+  reportSDoc "tc.cc" 30 $ sep $ do+    (prettyTCM q <+> " before compilation") : do+      map (prettyTCM . map unArg . clPats) cls++foo =+  reportSDoc "tc.cc" 30 $ sep $ do+    (prettyTCM q <+> " before compilation") :+      do+        map (prettyTCM . map unArg . clPats) cls
+ data/examples/declaration/value/function/type-applications-and-splice-out.hs view
@@ -0,0 +1,4 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}++staticKey name = [|sing @ $(symFQN name)|]
+ data/examples/declaration/value/function/type-applications-and-splice.hs view
@@ -0,0 +1,4 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeApplications #-}++staticKey name = [| sing @ $(symFQN name) |]
+ data/examples/import/deduplication-bug-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/deduplication-bug.hs view
@@ -0,0 +1,6 @@+import Foo1 (Bar1, Baz1, Bar1(..))+import Foo2 (Bar2(..), Baz2, Bar2)+import Foo3 (Bar3(x1,x3), Bar3(x1, x2))+import Foo4 (Bar4(x1), Bar4(x2))+import Foo5 (Bar5, Bar5(x1))+import Foo6 (Bar6(x1), Bar6(..))
data/examples/import/explicit-imports-out.hs view
@@ -1,12 +1,12 @@ import qualified MegaModule as M-  ( (<<<),-    (>>>),-    Either,+  ( Either,     Maybe (Just, Nothing),     MaybeT (..),-    Monad ((>>), (>>=), return),+    Monad (return, (>>), (>>=)),     MonadBaseControl,     join,     liftIO,     void,+    (<<<),+    (>>>),   )
data/examples/import/explicit-imports-with-comments-out.hs view
@@ -1,6 +1,7 @@ import qualified MegaModule as M   ( -- (1)-    (<<<), -- (2)-    (>>>),+    -- (2)     Either, -- (3)+    (<<<),+    (>>>),   )
+ data/examples/import/merging-0-out.hs view
@@ -0,0 +1,3 @@+import Foo+import Foo (bar, foo)+import Foo as F
+ data/examples/import/merging-0.hs view
@@ -0,0 +1,4 @@+import Foo+import Foo (foo)+import Foo (bar)+import Foo as F
+ data/examples/import/merging-1-out.hs view
@@ -0,0 +1,2 @@+import "bar" Foo (bar)+import "foo" Foo (baz, foo)
+ data/examples/import/merging-1.hs view
@@ -0,0 +1,3 @@+import "foo" Foo (foo)+import "bar" Foo (bar)+import "foo" Foo (baz)
+ data/examples/import/merging-2-out.hs view
@@ -0,0 +1,2 @@+import Foo hiding (bar4, foo2)+import qualified Foo (bar3, foo1)
+ data/examples/import/merging-2.hs view
@@ -0,0 +1,4 @@+import qualified Foo (foo1)+import Foo hiding (foo2)+import qualified Foo (bar3)+import Foo hiding (bar4)
data/examples/import/misc-out.hs view
@@ -1,11 +1,5 @@ import A hiding   ( foobarbazqux,-    foobarbazqux,-    foobarbazqux,-    foobarbazqux,-    foobarbazqux,-    foobarbazqux,-    foobarbazqux,   ) import {-# SOURCE #-} safe qualified Module as M hiding (a, b, c, d, e, f) import Name hiding ()
data/examples/import/nested-explicit-imports-out.hs view
@@ -1,10 +1,10 @@ import qualified MegaModule as M-  ( (<<<),-    (>>>),-    Either,+  ( Either,     Monad-      ( (>>),-        (>>=),-        return+      ( return,+        (>>),+        (>>=)       ),+    (<<<),+    (>>>),   )
data/examples/import/qualified-post-out.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE ImportQualifiedPost #-} -import Data.Text qualified as T 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-out.hs view
@@ -1,4 +1,4 @@ module P where +import Prelude hiding (id, (.)) import qualified Prelude-import Prelude hiding ((.), id)
data/examples/import/simple-out.hs view
@@ -1,6 +1,5 @@ import Data.Text-import Data.Text-import qualified Data.Text as T-import qualified Data.Text (a, b, c) 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/simple.hs view
@@ -4,3 +4,5 @@ import qualified Data.Text (a, c, b) import Data.Text (a, b, c) import Data.Text hiding (c, b, a)+import Data.Text (a, b, c, b, a)+import Data.Text hiding (c, b, a, b, c)
+ data/examples/import/sorted-export-list-out.hs view
@@ -0,0 +1,1 @@+import Linear.Vector (Additive (..), (*^), (^*))
+ data/examples/import/sorted-export-list.hs view
@@ -0,0 +1,1 @@+import Linear.Vector (Additive (..), (*^), (^*))
+ data/examples/other/comment-trailing-space-out.hs view
@@ -0,0 +1,9 @@+data T+  = {-++      some multi-line comment++      with empty lines++    -}+    A
+ data/examples/other/comment-trailing-space.hs view
@@ -0,0 +1,9 @@+data T+  = {-++      some multi-line comment++      with empty lines++    -}+    A
+ data/examples/other/pragma-comments-after-out.hs view
@@ -0,0 +1,4 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ConstraintKinds #-}+-- TODO: Fix and delete this pragma+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
+ data/examples/other/pragma-comments-after.hs view
@@ -0,0 +1,3 @@+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} -- TODO: Fix and delete this pragma+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ConstraintKinds #-}
ormolu.cabal view
@@ -1,6 +1,6 @@ cabal-version:   1.18 name:            ormolu-version:         0.1.0.0+version:         0.1.1.0 license:         BSD3 license-file:    LICENSE.md maintainer:      Mark Karpov <mark.karpov@tweag.io>@@ -152,6 +152,7 @@         ghc-options:             -Wall -Werror -Wcompat -Wincomplete-record-updates             -Wincomplete-uni-patterns -Wnoncanonical-monad-instances+            -optP-Wno-nonportable-include-path      else         ghc-options: -O2 -Wall -rtsopts
src/Ormolu/Diff.hs view
@@ -14,7 +14,7 @@ import qualified Data.Text as T import qualified FastString as GHC import GHC-import Ormolu.Imports (sortImports)+import Ormolu.Imports (normalizeImports) import Ormolu.Parser.CommentStream import Ormolu.Parser.Result import Ormolu.Utils@@ -47,8 +47,8 @@     } =     matchIgnoringSrcSpans cstream0 cstream1       <> matchIgnoringSrcSpans-        hs0 {hsmodImports = sortImports (hsmodImports hs0)}-        hs1 {hsmodImports = sortImports (hsmodImports hs1)}+        hs0 {hsmodImports = normalizeImports (hsmodImports hs0)}+        hs1 {hsmodImports = normalizeImports (hsmodImports hs1)}  -- | Compare two values for equality disregarding differences in 'SrcSpan's -- and the ordering of import lists.
src/Ormolu/Imports.hs view
@@ -4,82 +4,199 @@  -- | Manipulations on import lists. module Ormolu.Imports-  ( sortImports,+  ( normalizeImports,   ) where  import Data.Bifunctor+import Data.Char (isAlphaNum) import Data.Function (on)-import Data.Generics (gcompare)-import Data.List (sortBy)+import Data.List (foldl', nubBy, sortBy, sortOn)+import Data.Map.Strict (Map)+import qualified Data.Map.Strict as M+import FastString (FastString) import GHC hiding (GhcPs, IE) import GHC.Hs.Extension import GHC.Hs.ImpExp (IE (..))-import Ormolu.Utils (notImplemented)+import Ormolu.Utils (notImplemented, showOutputable) --- | Sort imports by module name. This also sorts explicit import lists for--- each declaration.-sortImports :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]-sortImports = sortBy compareIdecl . fmap (fmap sortImportLists)+-- | Sort and normalize imports.+normalizeImports :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]+normalizeImports =+  fmap snd+    . M.toAscList+    . M.fromListWith combineImports+    . fmap (\x -> (importId x, g x))   where-    sortImportLists :: ImportDecl GhcPs -> ImportDecl GhcPs-    sortImportLists = \case-      ImportDecl {..} ->+    g (L l ImportDecl {..}) =+      L+        l         ImportDecl-          { ideclHiding = second (fmap sortLies) <$> ideclHiding,+          { ideclHiding = second (fmap normalizeLies) <$> ideclHiding,             ..           }-      XImportDecl x -> noExtCon x+    g _ = notImplemented "XImportDecl" --- | Compare two @'LImportDecl' 'GhcPs'@ things.-compareIdecl :: LImportDecl GhcPs -> LImportDecl GhcPs -> Ordering-compareIdecl (L _ m0) (L _ m1) =-  case (isPrelude n0, isPrelude n1) of-    (False, False) -> n0 `compare` n1-    (True, False) -> GT-    (False, True) -> LT-    (True, True) -> m0 `gcompare` m1+-- | Combine two import declarations. It should be assumed that 'ImportId's+-- are equal.+combineImports ::+  LImportDecl GhcPs ->+  LImportDecl GhcPs ->+  LImportDecl GhcPs+combineImports (L lx ImportDecl {..}) (L _ y) =+  L+    lx+    ImportDecl+      { ideclHiding = case (ideclHiding, GHC.ideclHiding y) of+          (Just (hiding, L l' xs), Just (_, L _ ys)) ->+            Just (hiding, (L l' (normalizeLies (xs ++ ys))))+          _ -> Nothing,+        ..+      }+combineImports _ _ = notImplemented "XImportDecl"++-- | Import id, a collection of all things that justify having a separate+-- import entry. This is used for merging of imports. If two imports have+-- the same 'ImportId' they can be merged.+data ImportId = ImportId+  { importIsPrelude :: Bool,+    importIdName :: ModuleName,+    importPkgQual :: Maybe FastString,+    importSource :: Bool,+    importSafe :: Bool,+    importQualified :: Bool,+    importImplicit :: Bool,+    importAs :: Maybe ModuleName,+    importHiding :: Maybe Bool+  }+  deriving (Eq, Ord)++-- | Obtain an 'ImportId' for a given import.+importId :: LImportDecl GhcPs -> ImportId+importId (L _ ImportDecl {..}) =+  ImportId+    { importIsPrelude = isPrelude,+      importIdName = moduleName,+      importPkgQual = sl_fs <$> ideclPkgQual,+      importSource = ideclSource,+      importSafe = ideclSafe,+      importQualified = case ideclQualified of+        QualifiedPre -> True+        QualifiedPost -> True+        NotQualified -> False,+      importImplicit = ideclImplicit,+      importAs = unLoc <$> ideclAs,+      importHiding = fst <$> ideclHiding+    }   where-    n0 = unLoc (ideclName m0)-    n1 = unLoc (ideclName m1)-    isPrelude = (== "Prelude") . moduleNameString+    isPrelude = moduleNameString moduleName == "Prelude"+    moduleName = unLoc ideclName+importId _ = notImplemented "XImportDecl" --- | Sort located import or export.-sortLies :: [LIE GhcPs] -> [LIE GhcPs]-sortLies = sortBy (compareIE `on` unLoc) . fmap (fmap sortThings)+-- | Normalize a collection of import\/export items.+normalizeLies :: [LIE GhcPs] -> [LIE GhcPs]+normalizeLies = sortOn (getIewn . unLoc) . M.elems . foldl' combine M.empty+  where+    combine ::+      Map IEWrappedNameOrd (LIE GhcPs) ->+      LIE GhcPs ->+      Map IEWrappedNameOrd (LIE GhcPs)+    combine m (L new_l new) =+      let wname = getIewn new+          normalizeWNames =+            nubBy (\x y -> compareLIewn x y == EQ) . sortBy compareLIewn+          alter = \case+            Nothing -> Just . L new_l $+              case new of+                IEThingWith NoExtField n wildcard g flbl ->+                  IEThingWith NoExtField n wildcard (normalizeWNames g) flbl+                other -> other+            Just old ->+              let f = \case+                    IEVar NoExtField n -> IEVar NoExtField n+                    IEThingAbs NoExtField _ -> new+                    IEThingAll NoExtField n -> IEThingAll NoExtField n+                    IEThingWith NoExtField n wildcard g flbl ->+                      case new of+                        IEVar NoExtField _ ->+                          error "Ormolu.Imports broken presupposition"+                        IEThingAbs NoExtField _ ->+                          IEThingWith NoExtField n wildcard g flbl+                        IEThingAll NoExtField n' ->+                          IEThingAll NoExtField n'+                        IEThingWith NoExtField n' wildcard' g' flbl' ->+                          let combinedWildcard =+                                case (wildcard, wildcard') of+                                  (IEWildcard _, _) -> IEWildcard 0+                                  (_, IEWildcard _) -> IEWildcard 0+                                  _ -> NoIEWildcard+                           in IEThingWith+                                NoExtField+                                n'+                                combinedWildcard+                                (normalizeWNames (g <> g'))+                                flbl'+                        IEModuleContents NoExtField _ -> notImplemented "IEModuleContents"+                        IEGroup NoExtField _ _ -> notImplemented "IEGroup"+                        IEDoc NoExtField _ -> notImplemented "IEDoc"+                        IEDocNamed NoExtField _ -> notImplemented "IEDocNamed"+                        XIE x -> noExtCon x+                    IEModuleContents NoExtField _ -> notImplemented "IEModuleContents"+                    IEGroup NoExtField _ _ -> notImplemented "IEGroup"+                    IEDoc NoExtField _ -> notImplemented "IEDoc"+                    IEDocNamed NoExtField _ -> notImplemented "IEDocNamed"+                    XIE x -> noExtCon x+               in Just (f <$> old)+       in M.alter alter wname m --- | Sort imports\/exports inside of 'IEThingWith'.-sortThings :: IE GhcPs -> IE GhcPs-sortThings = \case-  IEThingWith NoExtField x w xs fl ->-    IEThingWith NoExtField x w (sortBy (compareIewn `on` unLoc) xs) fl-  other -> other+-- | A wrapper for @'IEWrappedName' 'RdrName'@ that allows us to define an+-- 'Ord' instance for it.+newtype IEWrappedNameOrd = IEWrappedNameOrd (IEWrappedName RdrName)+  deriving (Eq) --- | Compare two located imports or exports.-compareIE :: IE GhcPs -> IE GhcPs -> Ordering-compareIE = compareIewn `on` getIewn+instance Ord IEWrappedNameOrd where+  compare (IEWrappedNameOrd x) (IEWrappedNameOrd y) = compareIewn x y  -- | Project @'IEWrappedName' 'RdrName'@ from @'IE' 'GhcPs'@.-getIewn :: IE GhcPs -> IEWrappedName RdrName+getIewn :: IE GhcPs -> IEWrappedNameOrd getIewn = \case-  IEVar NoExtField x -> unLoc x-  IEThingAbs NoExtField x -> unLoc x-  IEThingAll NoExtField x -> unLoc x-  IEThingWith NoExtField x _ _ _ -> unLoc x+  IEVar NoExtField x -> IEWrappedNameOrd (unLoc x)+  IEThingAbs NoExtField x -> IEWrappedNameOrd (unLoc x)+  IEThingAll NoExtField x -> IEWrappedNameOrd (unLoc x)+  IEThingWith NoExtField x _ _ _ -> IEWrappedNameOrd (unLoc x)   IEModuleContents NoExtField _ -> notImplemented "IEModuleContents"   IEGroup NoExtField _ _ -> notImplemented "IEGroup"   IEDoc NoExtField _ -> notImplemented "IEDoc"   IEDocNamed NoExtField _ -> notImplemented "IEDocNamed"   XIE x -> noExtCon x +-- | Like 'compareIewn' for located wrapped names.+compareLIewn :: LIEWrappedName RdrName -> LIEWrappedName RdrName -> Ordering+compareLIewn = compareIewn `on` unLoc+ -- | Compare two @'IEWrapppedName' 'RdrName'@ things. compareIewn :: IEWrappedName RdrName -> IEWrappedName RdrName -> Ordering-compareIewn (IEName x) (IEName y) = unLoc x `compare` unLoc y+compareIewn (IEName x) (IEName y) = unLoc x `compareRdrName` unLoc y compareIewn (IEName _) (IEPattern _) = LT compareIewn (IEName _) (IEType _) = LT compareIewn (IEPattern _) (IEName _) = GT-compareIewn (IEPattern x) (IEPattern y) = unLoc x `compare` unLoc y+compareIewn (IEPattern x) (IEPattern y) = unLoc x `compareRdrName` unLoc y compareIewn (IEPattern _) (IEType _) = LT compareIewn (IEType _) (IEName _) = GT compareIewn (IEType _) (IEPattern _) = GT-compareIewn (IEType x) (IEType y) = unLoc x `compare` unLoc y+compareIewn (IEType x) (IEType y) = unLoc x `compareRdrName` unLoc y++compareRdrName :: RdrName -> RdrName -> Ordering+compareRdrName x y =+  case (getNameStr x, getNameStr y) of+    ([], []) -> EQ+    ((_ : _), []) -> GT+    ([], (_ : _)) -> LT+    ((x' : _), (y' : _)) ->+      case (isAlphaNum x', isAlphaNum y') of+        (False, False) -> x `compare` y+        (True, False) -> LT+        (False, True) -> GT+        (True, True) -> x `compare` y+  where+    getNameStr = showOutputable . rdrNameOcc
src/Ormolu/Parser.hs view
@@ -32,7 +32,7 @@ import Ormolu.Parser.CommentStream import Ormolu.Parser.Result import Ormolu.Processing.Preprocess (preprocess)-import Ormolu.Utils (incSpanLine)+import Ormolu.Utils (incSpanLine, removeIndentation) import qualified Panic as GHC import qualified Parser as GHC import qualified StringBuffer as GHC@@ -51,8 +51,9 @@       Either (SrcSpan, String) ParseResult     ) parseModule Config {..} path rawInput = liftIO $ do-  let (literalPrefix, input, literalSuffix, extraComments) =+  let (literalPrefix, indentedInput, literalSuffix, extraComments) =         preprocess path rawInput cfgRegion+      (input, indent) = removeIndentation indentedInput   -- It's important that 'setDefaultExts' is done before   -- 'parsePragmasIntoDynFlags', because otherwise we might enable an   -- extension that was explicitly disabled in the file.@@ -110,7 +111,8 @@                         prImportQualifiedPost =                           GHC.xopt ImportQualifiedPost dynFlags,                         prLiteralPrefix = T.pack literalPrefix,-                        prLiteralSuffix = T.pack literalSuffix+                        prLiteralSuffix = T.pack literalSuffix,+                        prIndent = indent                       }   return (warnings, r) 
src/Ormolu/Parser/CommentStream.hs view
@@ -27,7 +27,8 @@ import qualified Lexer as GHC import Ormolu.Parser.Pragma import Ormolu.Parser.Shebang-import Ormolu.Utils (showOutputable)+import Ormolu.Processing.Common+import Ormolu.Utils (onTheSameLine, showOutputable) import SrcLoc  ----------------------------------------------------------------------------@@ -109,11 +110,15 @@             Nothing -> s :| []             Just (x :| xs) ->               let getIndent y =-                    if all isSpace y+                    if all isSpace y || y == endDisabling                       then startIndent                       else length (takeWhile isSpace y)                   n = minimum (startIndent : fmap getIndent xs)-               in x :| (drop n <$> xs)+                  removeIndent y =+                    if y == endDisabling+                      then y+                      else drop n y+               in x :| (removeIndent <$> xs)           else s :| []     (atomsBefore, ls') =       case dropWhile ((< commentLine) . fst) ls of@@ -145,6 +150,7 @@  -- | Detect and extract stack header if it is present. extractStackHeader ::+  -- | Comment stream to analyze   [RealLocated String] ->   ([RealLocated String], Maybe (RealLocated Comment)) extractStackHeader = \case@@ -160,7 +166,9 @@  -- | Extract pragmas and their associated comments. extractPragmas ::+  -- | Input   String ->+  -- | Comment stream to analyze   [RealLocated String] ->   ([RealLocated Comment], [([RealLocated Comment], Pragma)]) extractPragmas input = go initialLs id id@@ -174,8 +182,17 @@             let (ls', x') = mkComment ls x              in go ls' (csSoFar . (x' :)) pragmasSoFar xs           Just pragma ->-            let combined = (csSoFar [], pragma)-             in go ls id (pragmasSoFar . (combined :)) xs+            let combined ys = (csSoFar ys, pragma)+                go' ls' ys rest = go ls' id (pragmasSoFar . (combined ys :)) rest+             in case xs of+                  [] -> go' ls [] xs+                  (y : ys) ->+                    let (ls', y') = mkComment ls y+                     in if onTheSameLine+                          (RealSrcSpan (getRealSrcSpan x))+                          (RealSrcSpan (getRealSrcSpan y))+                          then go' ls' [y'] ys+                          else go' ls [] xs  -- | Get a 'String' from 'GHC.AnnotationComment'. unAnnotationComment :: GHC.AnnotationComment -> Maybe String
src/Ormolu/Parser/Result.hs view
@@ -35,7 +35,9 @@     -- | Literal prefix     prLiteralPrefix :: Text,     -- | Literal suffix-    prLiteralSuffix :: Text+    prLiteralSuffix :: Text,+    -- | Indentation level, can be non-zero in case of region formatting+    prIndent :: Int   }  -- | Pretty-print a 'ParseResult'.
src/Ormolu/Printer.hs view
@@ -23,7 +23,7 @@   prLiteralPrefix <> region <> prLiteralSuffix   where     region =-      postprocess $+      postprocess prIndent $         runR           ( p_hsModule               prStackHeader
src/Ormolu/Printer/Combinators.hs view
@@ -21,6 +21,7 @@     space,     newline,     inci,+    inciIf,     located,     located',     switchLayout,@@ -51,6 +52,7 @@      -- ** Literals     comma,+    commaDel,     equals,      -- ** Stateful markers@@ -72,6 +74,15 @@ ---------------------------------------------------------------------------- -- Basic +-- | Indent the inner expression if the first argument is 'True'.+inciIf ::+  -- | Whether to indent+  Bool ->+  -- | The expression to indent+  R () ->+  R ()+inciIf b m = if b then inci m else m+ -- | Enter a 'Located' entity. This combinator handles outputting comments -- and sets layout (single-line vs multi-line) for the inner computation. -- Roughly, the rule for using 'located' is that every time there is a@@ -174,10 +185,12 @@         xs' ->           if ub             then do-              txt "{ "-              sep (txt "; ") (dontUseBraces . f) xs'-              txt " }"-            else sep (txt "; ") f xs'+              txt "{"+              space+              sep (txt ";" >> space) (dontUseBraces . f) xs'+              space+              txt "}"+            else sep (txt ";" >> space) f xs'     multiLine =       sep newline (dontUseBraces . f) xs @@ -190,6 +203,7 @@     N   | -- | Shifted one level     S+  deriving (Eq, Show)  -- | Surround given entity by backticks. backticks :: R () -> R ()@@ -266,9 +280,7 @@         then newline >> inci m         else space >> sitcc m       newline-      case style of-        N -> txt close-        S -> inci (txt close)+      inciIf (style == S) (txt close)  ---------------------------------------------------------------------------- -- Literals@@ -276,6 +288,10 @@ -- | Print @,@. comma :: R () comma = txt ","++-- | Delimiting combination with 'comma'. To be used with 'sep'.+commaDel :: R ()+commaDel = comma >> breakpoint  -- | Print @=@. Do not use @'txt' "="@. equals :: R ()
src/Ormolu/Printer/Internal.hs view
@@ -220,7 +220,8 @@   R () txt = spit SimpleText --- |+-- | Similar to 'txt' but the text inserted this way is assumed to break the+-- “link” between the preceding atom and its pending comments. interferingTxt ::   -- | 'Text' to output   Text ->@@ -243,6 +244,7 @@   -- | 'Text' to output   Text ->   R ()+spit _ "" = return () spit stype text = do   requestedDel <- R (gets scRequestedDelimiter)   pendingComments <- R (gets scPendingComments)
src/Ormolu/Printer/Meat/Common.hs view
@@ -114,14 +114,14 @@ p_infixDefHelper ::   -- | Whether to format in infix style   Bool ->-  -- | Indentation-bumping wrapper-  (R () -> R ()) ->+  -- | Whether to bump indentation for arguments+  Bool ->   -- | How to print the operator\/name   R () ->   -- | How to print the arguments   [R ()] ->   R ()-p_infixDefHelper isInfix inci' name args =+p_infixDefHelper isInfix indentArgs name args =   case (isInfix, args) of     (True, p0 : p1 : ps) -> do       let parens' =@@ -131,18 +131,18 @@       parens' $ do         p0         breakpoint-        inci $ sitcc $ do+        inci . sitcc $ do           name           space           p1-      unless (null ps) . inci' $ do+      unless (null ps) . inciIf indentArgs $ do         breakpoint         sitcc (sep breakpoint sitcc ps)     (_, ps) -> do       name       unless (null ps) $ do         breakpoint-        inci' $ sitcc (sep breakpoint sitcc args)+        inciIf indentArgs $ sitcc (sep breakpoint sitcc args)  -- | Print a Haddock. p_hsDocString ::
src/Ormolu/Printer/Meat/Declaration.hs view
@@ -12,7 +12,7 @@ where  import Data.List (sort)-import Data.List.NonEmpty ((<|), NonEmpty (..))+import Data.List.NonEmpty (NonEmpty (..), (<|)) import qualified Data.List.NonEmpty as NE import GHC hiding (InlinePragma) import OccName (occNameFS)@@ -54,12 +54,13 @@ p_hsDeclsRespectGrouping = p_hsDecls' Respect  p_hsDecls' :: UserGrouping -> FamilyStyle -> [LHsDecl GhcPs] -> R ()-p_hsDecls' grouping style decls = sepSemi id $-  -- Return a list of rendered declarations, adding a newline to separate-  -- groups.-  case groupDecls decls of-    [] -> []-    (x : xs) -> renderGroup x ++ concat (zipWith renderGroupWithPrev (x : xs) xs)+p_hsDecls' grouping style decls =+  sepSemi id $+    -- Return a list of rendered declarations, adding a newline to separate+    -- groups.+    case groupDecls decls of+      [] -> []+      (x : xs) -> renderGroup x ++ concat (zipWith renderGroupWithPrev (x : xs) xs)   where     renderGroup = NE.toList . fmap (located' $ dontUseBraces . p_hsDecl style)     renderGroupWithPrev prev curr =@@ -288,9 +289,10 @@ patSigRdrNames _ = Nothing  warnSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]-warnSigRdrNames (WarningD NoExtField (Warnings NoExtField _ ws)) = Just $ flip concatMap ws $ \case-  L _ (Warning NoExtField ns _) -> map unLoc ns-  L _ (XWarnDecl x) -> noExtCon x+warnSigRdrNames (WarningD NoExtField (Warnings NoExtField _ ws)) = Just $+  flip concatMap ws $ \case+    L _ (Warning NoExtField ns _) -> map unLoc ns+    L _ (XWarnDecl x) -> noExtCon x warnSigRdrNames _ = Nothing  patBindNames :: Pat GhcPs -> [RdrName]
src/Ormolu/Printer/Meat/Declaration/Class.hs view
@@ -58,7 +58,7 @@       switchLayout signatureSpans $         p_infixDefHelper           (isInfix fixity)-          inci+          True           (p_rdrName name)           (located' p_hsTyVarBndr <$> hsq_explicit)       inci (p_classFundeps fdeps)@@ -82,7 +82,7 @@   breakpoint   txt "|"   space-  sitcc $ sep (comma >> breakpoint) (sitcc . located' p_funDep) fdeps+  inci $ sep commaDel (sitcc . located' p_funDep) fdeps  p_funDep :: FunDep (Located RdrName) -> R () p_funDep (before, after) = do
src/Ormolu/Printer/Meat/Declaration/Data.hs view
@@ -41,7 +41,7 @@     inci $       p_infixDefHelper         (isInfix fixity)-        inci+        True         (p_rdrName name)         (located' p_hsType <$> tpats)   case dd_kindSig of@@ -60,28 +60,26 @@           txt "where"         breakpoint         sepSemi (located' (p_conDecl False)) dd_cons-      else switchLayout (getLoc name : (getLoc <$> dd_cons))-        $ inci-        $ do-          let singleConstRec = isSingleConstRec dd_cons-          if singleConstRec-            then space-            else-              if hasHaddocks dd_cons-                then newline-                else breakpoint-          equals-          space-          layout <- getLayout-          let s =-                if layout == MultiLine || hasHaddocks dd_cons-                  then newline >> txt "|" >> space-                  else space >> txt "|" >> space-              sitcc' =-                if singleConstRec-                  then id-                  else sitcc-          sep s (sitcc' . located' (p_conDecl singleConstRec)) dd_cons+      else switchLayout (getLoc name : (getLoc <$> dd_cons)) . inci $ do+        let singleConstRec = isSingleConstRec dd_cons+        if singleConstRec+          then space+          else+            if hasHaddocks dd_cons+              then newline+              else breakpoint+        equals+        space+        layout <- getLayout+        let s =+              if layout == MultiLine || hasHaddocks dd_cons+                then newline >> txt "|" >> space+                else space >> txt "|" >> space+            sitcc' =+              if singleConstRec+                then id+                else sitcc+        sep s (sitcc' . located' (p_conDecl singleConstRec)) dd_cons   unless (null $ unLoc dd_derivs) breakpoint   inci . located dd_derivs $ \xs ->     sep newline (located' p_hsDerivingClause) xs@@ -106,11 +104,10 @@         (c : cs) -> do           p_rdrName c           unless (null cs) . inci $ do-            comma-            breakpoint-            sitcc $ sep (comma >> breakpoint) p_rdrName cs-      space+            commaDel+            sep commaDel p_rdrName cs       inci $ do+        space         txt "::"         let interArgBreak =               if hasDocStrings (unLoc con_res_ty)@@ -158,11 +155,7 @@         RecCon l -> do           p_rdrName con_name           breakpoint-          let inci' =-                if singleConstRec-                  then id-                  else inci-          inci' (located l p_conDeclFields)+          inciIf (not singleConstRec) (located l p_conDeclFields)         InfixCon x y -> do           located x p_hsType           breakpoint@@ -211,9 +204,9 @@   let derivingWhat = located deriv_clause_tys $ \case         [] -> txt "()"         xs ->-          parens N . sitcc $+          parens N $             sep-              (comma >> breakpoint)+              commaDel               (sitcc . located' p_hsType . hsib_body)               xs   space
src/Ormolu/Printer/Meat/Declaration/Default.hs view
@@ -15,6 +15,6 @@   DefaultDecl NoExtField ts -> do     txt "default"     breakpoint-    inci . parens N . sitcc $-      sep (comma >> breakpoint) (sitcc . located' p_hsType) ts+    inci . parens N $+      sep commaDel (sitcc . located' p_hsType) ts   XDefaultDecl x -> noExtCon x
src/Ormolu/Printer/Meat/Declaration/Instance.hs view
@@ -32,9 +32,7 @@         txt "instance"         breakpoint         match_overlap_mode deriv_overlap_mode breakpoint-        if toIndent-          then inci typesAfterInstance-          else typesAfterInstance+        inciIf toIndent typesAfterInstance   txt "deriving"   space   case deriv_strategy of@@ -90,12 +88,10 @@             unless (null allDecls) $ do               breakpoint               txt "where"-        unless (null allDecls)-          $ inci-          $ do-            -- Ensure whitespace is added after where clause.-            breakpoint-            dontUseBraces $ p_hsDeclsRespectGrouping Associated allDecls+        unless (null allDecls) . inci $ do+          -- Ensure whitespace is added after where clause.+          breakpoint+          dontUseBraces $ p_hsDeclsRespectGrouping Associated allDecls       XHsImplicitBndrs x -> noExtCon x   XClsInstDecl x -> noExtCon x 
src/Ormolu/Printer/Meat/Declaration/Rule.hs view
@@ -18,7 +18,7 @@ p_ruleDecls :: RuleDecls GhcPs -> R () p_ruleDecls = \case   HsRules NoExtField _ xs ->-    pragma "RULES" . sitcc $+    pragma "RULES" $       sep breakpoint (sitcc . located' p_ruleDecl) xs   XRuleDecls x -> noExtCon x 
src/Ormolu/Printer/Meat/Declaration/Signature.hs view
@@ -14,7 +14,6 @@ import BasicTypes import BooleanFormula import Control.Monad-import Data.Bool (bool) import GHC import Ormolu.Printer.Combinators import Ormolu.Printer.Meat.Common@@ -48,25 +47,22 @@   p_rdrName n   if null ns     then p_typeAscription hswc-    else do-      comma-      breakpoint-      bool id inci indentTail $ do-        sep (comma >> breakpoint) p_rdrName ns-        p_typeAscription hswc+    else inciIf indentTail $ do+      commaDel+      sep commaDel p_rdrName ns+      p_typeAscription hswc  p_typeAscription ::   LHsSigWcType GhcPs ->   R ()-p_typeAscription HsWC {..} = do+p_typeAscription HsWC {..} = inci $ do   space-  inci $ do-    txt "::"-    let t = hsib_body hswc_body-    if hasDocStrings (unLoc t)-      then newline-      else breakpoint-    located t p_hsType+  txt "::"+  let t = hsib_body hswc_body+  if hasDocStrings (unLoc t)+    then newline+    else breakpoint+  located t p_hsType p_typeAscription (XHsWildCardBndrs x) = noExtCon x  p_patSynSig ::@@ -108,7 +104,7 @@     space     atom n     space-    sitcc $ sep (comma >> breakpoint) p_rdrName names+    sitcc $ sep commaDel p_rdrName names   XFixitySig x -> noExtCon x  p_inlineSig ::@@ -147,7 +143,7 @@   space   txt "::"   breakpoint-  inci $ sep (comma >> breakpoint) (located' p_hsType . hsib_body) ts+  inci $ sep commaDel (located' p_hsType . hsib_body) ts  p_inlineSpec :: InlineSpec -> R () p_inlineSpec = \case@@ -191,13 +187,13 @@   And xs ->     sitcc $       sep-        (comma >> breakpoint)+        commaDel         (located' p_booleanFormula)         xs   Or xs ->     sitcc $       sep-        (breakpoint >> txt "| ")+        (breakpoint >> txt "|" >> space)         (located' p_booleanFormula)         xs   Parens l -> located l (parens N . p_booleanFormula)@@ -211,7 +207,7 @@ p_completeSig cs' mty =   located cs' $ \cs ->     pragma "COMPLETE" . inci $ do-      sitcc $ sep (comma >> breakpoint) p_rdrName cs+      sep commaDel p_rdrName cs       forM_ mty $ \ty -> do         space         txt "::"@@ -228,12 +224,13 @@ p_standaloneKindSig :: StandaloneKindSig GhcPs -> R () p_standaloneKindSig (StandaloneKindSig NoExtField name bndrs) = do   txt "type"-  space-  p_rdrName name-  space-  txt "::"-  breakpoint-  inci $ case bndrs of-    HsIB NoExtField sig -> located sig p_hsType-    XHsImplicitBndrs x -> noExtCon x+  inci $ do+    space+    p_rdrName name+    space+    txt "::"+    breakpoint+    case bndrs of+      HsIB NoExtField sig -> located sig p_hsType+      XHsImplicitBndrs x -> noExtCon x p_standaloneKindSig (XStandaloneKindSig c) = noExtCon c
src/Ormolu/Printer/Meat/Declaration/Type.hs view
@@ -28,7 +28,7 @@   switchLayout (getLoc name : map getLoc hsq_explicit) $     p_infixDefHelper       (case fixity of Infix -> True; _ -> False)-      inci+      True       (p_rdrName name)       (map (located' p_hsTyVarBndr) hsq_explicit)   space
src/Ormolu/Printer/Meat/Declaration/TypeFamily.hs view
@@ -31,7 +31,7 @@     switchLayout (getLoc fdLName : (getLoc <$> hsq_explicit)) $       p_infixDefHelper         (isInfix fdFixity)-        inci+        True         (p_rdrName fdLName)         (located' p_hsTyVarBndr <$> hsq_explicit)     let resultSig = p_familyResultSigL fdResultSig@@ -92,12 +92,12 @@     Just bndrs -> do       p_forallBndrs ForallInvis p_hsTyVarBndr bndrs       breakpoint-  (if null feqn_bndrs then id else inci) $ do+  inciIf (not $ null feqn_bndrs) $ do     let famLhsSpn = getLoc feqn_tycon : fmap (getLoc . typeArgToType) feqn_pats     switchLayout famLhsSpn $       p_infixDefHelper         (isInfix feqn_fixity)-        inci+        True         (p_rdrName feqn_tycon)         (located' p_hsType . typeArgToType <$> feqn_pats)     space
src/Ormolu/Printer/Meat/Declaration/Value.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TypeApplications #-}@@ -21,12 +22,12 @@ import Data.Data hiding (Infix, Prefix) import Data.Functor ((<&>)) import Data.List (intersperse, sortOn)-import Data.List.NonEmpty ((<|), NonEmpty (..))+import Data.List.NonEmpty (NonEmpty (..), (<|)) import qualified Data.List.NonEmpty as NE import Data.Text (Text) import qualified Data.Text as Text import GHC-import OccName (mkVarOcc)+import OccName (occNameString) import Ormolu.Printer.Combinators import Ormolu.Printer.Internal import Ormolu.Printer.Meat.Common@@ -60,7 +61,7 @@     -- should use it and avoid bumping one level     -- of indentation     Hanging-  deriving (Eq)+  deriving (Eq, Show)  p_valDecl :: HsBindLR GhcPs GhcPs -> R () p_valDecl = \case@@ -179,25 +180,24 @@     NoSrcStrict -> return ()     SrcStrict -> txt "!"     SrcLazy -> txt "~"-  inci' <- case NE.nonEmpty m_pats of-    Nothing -> id <$ case style of-      Function name -> p_rdrName name-      _ -> return ()+  indentBody <- case NE.nonEmpty m_pats of+    Nothing ->+      False <$ case style of+        Function name -> p_rdrName name+        _ -> return ()     Just ne_pats -> do-      let combinedSpans =-            combineSrcSpans' $-              getLoc <$> ne_pats-          inci' =-            if isOneLineSpan combinedSpans-              then id-              else inci+      let combinedSpans = case style of+            Function name -> combineSrcSpans (getLoc name) patSpans+            _ -> patSpans+          patSpans = combineSrcSpans' (getLoc <$> ne_pats)+          indentBody = not (isOneLineSpan combinedSpans)       switchLayout [combinedSpans] $ do         let stdCase = sep breakpoint (located' p_pat) m_pats         case style of           Function name ->             p_infixDefHelper               isInfix-              inci'+              indentBody               (p_rdrName name)               (located' p_pat <$> m_pats)           PatternBind -> stdCase@@ -212,7 +212,7 @@             when needsSpace space             sitcc stdCase           LambdaCase -> stdCase-      return inci'+      return indentBody   let -- Calculate position of end of patterns. This is useful when we decide       -- about putting certain constructions in hanging positions.       endOfPats = case NE.nonEmpty m_pats of@@ -224,7 +224,7 @@         Case -> True         LambdaCase -> True         _ -> False-  let hasGuards = withGuards grhssGRHSs+      hasGuards = withGuards grhssGRHSs       grhssSpan =         combineSrcSpans' $           getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs@@ -253,7 +253,7 @@           txt "where"           unless whereIsEmpty breakpoint           inci $ located grhssLocalBinds p_hsLocalBinds-  inci' $ do+  inciIf indentBody $ do     unless (length grhssGRHSs > 1) $       case style of         Function _ | hasGuards -> return ()@@ -284,7 +284,7 @@     xs -> do       txt "|"       space-      sitcc (sep (comma >> breakpoint) (sitcc . located' p_stmt) xs)+      sitcc (sep commaDel (sitcc . located' p_stmt) xs)       space       inci $ case style of         EqualSign -> equals@@ -316,7 +316,7 @@         HsHigherOrderApp -> txt "-<<"       placeHanging (exprPlacement (unLoc input)) $         located input p_hsExpr-  HsCmdArrForm NoExtField form Prefix _ cmds -> banana $ sitcc $ do+  HsCmdArrForm NoExtField form Prefix _ cmds -> banana $ do     located form p_hsExpr     unless (null cmds) $ do       breakpoint@@ -353,7 +353,14 @@   HsCmdTop NoExtField cmd -> located cmd p_hsCmd   XCmdTop x -> noExtCon x -withSpacing :: Data a => (a -> R ()) -> Located a -> R ()+-- | Render an expression preserving blank lines between such consecutive+-- expressions found in the original source code.+withSpacing ::+  -- | Rendering function+  (a -> R ()) ->+  -- | Entity to render+  Located a ->+  R () withSpacing f l = located l $ \x -> do   case getLoc l of     UnhelpfulSpan _ -> f x@@ -464,30 +471,24 @@ p_hsLocalBinds :: HsLocalBindsLR GhcPs GhcPs -> R () p_hsLocalBinds = \case   HsValBinds NoExtField (ValBinds NoExtField bag lsigs) -> do-    let ssStart =-          either-            (srcSpanStart . getLoc)-            (srcSpanStart . getLoc)-        items =-          (Left <$> bagToList bag) ++ (Right <$> lsigs)-        p_item (Left x) = located x p_valDecl-        p_item (Right x) = located x p_sigDecl     -- When in a single-line layout, there is a chance that the inner     -- elements will also contain semicolons and they will confuse the     -- parser. so we request braces around every element except the last.     br <- layoutToBraces <$> getLayout-    sitcc $-      sepSemi-        ( \(p, i) ->-            ( case p of-                SinglePos -> id-                FirstPos -> br-                MiddlePos -> br-                LastPos -> id-            )-              (p_item i)-        )-        (attachRelativePos $ sortOn ssStart items)+    let items =+          let injectLeft (L l x) = L l (Left x)+              injectRight (L l x) = L l (Right x)+           in (injectLeft <$> bagToList bag) ++ (injectRight <$> lsigs)+        positionToBracing = \case+          SinglePos -> id+          FirstPos -> br+          MiddlePos -> br+          LastPos -> id+        p_item' (p, item) =+          positionToBracing p $+            withSpacing (either p_valDecl p_sigDecl) item+        binds = sortOn (srcSpanStart . getLoc) items+    sitcc $ sepSemi p_item' (attachRelativePos binds)   HsValBinds NoExtField _ -> notImplemented "HsValBinds"   HsIPBinds NoExtField (IPBinds NoExtField xs) ->     -- Second argument of IPBind is always Left before type-checking.@@ -520,12 +521,6 @@             else Normal     placeHanging placement (located hsRecFieldArg p_hsExpr) -p_hsTupArg :: HsTupArg GhcPs -> R ()-p_hsTupArg = \case-  Present NoExtField x -> located x p_hsExpr-  Missing NoExtField -> pure ()-  XTupArg x -> noExtCon x- p_hsExpr :: HsExpr GhcPs -> R () p_hsExpr = p_hsExpr' N @@ -589,23 +584,21 @@             -- do-block or case expression it is not a good idea. It seems             -- to be safe to always bump indentation when the function             -- expression is parenthesised.-            indent =+            doIndent =               case func of-                L _ (HsPar NoExtField _) -> inci-                L _ (HsAppType NoExtField _ _) -> inci-                L _ (HsMultiIf NoExtField _) -> inci-                L spn _ ->-                  if isOneLineSpan spn-                    then inci-                    else id-        ub <- getLayout <&> \case-          SingleLine -> useBraces-          MultiLine -> id+                L _ (HsPar NoExtField _) -> True+                L _ (HsAppType NoExtField _ _) -> True+                L _ (HsMultiIf NoExtField _) -> True+                L spn _ -> isOneLineSpan spn+        ub <-+          getLayout <&> \case+            SingleLine -> useBraces+            MultiLine -> id         ub $ do           located func (p_hsExpr' s)           breakpoint-          indent $ sep breakpoint (located' p_hsExpr) initp-        indent $ do+          inciIf doIndent $ sep breakpoint (located' p_hsExpr) initp+        inciIf doIndent $ do           unless (null initp) breakpoint           located lastp p_hsExpr       Hanging -> do@@ -620,10 +613,15 @@     breakpoint     inci $ do       txt "@"+      -- Insert a space when the type is represented as a TH splice to avoid+      -- gluing @ and $ together.+      case unLoc (hswc_body a) of+        HsSpliceTy {} -> space+        _ -> return ()       located (hswc_body a) p_hsType   OpApp NoExtField x op y -> do     let opTree = OpBranch (exprOpTree x) op (exprOpTree y)-    p_exprOpTree True s (reassociateOpTree getOpName opTree)+    p_exprOpTree s (reassociateOpTree getOpName opTree)   NegApp NoExtField e _ -> do     txt "-"     space@@ -640,22 +638,27 @@     let isRecordDot' = isRecordDot (unLoc op) (getLoc x)     unless (useRecordDot' && isRecordDot') breakpoint     inci (located x p_hsExpr)-  ExplicitTuple NoExtField args boxity -> do+  ExplicitTuple NoExtField args boxity ->     let isSection = any (isMissing . unLoc) args         isMissing = \case           Missing NoExtField -> True           _ -> False-    let parens' =+        p_arg = \case+          Present NoExtField x -> located x p_hsExpr+          Missing NoExtField -> pure ()+          XTupArg x -> noExtCon x+        p_larg = sitcc . located' p_arg+        parens' =           case boxity of             Boxed -> parens             Unboxed -> parensHash-    if isSection-      then-        switchLayout [] . parens' s $-          sep comma (located' p_hsTupArg) args-      else-        switchLayout (getLoc <$> args) . parens' s . sitcc $-          sep (comma >> breakpoint) (sitcc . located' p_hsTupArg) args+     in if isSection+          then+            switchLayout [] . parens' s $+              sep comma p_larg args+          else+            switchLayout (getLoc <$> args) . parens' s $+              sep commaDel p_larg args   ExplicitSum NoExtField tag arity e ->     p_unboxedSum N tag arity (located e p_hsExpr)   HsCase NoExtField e mgroup ->@@ -665,7 +668,7 @@   HsMultiIf NoExtField guards -> do     txt "if"     breakpoint-    inci . inci . sitcc $ sep newline (located' (p_grhs RightArrow)) guards+    inci . inci $ sep newline (located' (p_grhs RightArrow)) guards   HsLet NoExtField localBinds e ->     p_let p_hsExpr localBinds e   HsDo NoExtField ctx es -> do@@ -677,15 +680,15 @@             sepSemi               (ub . withSpacing (p_stmt' exprPlacement (p_hsExpr' S)))               (unLoc es)-        compBody = brackets N $ located es $ \xs -> do+        compBody = brackets N . located es $ \xs -> do           let p_parBody =                 sep-                  (breakpoint >> txt "| ")+                  (breakpoint >> txt "|" >> space)                   p_seqBody               p_seqBody =                 sitcc                   . sep-                    (comma >> breakpoint)+                    commaDel                     (located' (sitcc . p_stmt))               stmts = init xs               yield = last xs@@ -706,8 +709,8 @@       ParStmtCtxt _ -> notImplemented "ParStmtCtxt"       TransStmtCtxt _ -> notImplemented "TransStmtCtxt"   ExplicitList _ _ xs ->-    brackets s . sitcc $-      sep (comma >> breakpoint) (sitcc . located' p_hsExpr) xs+    brackets s $+      sep commaDel (sitcc . located' p_hsExpr) xs   RecordCon {..} -> do     located rcon_con_name atom     breakpoint@@ -723,8 +726,8 @@           case rec_dotdot of             Just {} -> [txt ".."]             Nothing -> []-    inci . braces N . sitcc $-      sep (comma >> breakpoint) sitcc (fields <> dotdot)+    inci . braces N $+      sep commaDel sitcc (fields <> dotdot)   RecordUpd {..} -> do     located rupd_expr p_hsExpr     useRecordDot' <- useRecordDot@@ -742,9 +745,9 @@                 Unambiguous _ n -> n                 XAmbiguousFieldOcc x -> noExtCon x             }-    inci . braces N . sitcc $+    inci . braces N $       sep-        (comma >> breakpoint)+        commaDel         (sitcc . located' (p_hsRecField . updName))         rupd_flds   ExprWithTySig NoExtField x HsWC {hswc_body = HsIB {..}} -> sitcc $ do@@ -757,22 +760,22 @@   ExprWithTySig NoExtField _ (XHsWildCardBndrs x) -> noExtCon x   ArithSeq NoExtField _ x ->     case x of-      From from -> brackets s . sitcc $ do+      From from -> brackets s $ do         located from p_hsExpr         breakpoint         txt ".."-      FromThen from next -> brackets s . sitcc $ do-        sitcc $ sep (comma >> breakpoint) (located' p_hsExpr) [from, next]+      FromThen from next -> brackets s $ do+        sep commaDel (located' p_hsExpr) [from, next]         breakpoint         txt ".."-      FromTo from to -> brackets s . sitcc $ do+      FromTo from to -> brackets s $ do         located from p_hsExpr         breakpoint         txt ".."         space         located to p_hsExpr-      FromThenTo from next to -> brackets s . sitcc $ do-        sitcc $ sep (comma >> breakpoint) (located' p_hsExpr) [from, next]+      FromThenTo from next to -> brackets s $ do+        sep commaDel (located' p_hsExpr) [from, next]         breakpoint         txt ".."         space@@ -849,8 +852,8 @@       inci $ do         switchLayout (getLoc . recordPatSynPatVar <$> xs) $ do           unless (null xs) breakpoint-          braces N . sitcc $-            sep (comma >> breakpoint) (p_rdrName . recordPatSynPatVar) xs+          braces N $+            sep commaDel (p_rdrName . recordPatSynPatVar) xs         rhs     InfixCon l r -> do       switchLayout [getLoc l, getLoc r] $ do@@ -946,13 +949,13 @@     txt "!"     located pat p_pat   ListPat NoExtField pats ->-    brackets S . sitcc $ sep (comma >> breakpoint) (located' p_pat) pats+    brackets S $ sep commaDel (located' p_pat) pats   TuplePat NoExtField pats boxing -> do-    let f =+    let parens' =           case boxing of             Boxed -> parens S             Unboxed -> parensHash S-    f . sitcc $ sep (comma >> breakpoint) (sitcc . located' p_pat) pats+    parens' $ sep commaDel (sitcc . located' p_pat) pats   SumPat NoExtField pat tag arity ->     p_unboxedSum S tag arity (located pat p_pat)   ConPatIn pat details ->@@ -968,7 +971,7 @@         let f = \case               Nothing -> txt ".."               Just x -> located x p_pat_hsRecField-        inci . braces N . sitcc . sep (comma >> breakpoint) f $+        inci . braces N . sep commaDel f $           case dotdot of             Nothing -> Just <$> fields             Just (L _ n) -> (Just <$> take n fields) ++ [Nothing]@@ -1018,17 +1021,15 @@   let before = tag - 1       after = arity - before - 1       args = replicate before Nothing <> [Just m] <> replicate after Nothing-      f (x, i) = do-        let isFirst = i == 0-            isLast = i == arity - 1+      f x =         case x :: Maybe (R ()) of           Nothing ->-            unless (isFirst || isLast) space+            space           Just m' -> do-            unless isFirst space+            space             m'-            unless isLast space-  parensHash s $ sep (txt "|") f (zip args [0 ..])+            space+  parensHash s $ sep (txt "|") f args  p_hsSplice :: HsSplice GhcPs -> R () p_hsSplice = \case@@ -1230,11 +1231,10 @@   HsCase NoExtField _ _ -> Hanging   HsDo NoExtField DoExpr _ -> Hanging   HsDo NoExtField MDoExpr _ -> Hanging-  -- If the rightmost expression in an operator chain is hanging, make the-  -- whole block hanging; so that we can use the common @f = foo $ do@-  -- style.-  OpApp NoExtField _ _ y -> exprPlacement (unLoc y)-  -- Same thing for function applications (usually with -XBlockArguments)+  OpApp NoExtField _ op y ->+    case (fmap getOpNameStr . getOpName . unLoc) op of+      Just "$" -> exprPlacement (unLoc y)+      _ -> Normal   HsApp NoExtField _ y -> exprPlacement (unLoc y)   HsProc NoExtField p _ ->     -- Indentation breaks if pattern is longer than one line and left@@ -1260,15 +1260,16 @@   HsVar NoExtField (L _ a) -> Just a   _ -> Nothing +getOpNameStr :: RdrName -> String+getOpNameStr = occNameString . rdrNameOcc+ p_exprOpTree ::-  -- | Can use special handling of dollar?-  Bool ->   -- | Bracket style to use   BracketStyle ->   OpTree (LHsExpr GhcPs) (LHsExpr GhcPs) ->   R ()-p_exprOpTree _ s (OpNode x) = located x (p_hsExpr' s)-p_exprOpTree isDollarSpecial s (OpBranch x op y) = do+p_exprOpTree s (OpNode x) = located x (p_hsExpr' s)+p_exprOpTree s (OpBranch x op y) = do   -- If the beginning of the first argument and the second argument are on   -- the same line, and the second argument has a hanging form, use hanging   -- placement.@@ -1290,44 +1291,54 @@         MultiLine -> case placement of           Hanging -> useBraces           Normal -> dontUseBraces-      gotDollar = case getOpName (unLoc op) of-        Just rname -> mkVarOcc "$" == rdrNameOcc rname-        _ -> False+      opNameStr = (fmap getOpNameStr . getOpName . unLoc) op+      gotDollar = opNameStr == Just "$"+      gotColon = opNameStr == Just ":"+      gotRecordDot = isRecordDot (unLoc op) (opTreeLoc y)       lhs =         switchLayout [opTreeLoc x] $-          p_exprOpTree (not gotDollar) s x-  let p_op = located op (opWrapper . p_hsExpr)-      p_y = switchLayout [opTreeLoc y] (p_exprOpTree True N y)+          p_exprOpTree s x+      p_op = located op (opWrapper . p_hsExpr)+      p_y = switchLayout [opTreeLoc y] (p_exprOpTree N y)       isSection = case (opTreeLoc x, getLoc op) of         (RealSrcSpan treeSpan, RealSrcSpan opSpan) ->           srcSpanEndCol treeSpan /= srcSpanStartCol opSpan         _ -> False+      isDoBlock = \case+        OpNode (L _ HsDo {}) -> True+        _ -> False   useRecordDot' <- useRecordDot-  let isRecordDot' = isRecordDot (unLoc op) (opTreeLoc y)-  if useRecordDot' && isRecordDot'-    then do-      lhs-      when isSection space-      p_op-      p_y-    else-      if isDollarSpecial-        && gotDollar-        && placement-        == Normal-        && isOneLineSpan (opTreeLoc x)-        then do-          useBraces lhs-          space-          p_op-          breakpoint-          inci p_y-        else do-          ub lhs-          placeHanging placement $ do-            p_op+  if+      | gotColon -> do+        lhs+        space+        p_op+        case placement of+          Hanging -> do             space             p_y+          Normal -> do+            breakpoint+            inciIf (isDoBlock y) p_y+      | gotDollar+          && isOneLineSpan (opTreeLoc x)+          && placement == Normal -> do+        useBraces lhs+        space+        p_op+        breakpoint+        inci p_y+      | useRecordDot' && gotRecordDot -> do+        lhs+        when isSection space+        p_op+        p_y+      | otherwise -> do+        ub lhs+        placeHanging placement $ do+          p_op+          space+          p_y  -- | Return 'True' if given expression is a record-dot operator expression. isRecordDot ::@@ -1338,13 +1349,9 @@   Bool isRecordDot op (RealSrcSpan ySpan) = case op of   HsVar NoExtField (L (RealSrcSpan opSpan) opName) ->-    isDot opName && (srcSpanEndCol opSpan == srcSpanStartCol ySpan)+    (getOpNameStr opName == ".") && (srcSpanEndCol opSpan == srcSpanStartCol ySpan)   _ -> False isRecordDot _ _ = False---- | Check whether a given 'RdrName' is the dot operator.-isDot :: RdrName -> Bool-isDot name = rdrNameOcc name == mkVarOcc "."  -- | Get annotations for the enclosing element. getEnclosingAnns :: R [AnnKeywordId]
src/Ormolu/Printer/Meat/Declaration/Warning.hs view
@@ -32,10 +32,9 @@ p_topLevelWarning :: [Located RdrName] -> WarningTxt -> R () p_topLevelWarning fnames wtxt = do   let (pragmaText, lits) = warningText wtxt-  switchLayout (fmap getLoc fnames ++ fmap getLoc lits)-    $ pragma pragmaText . inci-    $ do-      sitcc $ sep (comma >> breakpoint) p_rdrName fnames+  switchLayout (fmap getLoc fnames ++ fmap getLoc lits) $+    pragma pragmaText . inci $ do+      sep commaDel p_rdrName fnames       breakpoint       p_lits lits @@ -47,4 +46,4 @@ p_lits :: [Located StringLiteral] -> R () p_lits = \case   [l] -> atom l-  ls -> brackets N . sitcc $ sep (comma >> breakpoint) atom ls+  ls -> brackets N $ sep commaDel atom ls
src/Ormolu/Printer/Meat/ImportExport.hs view
@@ -21,7 +21,7 @@   breakpoint'   txt ")" p_hsmodExports xs =-  parens N . sitcc $ do+  parens N $ do     layout <- getLayout     sep       breakpoint@@ -65,7 +65,7 @@       Nothing -> return ()       Just (_, L _ xs) -> do         breakpoint-        parens N . sitcc $ do+        parens N $ do           layout <- getLayout           sep             breakpoint@@ -93,9 +93,8 @@     inci $ do       let names :: [R ()]           names = located' p_ieWrappedName <$> xs-      parens N . sitcc-        $ sep (comma >> breakpoint) sitcc-        $ case w of+      parens N . sep commaDel sitcc $+        case w of           NoIEWildcard -> names           IEWildcard n ->             let (before, after) = splitAt n names
src/Ormolu/Printer/Meat/Module.hs view
@@ -11,7 +11,7 @@ import Control.Monad import qualified Data.Text as T import GHC-import Ormolu.Imports+import Ormolu.Imports (normalizeImports) import Ormolu.Parser.CommentStream import Ormolu.Parser.Pragma import Ormolu.Parser.Shebang@@ -69,7 +69,7 @@         txt "where"         newline     newline-    forM_ (sortImports hsmodImports) (located' (p_hsmodImport qualifiedPost))+    forM_ (normalizeImports hsmodImports) (located' (p_hsmodImport qualifiedPost))     newline     switchLayout (getLoc <$> hsmodDecls) $ do       p_hsDecls Free hsmodDecls
src/Ormolu/Printer/Meat/Type.hs view
@@ -67,7 +67,7 @@             L _ (HsAppTy _ l r) -> gatherArgs l (r : knownArgs)             _ -> (f', knownArgs)         (func, args) = gatherArgs f [x]-    switchLayout (getLoc f : fmap getLoc args) $ sitcc $ do+    switchLayout (getLoc f : fmap getLoc args) . sitcc $ do       located func p_hsType       breakpoint       inci $@@ -98,10 +98,9 @@             HsBoxedTuple -> parens N             HsConstraintTuple -> parens N             HsBoxedOrConstraintTuple -> parens N-     in parens' . sitcc $-          sep (comma >> breakpoint) (sitcc . located' p_hsType) xs+     in parens' $ sep commaDel (sitcc . located' p_hsType) xs   HsSumTy NoExtField xs ->-    parensHash N . sitcc $+    parensHash N $       sep (txt "|" >> breakpoint) (sitcc . located' p_hsType) xs   HsOpTy NoExtField x op y ->     sitcc $@@ -118,9 +117,9 @@   HsStarTy NoExtField _ -> txt "*"   HsKindSig NoExtField t k -> sitcc $ do     located t p_hsType-    space -- FIXME-    txt "::"     space+    txt "::"+    breakpoint     inci (located k p_hsType)   HsSpliceTy NoExtField splice -> p_hsSplice splice   HsDocTy NoExtField t str ->@@ -154,14 +153,14 @@       case (p, xs) of         (IsPromoted, L _ t : _) | isPromoted t -> space         _ -> return ()-      sitcc $ sep (comma >> breakpoint) (sitcc . located' p_hsType) xs+      sep commaDel (sitcc . located' p_hsType) xs   HsExplicitTupleTy NoExtField xs -> do     txt "'"     parens N $ do       case xs of         L _ t : _ | isPromoted t -> space         _ -> return ()-      sep (comma >> breakpoint) (located' p_hsType) xs+      sep commaDel (located' p_hsType) xs   HsTyLit NoExtField t ->     case t of       HsStrTy (SourceText s) _ -> p_stringLit s@@ -192,9 +191,7 @@ p_hsContext = \case   [] -> txt "()"   [x] -> located x p_hsType-  xs ->-    parens N . sitcc $-      sep (comma >> breakpoint) (sitcc . located' p_hsType) xs+  xs -> parens N $ sep commaDel (sitcc . located' p_hsType) xs  p_hsTyVarBndr :: HsTyVarBndr GhcPs -> R () p_hsTyVarBndr = \case@@ -224,15 +221,14 @@  p_conDeclFields :: [LConDeclField GhcPs] -> R () p_conDeclFields xs =-  braces N . sitcc $-    sep (comma >> breakpoint) (sitcc . located' p_conDeclField) xs+  braces N $ sep commaDel (sitcc . located' p_conDeclField) xs  p_conDeclField :: ConDeclField GhcPs -> R () p_conDeclField ConDeclField {..} = do   mapM_ (p_hsDocString Pipe True) cd_fld_doc   sitcc $     sep-      (comma >> breakpoint)+      commaDel       (located' (p_rdrName . rdrNameFieldOcc))       cd_fld_names   space@@ -274,6 +270,6 @@     -- <https://gitlab.haskell.org/ghc/ghc/issues/17404>. This is fine as     -- long as 'tyVarToType' does not get applied to right-hand sides of     -- declarations.-    HsParTy NoExtField $ noLoc $+    HsParTy NoExtField . noLoc $       HsKindSig NoExtField (noLoc (HsTyVar NoExtField NotPromoted tvar)) kind   XTyVarBndr x -> noExtCon x
src/Ormolu/Printer/Operators.hs view
@@ -16,7 +16,7 @@ import qualified Data.Map.Strict as M import Data.Maybe (fromMaybe, mapMaybe) import GHC-import OccName (mkVarOcc)+import OccName (occNameString) import Ormolu.Utils (unSrcSpan)  -- | Intermediate representation of operator trees. It has two type@@ -57,7 +57,7 @@ reassociateOpTreeWith ::   forall ty op.   -- | Fixity map for operators-  Map RdrName Fixity ->+  Map String Fixity ->   -- | How to get the name of an operator   (op -> Maybe RdrName) ->   -- | Original 'OpTree'@@ -68,8 +68,8 @@   where     fixityOf :: op -> Fixity     fixityOf op = fromMaybe defaultFixity $ do-      opName <- getOpName op-      M.lookup opName fixityMap+      s <- occNameString . rdrNameOcc <$> getOpName op+      M.lookup s fixityMap     -- Here, left branch is already associated and the root alongside with     -- the right branch is right-associated. This function picks up one item     -- from the right and inserts it correctly to the left.@@ -112,26 +112,26 @@   -- | Operator tree   OpTree (Located ty) (Located op) ->   -- | Fixity map-  Map RdrName Fixity+  Map String Fixity buildFixityMap getOpName opTree =   addOverrides     . M.fromList     . concatMap (\(i, ns) -> map (\(n, _) -> (n, fixity i InfixL)) ns)-    . zip [1 ..]+    . zip [2 ..]     . L.groupBy ((==) `on` snd)     . selectScores     $ score opTree   where-    addOverrides :: Map RdrName Fixity -> Map RdrName Fixity+    addOverrides :: Map String Fixity -> Map String Fixity     addOverrides m =-      let mk k v = (mkRdrUnqual (mkVarOcc k), fixity v InfixL)-       in M.fromList-            [ mk "$" 0,-              mk "." 9-            ]-            `M.union` m+      M.fromList+        [ ("$", fixity 0 InfixR),+          (":", fixity 1 InfixR),+          (".", fixity 100 InfixL)+        ]+        `M.union` m     fixity = Fixity NoSourceText-    score :: OpTree (Located ty) (Located op) -> [(RdrName, Score)]+    score :: OpTree (Located ty) (Located op) -> [(String, Score)]     score (OpNode _) = []     score (OpBranch l o r) = fromMaybe (score r) $ do       -- If we fail to get any of these, 'defaultFixity' will be used by@@ -141,13 +141,13 @@       oe <- srcSpanEndLine <$> unSrcSpan (getLoc o) -- operator end       rb <- srcSpanStartLine <$> unSrcSpan (opTreeLoc r) -- right begin       oc <- srcSpanStartCol <$> unSrcSpan (getLoc o) -- operator column-      opName <- getOpName (unLoc o)+      opName <- occNameString . rdrNameOcc <$> getOpName (unLoc o)       let s             | le < ob = AtBeginning oc             | oe < rb = AtEnd             | otherwise = InBetween       return $ (opName, s) : score r-    selectScores :: [(RdrName, Score)] -> [(RdrName, Score)]+    selectScores :: [(String, Score)] -> [(String, Score)]     selectScores =       L.sortOn snd         . mapMaybe
src/Ormolu/Processing/Common.hs view
@@ -20,7 +20,7 @@  -- | Marker for the beginning of the region where Ormolu should be disabled. startDisabling :: IsString s => s-startDisabling = "{- ORMOLU_DISABLING_START"+startDisabling = "{- ORMOLU_DISABLE_START"  -- | Marker for the end of the region where Ormolu should be disabled. endDisabling :: IsString s => s
src/Ormolu/Processing/Postprocess.hs view
@@ -1,3 +1,6 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-}+ -- | Postprocessing for the results of printing. module Ormolu.Processing.Postprocess   ( postprocess,@@ -10,12 +13,19 @@ import qualified Ormolu.Processing.Cpp as Cpp  -- | Postprocess output of the formatter.-postprocess :: Text -> Text-postprocess =+postprocess ::+  -- | Desired indentation level+  Int ->+  -- | Input to process+  Text ->+  Text+postprocess indent =   T.unlines+    . fmap indentLine     . fmap Cpp.unmaskLine     . filter (not . magicComment)     . T.lines   where-    magicComment x =+    magicComment (T.stripStart -> x) =       x == startDisabling || x == endDisabling+    indentLine x = T.replicate indent " " <> x
src/Ormolu/Processing/Preprocess.hs view
@@ -11,8 +11,7 @@ import Control.Monad import Data.Char (isSpace) import qualified Data.List as L-import Data.Maybe (isJust)-import Data.Maybe (maybeToList)+import Data.Maybe (isJust, maybeToList) import FastString import Ormolu.Config (RegionDeltas (..)) import Ormolu.Parser.Shebang (isShebang)@@ -143,7 +142,8 @@   -- | Whether or not the two strings watch   Bool magicComment expected s0 = isJust $ do-  s1 <- dropWhile isSpace <$> L.stripPrefix "{-" s0-  s2 <- dropWhile isSpace <$> L.stripPrefix expected s1+  let trim = dropWhile isSpace+  s1 <- trim <$> L.stripPrefix "{-" (trim s0)+  s2 <- trim <$> L.stripPrefix expected s1   s3 <- L.stripPrefix "-}" s2   guard (all isSpace s3)
src/Ormolu/Utils.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-}  -- | Random utilities used by the code. module Ormolu.Utils@@ -15,12 +16,14 @@     separatedByBlank,     separatedByBlankNE,     onTheSameLine,+    removeIndentation,   ) where +import Data.Char (isSpace) import Data.List (dropWhileEnd)-import qualified Data.List.NonEmpty as NE import Data.List.NonEmpty (NonEmpty (..))+import qualified Data.List.NonEmpty as NE import Data.Maybe (fromMaybe) import Data.Text (Text) import qualified Data.Text as T@@ -139,3 +142,14 @@ onTheSameLine :: SrcSpan -> SrcSpan -> Bool onTheSameLine a b =   isOneLineSpan (mkSrcSpan (srcSpanEnd a) (srcSpanStart b))++-- | Remove indentation from a given 'String'. Return the input with+-- indentation removed and the detected indentation level.+removeIndentation :: String -> (String, Int)+removeIndentation (lines -> xs) = (unlines (drop n <$> xs), n)+  where+    n = minimum (getIndent <$> xs)+    getIndent y =+      if all isSpace y+        then 0+        else length (takeWhile isSpace y)