1
1
mirror of https://github.com/google/ormolu.git synced 2024-09-11 08:05:24 +03:00

Deal with non-zero indentation in region formatting

Improved region formatting so that indented fragments can also be processed
correctly.
This commit is contained in:
Mark Karpov 2020-06-16 11:40:26 +02:00
parent c982ba9284
commit 35f4fb3932
13 changed files with 94 additions and 17 deletions

View File

@ -25,6 +25,10 @@
* Fixed the bug when type applications glued to TH splices that followed * Fixed the bug when type applications glued to TH splices that followed
them. [Issue 613](https://github.com/tweag/ormolu/issues/613). 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).
## Ormolu 0.1.0.0 ## Ormolu 0.1.0.0
* Fixed rendering of type signatures concerning several identifiers. [Issue * Fixed rendering of type signatures concerning several identifiers. [Issue

View File

@ -132,17 +132,19 @@ in {
cp src.hs result-all-implicit.hs cp src.hs result-all-implicit.hs
ormolu --check-idempotence --mode inplace result-all-implicit.hs ormolu --check-idempotence --mode inplace result-all-implicit.hs
cp src.hs result-all-explicit.hs cp src.hs result-all-explicit.hs
ormolu --check-idempotence --mode inplace --start-line 1 --end-line 13 result-all-explicit.hs ormolu --check-idempotence --mode inplace --start-line 1 --end-line 18 result-all-explicit.hs
cp src.hs result-only-start.hs cp src.hs result-only-start.hs
ormolu --check-idempotence --mode inplace --start-line 1 result-only-start.hs ormolu --check-idempotence --mode inplace --start-line 1 result-only-start.hs
cp src.hs result-only-end.hs cp src.hs result-only-end.hs
ormolu --check-idempotence --mode inplace --end-line 13 result-only-end.hs ormolu --check-idempotence --mode inplace --end-line 18 result-only-end.hs
cp src.hs result-6-7.hs cp src.hs result-6-7.hs
ormolu --check-idempotence --mode inplace --start-line 6 --end-line 7 result-6-7.hs ormolu --check-idempotence --mode inplace --start-line 6 --end-line 7 result-6-7.hs
cp src.hs result-6-8.hs cp src.hs result-6-8.hs
ormolu --check-idempotence --mode inplace --start-line 6 --end-line 8 result-6-8.hs ormolu --check-idempotence --mode inplace --start-line 6 --end-line 8 result-6-8.hs
cp src.hs result-9-13.hs cp src.hs result-9-12.hs
ormolu --check-idempotence --mode inplace --start-line 9 --end-line 13 result-9-13.hs ormolu --check-idempotence --mode inplace --start-line 9 --end-line 12 result-9-12.hs
cp src.hs result-17-18.hs
ormolu --check-idempotence --mode inplace --start-line 17 --end-line 18 result-17-18.hs
''; '';
checkPhase = '' checkPhase = ''
echo result-all-implicit.hs echo result-all-implicit.hs
@ -157,8 +159,10 @@ in {
diff --color=always expected-result-6-7.hs result-6-7.hs diff --color=always expected-result-6-7.hs result-6-7.hs
echo result-6-8.hs echo result-6-8.hs
diff --color=always expected-result-6-8.hs result-6-8.hs diff --color=always expected-result-6-8.hs result-6-8.hs
echo result-9-13.hs echo result-9-12.hs
diff --color=always expected-result-9-13.hs result-9-13.hs diff --color=always expected-result-9-12.hs result-9-12.hs
echo result-17-18.hs
diff --color=always expected-result-17-18.hs result-17-18.hs
''; '';
installPhase = '' installPhase = ''
mkdir "$out" mkdir "$out"

View File

@ -0,0 +1,17 @@
{-# LANGUAGE LambdaCase #-}
module Foo (
foo, bar, baz) where
foo :: Int
foo = 5
bar :: Int -> Int
bar = \case
0 -> foo
x -> x - foo
baz :: Int -> Int
baz = gege
where
gege = 1 + 2

View File

@ -1,7 +1,7 @@
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
module Foo ( module Foo (
foo, bar) where foo, bar, baz) where
foo :: Int foo :: Int
foo = 5 foo = 5
@ -10,3 +10,8 @@ bar :: Int -> Int
bar = \case bar = \case
0 -> foo 0 -> foo
x -> x - foo x -> x - foo
baz :: Int -> Int
baz = gege
where
gege = 1 + 2

View File

@ -1,7 +1,7 @@
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
module Foo ( module Foo (
foo, bar) where foo, bar, baz) where
foo :: Int foo :: Int
foo = 5 foo = 5
@ -9,3 +9,8 @@ bar :: Int -> Int
bar = \case bar = \case
0 -> foo 0 -> foo
x -> x - foo x -> x - foo
baz :: Int -> Int
baz = gege
where
gege = 1 + 2

View File

@ -1,7 +1,7 @@
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
module Foo ( module Foo (
foo, bar) where foo, bar, baz) where
foo :: Int foo :: Int
foo = 5 foo = 5
@ -10,3 +10,8 @@ bar :: Int -> Int
bar = \case bar = \case
0 -> foo 0 -> foo
x -> x - foo x -> x - foo
baz :: Int -> Int
baz = gege
where
gege = 1 + 2

View File

@ -3,6 +3,7 @@
module Foo module Foo
( foo, ( foo,
bar, bar,
baz,
) )
where where
@ -13,3 +14,8 @@ bar :: Int -> Int
bar = \case bar = \case
0 -> foo 0 -> foo
x -> x - foo x -> x - foo
baz :: Int -> Int
baz = gege
where
gege = 1 + 2

View File

@ -1,7 +1,7 @@
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
module Foo ( module Foo (
foo, bar) where foo, bar, baz) where
foo :: Int foo :: Int
foo = 5 foo = 5
@ -10,3 +10,8 @@ bar :: Int -> Int
bar = \case bar = \case
0 -> foo 0 -> foo
x -> x - foo x -> x - foo
baz :: Int -> Int
baz = gege
where
gege = 1 + 2

View File

@ -32,7 +32,7 @@ import Ormolu.Parser.Anns
import Ormolu.Parser.CommentStream import Ormolu.Parser.CommentStream
import Ormolu.Parser.Result import Ormolu.Parser.Result
import Ormolu.Processing.Preprocess (preprocess) import Ormolu.Processing.Preprocess (preprocess)
import Ormolu.Utils (incSpanLine) import Ormolu.Utils (incSpanLine, removeIndentation)
import qualified Panic as GHC import qualified Panic as GHC
import qualified Parser as GHC import qualified Parser as GHC
import qualified StringBuffer as GHC import qualified StringBuffer as GHC
@ -51,8 +51,9 @@ parseModule ::
Either (SrcSpan, String) ParseResult Either (SrcSpan, String) ParseResult
) )
parseModule Config {..} path rawInput = liftIO $ do parseModule Config {..} path rawInput = liftIO $ do
let (literalPrefix, input, literalSuffix, extraComments) = let (literalPrefix, indentedInput, literalSuffix, extraComments) =
preprocess path rawInput cfgRegion preprocess path rawInput cfgRegion
(input, indent) = removeIndentation indentedInput
-- It's important that 'setDefaultExts' is done before -- It's important that 'setDefaultExts' is done before
-- 'parsePragmasIntoDynFlags', because otherwise we might enable an -- 'parsePragmasIntoDynFlags', because otherwise we might enable an
-- extension that was explicitly disabled in the file. -- extension that was explicitly disabled in the file.
@ -110,7 +111,8 @@ parseModule Config {..} path rawInput = liftIO $ do
prImportQualifiedPost = prImportQualifiedPost =
GHC.xopt ImportQualifiedPost dynFlags, GHC.xopt ImportQualifiedPost dynFlags,
prLiteralPrefix = T.pack literalPrefix, prLiteralPrefix = T.pack literalPrefix,
prLiteralSuffix = T.pack literalSuffix prLiteralSuffix = T.pack literalSuffix,
prIndent = indent
} }
return (warnings, r) return (warnings, r)

View File

@ -35,7 +35,9 @@ data ParseResult = ParseResult
-- | Literal prefix -- | Literal prefix
prLiteralPrefix :: Text, prLiteralPrefix :: Text,
-- | Literal suffix -- | Literal suffix
prLiteralSuffix :: Text prLiteralSuffix :: Text,
-- | Indentation level, can be non-zero in case of region formatting
prIndent :: Int
} }
-- | Pretty-print a 'ParseResult'. -- | Pretty-print a 'ParseResult'.

View File

@ -23,7 +23,7 @@ printModule ParseResult {..} =
prLiteralPrefix <> region <> prLiteralSuffix prLiteralPrefix <> region <> prLiteralSuffix
where where
region = region =
postprocess $ postprocess prIndent $
runR runR
( p_hsModule ( p_hsModule
prStackHeader prStackHeader

View File

@ -1,3 +1,4 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns #-} {-# LANGUAGE ViewPatterns #-}
-- | Postprocessing for the results of printing. -- | Postprocessing for the results of printing.
@ -12,12 +13,19 @@ import Ormolu.Processing.Common
import qualified Ormolu.Processing.Cpp as Cpp import qualified Ormolu.Processing.Cpp as Cpp
-- | Postprocess output of the formatter. -- | Postprocess output of the formatter.
postprocess :: Text -> Text postprocess ::
postprocess = -- | Desired indentation level
Int ->
-- | Input to process
Text ->
Text
postprocess indent =
T.unlines T.unlines
. fmap indentLine
. fmap Cpp.unmaskLine . fmap Cpp.unmaskLine
. filter (not . magicComment) . filter (not . magicComment)
. T.lines . T.lines
where where
magicComment (T.stripStart -> x) = magicComment (T.stripStart -> x) =
x == startDisabling || x == endDisabling x == startDisabling || x == endDisabling
indentLine x = T.replicate indent " " <> x

View File

@ -1,5 +1,6 @@
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns #-}
-- | Random utilities used by the code. -- | Random utilities used by the code.
module Ormolu.Utils module Ormolu.Utils
@ -15,9 +16,11 @@ module Ormolu.Utils
separatedByBlank, separatedByBlank,
separatedByBlankNE, separatedByBlankNE,
onTheSameLine, onTheSameLine,
removeIndentation,
) )
where where
import Data.Char (isSpace)
import Data.List (dropWhileEnd) import Data.List (dropWhileEnd)
import qualified Data.List.NonEmpty as NE import qualified Data.List.NonEmpty as NE
import Data.List.NonEmpty (NonEmpty (..)) import Data.List.NonEmpty (NonEmpty (..))
@ -139,3 +142,14 @@ separatedByBlankNE loc a b = separatedByBlank loc (NE.last a) (NE.head b)
onTheSameLine :: SrcSpan -> SrcSpan -> Bool onTheSameLine :: SrcSpan -> SrcSpan -> Bool
onTheSameLine a b = onTheSameLine a b =
isOneLineSpan (mkSrcSpan (srcSpanEnd a) (srcSpanStart 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)