ormolu 0.7.3.0 → 0.7.4.0
raw patch · 52 files changed
+485/−176 lines, 52 filesdep ~Cabal-syntaxdep ~Diffdep ~ansi-terminalPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: Cabal-syntax, Diff, ansi-terminal, containers, filepath
API changes (from Hackage documentation)
+ Ormolu.Printer.Combinators: askDebug :: R Bool
+ Ormolu.Printer.Internal: askDebug :: R Bool
+ Ormolu.Utils: instance Ormolu.Utils.HasSrcSpan GHC.Types.SrcLoc.RealSrcSpan
- Ormolu.Fixity: inferFixity :: RdrName -> ModuleFixityMap -> FixityApproximation
+ Ormolu.Fixity: inferFixity :: Bool -> RdrName -> ModuleFixityMap -> FixityApproximation
- Ormolu.Fixity.Internal: inferFixity :: RdrName -> ModuleFixityMap -> FixityApproximation
+ Ormolu.Fixity.Internal: inferFixity :: Bool -> RdrName -> ModuleFixityMap -> FixityApproximation
- Ormolu.Printer: printSnippets :: [SourceSnippet] -> Text
+ Ormolu.Printer: printSnippets :: Bool -> [SourceSnippet] -> Text
- Ormolu.Printer.Combinators: runR :: R () -> SpanStream -> CommentStream -> SourceType -> EnumSet Extension -> ModuleFixityMap -> Text
+ Ormolu.Printer.Combinators: runR :: R () -> SpanStream -> CommentStream -> SourceType -> EnumSet Extension -> ModuleFixityMap -> Bool -> Text
- Ormolu.Printer.Internal: runR :: R () -> SpanStream -> CommentStream -> SourceType -> EnumSet Extension -> ModuleFixityMap -> Text
+ Ormolu.Printer.Internal: runR :: R () -> SpanStream -> CommentStream -> SourceType -> EnumSet Extension -> ModuleFixityMap -> Bool -> Text
- Ormolu.Printer.Operators: reassociateOpTree :: (op -> Maybe RdrName) -> ModuleFixityMap -> OpTree ty op -> OpTree ty (OpInfo op)
+ Ormolu.Printer.Operators: reassociateOpTree :: Bool -> (op -> Maybe RdrName) -> ModuleFixityMap -> OpTree ty op -> OpTree ty (OpInfo op)
Files
- CHANGELOG.md +16/−0
- README.md +28/−0
- app/Main.hs +7/−5
- data/examples/declaration/data/ctype-0-out.hs +1/−0
- data/examples/declaration/data/ctype-0.hs +1/−0
- data/examples/declaration/data/ctype-1-out.hs +6/−0
- data/examples/declaration/data/ctype-1.hs +6/−0
- data/examples/declaration/data/ctype-out.hs +0/−1
- data/examples/declaration/data/ctype.hs +0/−1
- data/examples/declaration/data/field-layout/record-0-out.hs +10/−0
- data/examples/declaration/data/field-layout/record-0.hs +9/−0
- data/examples/declaration/data/field-layout/record-1-out.hs +11/−0
- data/examples/declaration/data/field-layout/record-1.hs +10/−0
- data/examples/declaration/data/field-layout/record-2-out.hs +7/−0
- data/examples/declaration/data/field-layout/record-2.hs +7/−0
- data/examples/declaration/data/field-layout/record-out.hs +0/−12
- data/examples/declaration/data/field-layout/record.hs +0/−11
- data/examples/declaration/data/record-fancy-existential-out.hs +6/−0
- data/examples/declaration/data/record-fancy-existential.hs +5/−0
- data/examples/declaration/data/simple-broken-out.hs +2/−1
- data/examples/declaration/value/function/if-single-line-functions-do-out.hs +5/−0
- data/examples/declaration/value/function/if-single-line-functions-do.hs +5/−0
- data/examples/declaration/value/function/if-single-line-functions-out.hs +4/−0
- data/examples/declaration/value/function/if-single-line-functions.hs +4/−0
- data/examples/declaration/value/function/if-with-comment-above-branches-out.hs +7/−0
- data/examples/declaration/value/function/if-with-comment-above-branches.hs +8/−0
- data/examples/declaration/value/function/if-with-comment-before-do-blocks-out.hs +10/−0
- data/examples/declaration/value/function/if-with-comment-before-do-blocks.hs +10/−0
- data/examples/declaration/value/function/if-with-comment-in-branches-out.hs +14/−0
- data/examples/declaration/value/function/if-with-comment-in-branches-with-functions-out.hs +12/−0
- data/examples/declaration/value/function/if-with-comment-in-branches-with-functions.hs +12/−0
- data/examples/declaration/value/function/if-with-comment-in-branches.hs +14/−0
- data/examples/declaration/value/function/if-with-comment-next-to-keyword-out.hs +10/−0
- data/examples/declaration/value/function/if-with-comment-next-to-keyword.hs +10/−0
- data/examples/declaration/value/function/if-with-comment-out.hs +0/−8
- data/examples/declaration/value/function/if-with-comment.hs +0/−8
- data/examples/other/jsffi-out.hs +1/−0
- data/examples/other/jsffi.hs +1/−0
- ormolu.cabal +1/−1
- src/GHC/DynFlags.hs +2/−1
- src/Ormolu.hs +2/−2
- src/Ormolu/Fixity/Internal.hs +55/−16
- src/Ormolu/Printer.hs +4/−1
- src/Ormolu/Printer/Combinators.hs +1/−0
- src/Ormolu/Printer/Internal.hs +13/−3
- src/Ormolu/Printer/Meat/Declaration/Data.hs +88/−83
- src/Ormolu/Printer/Meat/Declaration/Value.hs +43/−13
- src/Ormolu/Printer/Meat/Type.hs +2/−1
- src/Ormolu/Printer/Operators.hs +10/−6
- src/Ormolu/Utils.hs +3/−0
- tests/Ormolu/FixitySpec.hs +1/−1
- tests/Ormolu/OpTreeSpec.hs +1/−1
CHANGELOG.md view
@@ -1,3 +1,19 @@+## Ormolu 0.7.4.0++* Don't error when the `JavaScriptFFI` language pragma is present. [Issue+ 1087](https://github.com/tweag/ormolu/issues/1087).+* Improve comment placement in if-then-else blocks. [Issue+ 998](https://github.com/tweag/ormolu/issues/998).+* Now command line options for fixity overrides and module re-exports+ overwrite information from `.ormolu` files. [Issue+ 1030](https://github.com/tweag/ormolu/issues/1030).+* Respect newlines in data declarations in more cases. [Issue+ 1077](https://github.com/tweag/ormolu/issues/1077) and [issue+ 947](https://github.com/tweag/ormolu/issues/947).+* The `-d / --debug` command line option now makes Ormolu print out debug+ information regarding operator fixity inference. [Issue+ 1060](https://github.com/tweag/ormolu/issues/1060).+ ## Ormolu 0.7.3.0 * Switched to `ghc-lib-parser-9.8`, with the following new syntactic features:
README.md view
@@ -18,6 +18,8 @@ * [Regions](#regions) * [Exit codes](#exit-codes) * [Using as a library](#using-as-a-library)+* [Troubleshooting](#troubleshooting)+ * [Operators are being formatted weirdly!](#operators-are-being-formatted-weirdly) * [Limitations](#limitations) * [Running on Hackage](#running-on-hackage) * [Forks and modifications](#forks-and-modifications)@@ -271,6 +273,32 @@ For these purposes only the top `Ormolu` module should be considered stable. It follows [PVP](https://pvp.haskell.org/) starting from the version 0.5.3.0. Rely on other modules at your own risk.++## Troubleshooting++### Operators are being formatted weirdly!++This can happen when Ormolu doesn't know or can't determine the fixity of an+operator.++* If this is a custom operator, see the instructions in the [Language+ extensions, dependencies, and+ fixities](#language-extensions-dependencies-and-fixities) section to+ specify the correct fixities in a `.ormolu` file.++* If this is a third-party operator (e.g. from `base` or some other package+ from Hackage), Ormolu probably doesn't recognize that the operator is the+ same as the third-party one.++ Some reasons this might be the case:++ * You might have a custom Prelude that re-exports things from Prelude+ * You might have `-XNoImplicitPrelude` turned on++ If any of these are true, make sure to specify the reexports correctly in+ a `.ormolu` file.++You can see how Ormolu decides the fixity of operators if you use `--debug`. ## Limitations
app/Main.hs view
@@ -168,15 +168,17 @@ fromMaybe ModuleSource (reqSourceType <|> mdetectedSourceType)- let mfixityOverrides = fst <$> mdotOrmolu- mmoduleReexports = snd <$> mdotOrmolu return $ refineConfig sourceType mcabalInfo- mfixityOverrides- mmoduleReexports- rawConfig+ (Just (cfgFixityOverrides rawConfig))+ (Just (cfgModuleReexports rawConfig))+ ( rawConfig+ { cfgFixityOverrides = maybe defaultFixityOverrides fst mdotOrmolu,+ cfgModuleReexports = maybe defaultModuleReexports snd mdotOrmolu+ }+ ) handleDiff originalInput formattedInput fileRepr = case diffText originalInput formattedInput fileRepr of Nothing -> return ExitSuccess
+ data/examples/declaration/data/ctype-0-out.hs view
@@ -0,0 +1,1 @@+data {-# CTYPE "unistd.h" "useconds_t" #-} T
+ data/examples/declaration/data/ctype-0.hs view
@@ -0,0 +1,1 @@+data {-# CTYPE "unistd.h" "useconds_t" #-} T
+ data/examples/declaration/data/ctype-1-out.hs view
@@ -0,0 +1,6 @@+data+ {-# CTYPE "header.h" "an-ffi-type-with-along-name" #-}+ AnFFITypeWithAlongName = AnFFITypeWithAlongName+ { a :: X,+ b :: Y+ }
+ data/examples/declaration/data/ctype-1.hs view
@@ -0,0 +1,6 @@+data+ {-# CTYPE "header.h" "an-ffi-type-with-along-name" #-}+ AnFFITypeWithAlongName = AnFFITypeWithAlongName+ { a :: X,+ b :: Y+ }
− data/examples/declaration/data/ctype-out.hs
@@ -1,1 +0,0 @@-data {-# CTYPE "unistd.h" "useconds_t" #-} T
− data/examples/declaration/data/ctype.hs
@@ -1,1 +0,0 @@-data {-# CTYPE "unistd.h" "useconds_t" #-} T
+ data/examples/declaration/data/field-layout/record-0-out.hs view
@@ -0,0 +1,10 @@+-- | Foo.+data Foo = Foo+ { -- | Something+ foo :: Foo Int Int,+ -- | Something else+ bar ::+ Bar+ Char+ Char+ }
+ data/examples/declaration/data/field-layout/record-0.hs view
@@ -0,0 +1,9 @@+-- | Foo.++data Foo = Foo+ { foo :: Foo Int Int+ -- ^ Something+ , bar :: Bar Char+ Char+ -- ^ Something else+ }
+ data/examples/declaration/data/field-layout/record-1-out.hs view
@@ -0,0 +1,11 @@+-- | Foo.+data Foo+ = Foo+ { -- | Something+ foo :: Foo Int Int,+ -- | Something else+ bar ::+ Bar+ Char+ Char+ }
+ data/examples/declaration/data/field-layout/record-1.hs view
@@ -0,0 +1,10 @@+-- | Foo.++data Foo =+ Foo+ { foo :: Foo Int Int+ -- ^ Something+ , bar :: Bar Char+ Char+ -- ^ Something else+ }
+ data/examples/declaration/data/field-layout/record-2-out.hs view
@@ -0,0 +1,7 @@+data IndexWithInfo schema+ = forall x.+ IndexWithInfo+ { checkedIndex :: Index schema x,+ checkedIndexName :: U.Variable,+ checkedIndexType :: Type x+ }
+ data/examples/declaration/data/field-layout/record-2.hs view
@@ -0,0 +1,7 @@+data IndexWithInfo schema =+ forall x.+ IndexWithInfo+ { checkedIndex :: Index schema x+ , checkedIndexName :: U.Variable+ , checkedIndexType :: Type x+ }
− data/examples/declaration/data/field-layout/record-out.hs
@@ -1,12 +0,0 @@-module Main where---- | Foo.-data Foo = Foo- { -- | Something- foo :: Foo Int Int,- -- | Something else- bar ::- Bar- Char- Char- }
− data/examples/declaration/data/field-layout/record.hs
@@ -1,11 +0,0 @@-module Main where---- | Foo.--data Foo = Foo- { foo :: Foo Int Int- -- ^ Something- , bar :: Bar Char- Char- -- ^ Something else- }
+ data/examples/declaration/data/record-fancy-existential-out.hs view
@@ -0,0 +1,6 @@+{-# LANGUAGE ExistentialQuantification #-}++data Foo = forall a b. (Show a, Eq b) => Bar+ { foo :: a,+ bars :: b+ }
+ data/examples/declaration/data/record-fancy-existential.hs view
@@ -0,0 +1,5 @@+{-# LANGUAGE ExistentialQuantification #-}+data Foo = forall a b . (Show a, Eq b) => Bar+ { foo :: a+ , bars :: b+ }
data/examples/declaration/data/simple-broken-out.hs view
@@ -1,7 +1,8 @@ module Main where -- | Here we go.-data Foo = Foo {unFoo :: Int}+data Foo+ = Foo {unFoo :: Int} deriving (Eq) -- | And once again.
+ data/examples/declaration/value/function/if-single-line-functions-do-out.hs view
@@ -0,0 +1,5 @@+foo x = do+ y <- quux+ if x > 2+ then bar x+ else baz y
+ data/examples/declaration/value/function/if-single-line-functions-do.hs view
@@ -0,0 +1,5 @@+foo x = do+ y <- quux+ if x > 2+ then bar x+ else baz y
+ data/examples/declaration/value/function/if-single-line-functions-out.hs view
@@ -0,0 +1,4 @@+foo x =+ if x > 2+ then bar x+ else baz x
+ data/examples/declaration/value/function/if-single-line-functions.hs view
@@ -0,0 +1,4 @@+foo x =+ if x > 2+ then bar x+ else baz x
+ data/examples/declaration/value/function/if-with-comment-above-branches-out.hs view
@@ -0,0 +1,7 @@+foo =+ if undefined+ -- then comment+ then undefined+ -- else comment+ else do+ undefined
+ data/examples/declaration/value/function/if-with-comment-above-branches.hs view
@@ -0,0 +1,8 @@+foo =+ if undefined+ -- then comment+ then undefined+ -- else comment+ else+ do+ undefined
+ data/examples/declaration/value/function/if-with-comment-before-do-blocks-out.hs view
@@ -0,0 +1,10 @@+foo =+ if something+ -- then comment+ then do+ stuff+ stuff+ -- else comment+ else do+ stuff+ stuff
+ data/examples/declaration/value/function/if-with-comment-before-do-blocks.hs view
@@ -0,0 +1,10 @@+foo =+ if something+ -- then comment+ then do+ stuff+ stuff+ -- else comment+ else do+ stuff+ stuff
+ data/examples/declaration/value/function/if-with-comment-in-branches-out.hs view
@@ -0,0 +1,14 @@+foo =+ if x+ then+ -- comment 1+ -- comment 2+ case a of+ Just b -> _+ Nothing -> _+ else+ -- comment 3+ -- comment 4+ case a of+ Just b -> _+ Nothing -> _
+ data/examples/declaration/value/function/if-with-comment-in-branches-with-functions-out.hs view
@@ -0,0 +1,12 @@+foo =+ if x+ then+ -- comment 1+ -- comment 2+ foo 1 2 3+ else+ -- comment 3+ -- comment 4+ foo+ "here"+ "there"
+ data/examples/declaration/value/function/if-with-comment-in-branches-with-functions.hs view
@@ -0,0 +1,12 @@+foo =+ if x+ then+ -- comment 1+ -- comment 2+ foo 1 2 3+ else+ -- comment 3+ -- comment 4+ foo+ "here"+ "there"
+ data/examples/declaration/value/function/if-with-comment-in-branches.hs view
@@ -0,0 +1,14 @@+foo =+ if x+ then+ -- comment 1+ -- comment 2+ case a of+ Just b -> _+ Nothing -> _+ else+ -- comment 3+ -- comment 4+ case a of+ Just b -> _+ Nothing -> _
+ data/examples/declaration/value/function/if-with-comment-next-to-keyword-out.hs view
@@ -0,0 +1,10 @@+foo =+ if x+ then -- comment 1+ -- comment 2+ foo 1 2 3+ else -- comment 3+ -- comment 4+ foo+ "here"+ "there"
+ data/examples/declaration/value/function/if-with-comment-next-to-keyword.hs view
@@ -0,0 +1,10 @@+foo =+ if x+ then -- comment 1+ -- comment 2+ foo 1 2 3+ else -- comment 3+ -- comment 4+ foo+ "here"+ "there"
− data/examples/declaration/value/function/if-with-comment-out.hs
@@ -1,8 +0,0 @@-foo =- if undefined- then -- then comment- undefined- else -- else comment-- do- undefined
− data/examples/declaration/value/function/if-with-comment.hs
@@ -1,8 +0,0 @@-foo =- if undefined- -- then comment- then undefined- -- else comment- else- do- undefined
+ data/examples/other/jsffi-out.hs view
@@ -0,0 +1,1 @@+{-# LANGUAGE JavaScriptFFI #-}
+ data/examples/other/jsffi.hs view
@@ -0,0 +1,1 @@+{-# language JavaScriptFFI #-}
ormolu.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: ormolu-version: 0.7.3.0+version: 0.7.4.0 license: BSD-3-Clause license-file: LICENSE.md maintainer: Mark Karpov <mark.karpov@tweag.io>
src/GHC/DynFlags.hs view
@@ -26,7 +26,8 @@ Platform { platformArchOS = ArchOS- { archOS_arch = ArchUnknown,+ { -- see https://github.com/tweag/ormolu/issues/1087+ archOS_arch = ArchJavaScript, archOS_OS = OSUnknown }, platformWordSize = PW8,
src/Ormolu.hs view
@@ -112,7 +112,7 @@ -- when we try to parse the rendered code back, inside of GHC monad -- wrapper which will lead to error messages presenting the exceptions as -- GHC bugs.- let !formattedText = printSnippets result0+ let !formattedText = printSnippets (cfgDebug cfg) result0 when (not (cfgUnsafe cfg) || cfgCheckIdempotence cfg) $ do -- Parse the result of pretty-printing again and make sure that AST -- is the same as AST of original snippet module span positions.@@ -138,7 +138,7 @@ -- Try re-formatting the formatted result to check if we get exactly -- the same output. when (cfgCheckIdempotence cfg) . liftIO $- let reformattedText = printSnippets result1+ let reformattedText = printSnippets (cfgDebug cfg) result1 in case diffText formattedText reformattedText path of Nothing -> return () Just diff -> throwIO (OrmoluNonIdempotentOutput diff)
src/Ormolu/Fixity/Internal.hs view
@@ -42,6 +42,7 @@ import Data.Text (Text) import Data.Text qualified as T import Data.Text.Encoding qualified as T+import Debug.Trace (trace) import Distribution.ModuleName (ModuleName) import Distribution.Types.PackageName import GHC.Data.FastString (fs_sbs)@@ -256,24 +257,62 @@ deriving stock (Eq, Show) -- | Get a 'FixityApproximation' of an operator.-inferFixity :: RdrName -> ModuleFixityMap -> FixityApproximation-inferFixity rdrName (ModuleFixityMap m) =- case Map.lookup opName m of- Nothing -> defaultFixityApproximation- Just (Given fixityInfo) ->- fixityInfoToApproximation fixityInfo- Just (FromModuleImports xs) ->- let isMatching (provenance, _fixityInfo) =- case provenance of- UnqualifiedAndQualified mn ->- maybe True (== mn) moduleName- OnlyQualified mn ->- maybe False (== mn) moduleName- in fromMaybe defaultFixityApproximation- . foldMap (Just . fixityInfoToApproximation . snd)- $ NE.filter isMatching xs+inferFixity ::+ -- | Whether to print debug info regarding fixity inference+ Bool ->+ -- | Operator name+ RdrName ->+ -- | Module fixity map+ ModuleFixityMap ->+ -- | The resulting fixity approximation+ FixityApproximation+inferFixity debug rdrName (ModuleFixityMap m) =+ if debug+ then+ trace+ (renderFixityJustification opName moduleName m result)+ result+ else result where+ result =+ case Map.lookup opName m of+ Nothing -> defaultFixityApproximation+ Just (Given fixityInfo) ->+ fixityInfoToApproximation fixityInfo+ Just (FromModuleImports xs) ->+ let isMatching (provenance, _fixityInfo) =+ case provenance of+ UnqualifiedAndQualified mn ->+ maybe True (== mn) moduleName+ OnlyQualified mn ->+ maybe False (== mn) moduleName+ in fromMaybe defaultFixityApproximation+ . foldMap (Just . fixityInfoToApproximation . snd)+ $ NE.filter isMatching xs opName = occOpName (rdrNameOcc rdrName) moduleName = case rdrName of Qual x _ -> Just (ghcModuleNameToCabal x) _ -> Nothing++-- | Render a human-readable account of why a certain 'FixityApproximation'+-- was chosen for an operator.+renderFixityJustification ::+ -- | Operator name+ OpName ->+ -- | Qualification of the operator name+ Maybe ModuleName ->+ -- | Module fixity map+ Map OpName FixityProvenance ->+ -- | The chosen fixity approximation+ FixityApproximation ->+ String+renderFixityJustification opName mqualification m approximation =+ concat+ [ "FIXITY analysis of ",+ show opName,+ case mqualification of+ Nothing -> ""+ Just mn -> " qualified in " ++ show mn,+ "\n Provenance: " ++ show (Map.lookup opName m),+ "\n Inferred: " ++ show approximation+ ]
src/Ormolu/Printer.hs view
@@ -17,11 +17,13 @@ -- | Render several source snippets. printSnippets ::+ -- | Whether to print out debug information during printing+ Bool -> -- | Result of parsing [SourceSnippet] -> -- | Resulting rendition Text-printSnippets = T.concat . fmap printSnippet+printSnippets debug = T.concat . fmap printSnippet where printSnippet = \case ParsedSnippet ParseResult {..} ->@@ -37,4 +39,5 @@ prSourceType prExtensions prModuleFixityMap+ debug RawSnippet r -> r
src/Ormolu/Printer/Combinators.hs view
@@ -24,6 +24,7 @@ inciIf, askSourceType, askModuleFixityMap,+ askDebug, located, encloseLocated, located',
src/Ormolu/Printer/Internal.hs view
@@ -18,6 +18,7 @@ newline, askSourceType, askModuleFixityMap,+ askDebug, inci, sitcc, Layout (..),@@ -100,7 +101,9 @@ -- | Whether the source is a signature or a regular module rcSourceType :: SourceType, -- | Module fixity map- rcModuleFixityMap :: ModuleFixityMap+ rcModuleFixityMap :: ModuleFixityMap,+ -- | Whether to print out debug information during printing+ rcDebug :: !Bool } -- | State context of 'R'.@@ -171,8 +174,9 @@ -- | Module fixity map ModuleFixityMap -> -- | Resulting rendition+ Bool -> Text-runR (R m) sstream cstream sourceType extensions moduleFixityMap =+runR (R m) sstream cstream sourceType extensions moduleFixityMap debug = TL.toStrict . toLazyText . scBuilder $ execState (runReaderT m rc) sc where rc =@@ -183,7 +187,8 @@ rcCanUseBraces = False, rcExtensions = extensions, rcSourceType = sourceType,- rcModuleFixityMap = moduleFixityMap+ rcModuleFixityMap = moduleFixityMap,+ rcDebug = debug } sc = SC@@ -383,6 +388,11 @@ -- | Retrieve the module fixity map. askModuleFixityMap :: R ModuleFixityMap askModuleFixityMap = R (asks rcModuleFixityMap)++-- | Retrieve whether we should print out certain debug information while+-- printing.+askDebug :: R Bool+askDebug = R (asks rcDebug) inciBy :: Int -> R () -> R () inciBy step (R m) = R (local modRC m)
src/Ormolu/Printer/Meat/Declaration/Data.hs view
@@ -50,74 +50,78 @@ txt $ case style of Associated -> mempty Free -> " instance"- case unLoc <$> dd_cType of- Nothing -> pure ()- Just (CType prag header (type_, _)) -> do- space- p_sourceText prag- case header of- Nothing -> pure ()- Just (Header h _) -> space *> p_sourceText h- space- p_sourceText type_- txt " #-}" let constructorSpans = getLocA name : fmap getTyVarLoc tyVars sigSpans = maybeToList . fmap getLocA $ dd_kindSig+ contextSpans = maybeToList . fmap getLocA $ dd_ctxt+ ctypeSpans = maybeToList . fmap getLocA $ dd_cType declHeaderSpans =- maybeToList (getLocA <$> dd_ctxt) ++ constructorSpans ++ sigSpans- switchLayout declHeaderSpans $ do- breakpoint- inci $ do- case dd_ctxt of- Nothing -> pure ()- Just ctxt -> do- located ctxt p_hsContext- space- txt "=>"- breakpoint- switchLayout constructorSpans $- p_infixDefHelper- (isInfix fixity)- True- (p_rdrName name)- (p_tyVar <$> tyVars)- forM_ dd_kindSig $ \k -> do- space- txt "::"+ constructorSpans ++ sigSpans ++ contextSpans ++ ctypeSpans+ switchLayout declHeaderSpans . inci $ do+ case unLoc <$> dd_cType of+ Nothing -> pure ()+ Just (CType prag header (type_, _)) -> do breakpoint- inci $ located k p_hsType+ p_sourceText prag+ case header of+ Nothing -> pure ()+ Just (Header h _) -> space *> p_sourceText h+ space+ p_sourceText type_+ txt " #-}"+ breakpoint+ forM_ dd_ctxt p_lhsContext+ switchLayout constructorSpans $+ p_infixDefHelper+ (isInfix fixity)+ True+ (p_rdrName name)+ (p_tyVar <$> tyVars)+ forM_ dd_kindSig $ \k -> do+ space+ txt "::"+ breakpoint+ inci $ located k p_hsType let dd_cons' = case dd_cons of NewTypeCon a -> [a] DataTypeCons _ as -> as gadt = isJust dd_kindSig || any (isGadt . unLoc) dd_cons'- unless (null dd_cons') $- if gadt- then inci $ do- switchLayout declHeaderSpans $ do+ case dd_cons' of+ [] -> pure ()+ first_dd_cons : _ ->+ if gadt+ then inci $ do+ switchLayout declHeaderSpans $ do+ breakpoint+ txt "where" breakpoint- txt "where"- breakpoint- sepSemi (located' (p_conDecl False)) dd_cons'- else switchLayout (getLocA name : (getLocA <$> dd_cons')) . inci $ do- let singleConstRec = isSingleConstRec dd_cons'- if hasHaddocks dd_cons'- then newline- else- if singleConstRec- then space- else breakpoint- equals- space- layout <- getLayout- let s =- if layout == MultiLine || hasHaddocks dd_cons'- then newline >> txt "|" >> space- else space >> txt "|" >> space- sitcc' =- if hasHaddocks dd_cons' || not singleConstRec- then sitcc- else id- sep s (sitcc' . located' (p_conDecl singleConstRec)) dd_cons'+ sepSemi (located' (p_conDecl False)) dd_cons'+ else switchLayout (getLocA name : (getLocA <$> dd_cons')) . inci $ do+ let singleConstRec = isSingleConstRec dd_cons'+ compactLayoutAroundEquals =+ onTheSameLine+ (getLocA name)+ (combineSrcSpans' (conDeclConsSpans (unLoc first_dd_cons)))+ conDeclConsSpans = \case+ ConDeclGADT {..} -> getLocA <$> con_names+ ConDeclH98 {..} -> getLocA con_name :| []+ if hasHaddocks dd_cons'+ then newline+ else+ if singleConstRec && compactLayoutAroundEquals+ then space+ else breakpoint+ equals+ space+ layout <- getLayout+ let s =+ if layout == MultiLine || hasHaddocks dd_cons'+ then newline >> txt "|" >> space+ else space >> txt "|" >> space+ sitcc' =+ if hasHaddocks dd_cons' || not singleConstRec+ then sitcc+ else id+ sep s (sitcc' . located' (p_conDecl singleConstRec)) dd_cons' unless (null dd_derivs) breakpoint inci $ sep newline (located' p_hsDerivingClause) dd_derivs @@ -171,46 +175,47 @@ located quantifiedTy p_hsType ConDeclH98 {..} -> do mapM_ (p_hsDoc Pipe True) con_doc- let conDeclWithContextSpn =+ let conNameSpn = getLocA con_name+ conNameWithContextSpn = [ RealSrcSpan real Strict.Nothing | Just (EpaSpan real _) <- matchAddEpAnn AnnForall <$> epAnnAnns con_ext ] <> fmap getLocA con_ex_tvs <> maybeToList (fmap getLocA con_mb_cxt)- <> conDeclSpn- conDeclSpn = getLocA con_name : conArgsSpans+ <> [conNameSpn]+ conDeclSpn = conNameSpn : conArgsSpans where conArgsSpans = case con_args of PrefixCon [] xs -> getLocA . hsScaledThing <$> xs PrefixCon (v : _) _ -> absurd v RecCon l -> [getLocA l] InfixCon x y -> getLocA . hsScaledThing <$> [x, y]- switchLayout conDeclWithContextSpn $ do+ switchLayout conNameWithContextSpn $ do when con_forall $ do p_forallBndrs ForAllInvis p_hsTyVarBndr con_ex_tvs breakpoint forM_ con_mb_cxt p_lhsContext- switchLayout conDeclSpn $ case con_args of- PrefixCon [] xs -> do- p_rdrName con_name- let args = hsScaledThing <$> xs- argsHaveDocs = conArgsHaveHaddocks args- delimiter = if argsHaveDocs then newline else breakpoint- unless (null xs) delimiter- inci . sitcc $- sep delimiter (sitcc . located' p_hsType) args- PrefixCon (v : _) _ -> absurd v- RecCon l -> do+ switchLayout conDeclSpn $ case con_args of+ PrefixCon [] xs -> do+ p_rdrName con_name+ let args = hsScaledThing <$> xs+ argsHaveDocs = conArgsHaveHaddocks args+ delimiter = if argsHaveDocs then newline else breakpoint+ unless (null xs) delimiter+ inci . sitcc $+ sep delimiter (sitcc . located' p_hsType) args+ PrefixCon (v : _) _ -> absurd v+ RecCon l -> do+ p_rdrName con_name+ breakpoint+ inciIf (not singleConstRec) (located l p_conDeclFields)+ InfixCon (HsScaled _ x) (HsScaled _ y) -> do+ located x p_hsType+ breakpoint+ inci $ do p_rdrName con_name- breakpoint- inciIf (not singleConstRec) (located l p_conDeclFields)- InfixCon (HsScaled _ x) (HsScaled _ y) -> do- located x p_hsType- breakpoint- inci $ do- p_rdrName con_name- space- located y p_hsType+ space+ located y p_hsType p_lhsContext :: LHsContext GhcPs ->
src/Ormolu/Printer/Meat/Declaration/Value.hs view
@@ -348,10 +348,11 @@ inci (sequence_ (intersperse breakpoint (located' (p_hsCmdTop N) <$> cmds))) HsCmdArrForm _ form Infix _ [left, right] -> do modFixityMap <- askModuleFixityMap+ debug <- askDebug let opTree = BinaryOpBranches (cmdOpTree left) form (cmdOpTree right) p_cmdOpTree s- (reassociateOpTree (getOpName . unLoc) modFixityMap opTree)+ (reassociateOpTree debug (getOpName . unLoc) modFixityMap opTree) HsCmdArrForm _ _ Infix _ _ -> notImplemented "HsCmdArrForm" HsCmdApp _ cmd expr -> do located cmd (p_hsCmd' Applicand s)@@ -363,8 +364,8 @@ p_case isApp cmdPlacement p_hsCmd e mgroup HsCmdLamCase _ variant mgroup -> p_lamcase isApp variant cmdPlacement p_hsCmd mgroup- HsCmdIf _ _ if' then' else' ->- p_if cmdPlacement p_hsCmd if' then' else'+ HsCmdIf anns _ if' then' else' ->+ p_if cmdPlacement p_hsCmd anns if' then' else' HsCmdLet _ _ localBinds _ c -> p_let p_hsCmd localBinds c HsCmdDo _ es -> do@@ -679,10 +680,11 @@ located (hswc_body a) p_hsType OpApp _ x op y -> do modFixityMap <- askModuleFixityMap+ debug <- askDebug let opTree = BinaryOpBranches (exprOpTree x) op (exprOpTree y) p_exprOpTree s- (reassociateOpTree (getOpName . unLoc) modFixityMap opTree)+ (reassociateOpTree debug (getOpName . unLoc) modFixityMap opTree) NegApp _ e _ -> do negativeLiterals <- isExtensionEnabled NegativeLiterals let isLiteral = case unLoc e of@@ -731,8 +733,8 @@ p_unboxedSum N tag arity (located e p_hsExpr) HsCase _ e mgroup -> p_case isApp exprPlacement p_hsExpr e mgroup- HsIf _ if' then' else' ->- p_if exprPlacement p_hsExpr if' then' else'+ HsIf anns if' then' else' ->+ p_if exprPlacement p_hsExpr anns if' then' else' HsMultiIf _ guards -> do txt "if" breakpoint@@ -971,6 +973,8 @@ (body -> Placement) -> -- | Render (body -> R ()) ->+ -- | Annotations+ EpAnn AnnsIf -> -- | If LHsExpr GhcPs -> -- | Then@@ -978,21 +982,47 @@ -- | Else LocatedA body -> R ()-p_if placer render if' then' else' = do+p_if placer render epAnn if' then' else' = do txt "if" space located if' p_hsExpr breakpoint inci $ do- txt "then"+ locatedToken thenSpan "then" space- located then' $ \x ->- placeHanging (placer x) (render x)+ placeHangingLocated thenSpan then' breakpoint- txt "else"+ locatedToken elseSpan "else" space- located else' $ \x ->- placeHanging (placer x) (render x)+ placeHangingLocated elseSpan else'+ where+ (thenSpan, elseSpan, commentSpans) =+ case epAnn of+ EpAnn {anns = AnnsIf {aiThen, aiElse}, comments} ->+ ( loc' $ epaLocationRealSrcSpan aiThen,+ loc' $ epaLocationRealSrcSpan aiElse,+ map (anchor . getLoc) $+ case comments of+ EpaComments cs -> cs+ EpaCommentsBalanced pre post -> pre <> post+ )+ EpAnnNotUsed ->+ (noSrcSpan, noSrcSpan, [])++ locatedToken tokenSpan token =+ located (L tokenSpan ()) $ \_ -> txt token++ betweenSpans spanA spanB s = spanA < s && s < spanB++ placeHangingLocated tokenSpan bodyLoc@(L _ body) = do+ let bodySpan = getLoc' bodyLoc+ hasComments = fromMaybe False $ do+ tokenRealSpan <- srcSpanToRealSrcSpan tokenSpan+ bodyRealSpan <- srcSpanToRealSrcSpan bodySpan+ pure $ any (betweenSpans tokenRealSpan bodyRealSpan) commentSpans+ placement = if hasComments then Normal else placer body+ switchLayout [tokenSpan, bodySpan] $+ placeHanging placement (located bodyLoc render) p_let :: -- | Render
src/Ormolu/Printer/Meat/Type.hs view
@@ -110,9 +110,10 @@ sep (space >> txt "|" >> breakpoint) (sitcc . located' p_hsType) xs HsOpTy _ _ x op y -> do modFixityMap <- askModuleFixityMap+ debug <- askDebug let opTree = BinaryOpBranches (tyOpTree x) op (tyOpTree y) p_tyOpTree- (reassociateOpTree (Just . unLoc) modFixityMap opTree)+ (reassociateOpTree debug (Just . unLoc) modFixityMap opTree) HsParTy _ t -> parens N (located t p_hsType) HsIParamTy _ n t -> sitcc $ do
src/Ormolu/Printer/Operators.hs view
@@ -90,6 +90,8 @@ -- Users are expected to first construct an initial 'OpTree', then -- re-associate it using this function before printing. reassociateOpTree ::+ -- | Whether to print debug info regarding fixity inference+ Bool -> -- | How to get name of an operator (op -> Maybe RdrName) -> -- | Fixity Map@@ -98,14 +100,16 @@ OpTree ty op -> -- | Re-associated 'OpTree', with added context and info around operators OpTree ty (OpInfo op)-reassociateOpTree getOpName modFixityMap =+reassociateOpTree debug getOpName modFixityMap = reassociateFlatOpTree . makeFlatOpTree- . addFixityInfo modFixityMap getOpName+ . addFixityInfo debug modFixityMap getOpName -- | Wrap every operator of the tree with 'OpInfo' to carry the information -- about its fixity (extracted from the specified fixity map). addFixityInfo ::+ -- | Whether to print debug info regarding fixity inference+ Bool -> -- | Fixity map for operators ModuleFixityMap -> -- | How to get the name of an operator@@ -114,10 +118,10 @@ OpTree ty op -> -- | 'OpTree', with fixity info wrapped around each operator OpTree ty (OpInfo op)-addFixityInfo _ _ (OpNode n) = OpNode n-addFixityInfo modFixityMap getOpName (OpBranches exprs ops) =+addFixityInfo _ _ _ (OpNode n) = OpNode n+addFixityInfo debug modFixityMap getOpName (OpBranches exprs ops) = OpBranches- (addFixityInfo modFixityMap getOpName <$> exprs)+ (addFixityInfo debug modFixityMap getOpName <$> exprs) (toOpInfo <$> ops) where toOpInfo o = OpInfo o mrdrName fixityApproximation@@ -125,7 +129,7 @@ mrdrName = getOpName o fixityApproximation = case mrdrName of Nothing -> defaultFixityApproximation- Just rdrName -> inferFixity rdrName modFixityMap+ Just rdrName -> inferFixity debug rdrName modFixityMap -- | Given a 'OpTree' of any shape, produce a flat 'OpTree', where every -- node and operator is directly connected to the root.
src/Ormolu/Utils.hs view
@@ -147,6 +147,9 @@ instance HasSrcSpan SrcSpan where loc' = id +instance HasSrcSpan RealSrcSpan where+ loc' l = RealSrcSpan l Strict.Nothing+ instance HasSrcSpan (SrcSpanAnn' ann) where loc' = locA
tests/Ormolu/FixitySpec.hs view
@@ -261,7 +261,7 @@ where actualResult = fmap- (\(k, _) -> (k, inferFixity k resultMap))+ (\(k, _) -> (k, inferFixity False k resultMap)) expectedResult resultMap = moduleFixityMap
tests/Ormolu/OpTreeSpec.hs view
@@ -31,7 +31,7 @@ removeOpInfo (OpNode x) = OpNode x removeOpInfo (OpBranches exprs ops) = OpBranches (removeOpInfo <$> exprs) (opiOp <$> ops)- actualOutputTree = reassociateOpTree convertName modFixityMap inputTree+ actualOutputTree = reassociateOpTree False convertName modFixityMap inputTree modFixityMap = ModuleFixityMap (Map.map Given (Map.fromList fixities)) convertName = Just . mkRdrUnqual . mkOccName varName . T.unpack . unOpName