on dde7560 help sign in
.buildkite/pipeline.yml+2−2
since splitsnapshots
unifiedsplit
@@ -3,9 +3,9 @@ steps:
3 command: |
3 command: |
4 nix-build --keep-going --no-out-link --argstr ormoluCompiler ghc865
4 nix-build --keep-going --no-out-link --argstr ormoluCompiler ghc865
5 timeout: 100
5 timeout: 100
6− - label: Build and test with GHC 8.8.4
6+ - label: Build and test with GHC 8.8.3
7 command: |
7 command: |
8− nix-build --keep-going --no-out-link --argstr ormoluCompiler ghc884
8+ nix-build --keep-going --no-out-link --argstr ormoluCompiler ghc883
9 timeout: 100
9 timeout: 100
10 - label: Build and test with GHC 8.10.1
10 - label: Build and test with GHC 8.10.1
11 command: |
11 command: |
.github/workflows/binaries.ymldeleted−39
@@ -1,39 +0,0 @@
1−name: Build binaries
2−on:
3− release:
4− types: [published]
5−jobs:
6− build:
7− strategy:
8− fail-fast: false
9− matrix:
10− os: [ubuntu-latest, macOS-latest, windows-latest]
11− runs-on: ${{ matrix.os }}
12− steps:
13− - uses: actions/checkout@v2
14− - uses: actions/setup-haskell@v1
15− if: runner.os != 'Linux'
16− with:
17− ghc-version: '8.10.1'
18− cabal-version: '3.2'
19− - name: Build Linux binary
20− if: runner.os == 'Linux'
21− run: |
22− docker run \
23− -v $(pwd):/mnt -w /mnt \
24− utdemir/ghc-musl:v14-ghc8101 \
25− bash .github/workflows/build.sh
26− - name: Build ${{ runner.os }} binary
27− if: runner.os != 'Linux'
28− shell: bash
29− run: |
30− cabal build exe:ormolu
31− cp $(find dist-newstyle \( -name ormolu -o -name ormolu.exe \) -type f) ormolu
32− - uses: actions/upload-release-asset@v1
33− env:
34− GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35− with:
36− upload_url: ${{ github.event.release.upload_url }}
37− asset_path: ormolu
38− asset_name: ormolu-${{ runner.os }}
39− asset_content_type: application/octet-stream
.github/workflows/build.shdeleted−7
@@ -1,7 +0,0 @@
1−set -e
2−
3−cabal update
4−cabal build exe:ormolu --enable-executable-static --ghc-options="-split-sections"
5−
6−cp $(find dist-newstyle -name ormolu -type f) .
7−strip -s ormolu
CHANGELOG.md−107
@@ -1,102 +1,5 @@
1## Unreleased
1## Unreleased
2
2
3−* Ormolu no longer overwrites already formatted files. [PR
4− 649](https://github.com/tweag/ormolu/pull/649).
5−
6−## Ormolu 0.1.2.0
7−
8−* Fixed the bug when comments in different styles got glued together after
9− formatting. [Issue 589](https://github.com/tweag/ormolu/issues/589).
10−
11−* Added `-i` as a shortcut for `--mode inplace`. [Issue
12− 467](https://github.com/tweag/ormolu/issues/467).
13−
14−* Improved grouping of top-level declarations. [Issue
15− 466](https://github.com/tweag/ormolu/issues/466).
16−
17−## Ormolu 0.1.1.0
18−
19−* Imports in a import lists are now normalized: duplicate imports are
20− combined/eliminated intelligently.
21−
22−* Import declarations that can be merged are now automatically merged.
23− [Issue 414](https://github.com/tweag/ormolu/issues/414).
24−
25−* The magic comments for disabling and enabling Ormolu now can encompass any
26− fragment of code provided that the remaining code after exclusion of the
27− disabled part is still syntactically correct. [Issue
28− 601](https://github.com/tweag/ormolu/issues/601).
29−
30−* Improved sorting of operators in imports. [Issue
31− 602](https://github.com/tweag/ormolu/issues/602).
32−
33−* Fixed a bug related to trailing space in multiline comments in certain
34− cases. [Issue 603](https://github.com/tweag/ormolu/issues/602).
35−
36−* Added support for formatting linked lists with `(:)` as line terminator.
37− [Issue 478](https://github.com/tweag/ormolu/issues/478).
38−
39−* Fixed rendering of function arguments in multiline layout. [Issue
40− 609](https://github.com/tweag/ormolu/issues/609).
41−
42−* Blank lines between definitions in `let` and `while` bindings are now
43− preserved. [Issue 554](https://github.com/tweag/ormolu/issues/554).
44−
45−* Fixed the bug when type applications stuck to the `$` of TH splices that
46− followed them. [Issue 613](https://github.com/tweag/ormolu/issues/613).
47−
48−* Improved region formatting so that indented fragments—such as definitions
49− inside of `where` clauses—can be formatted. [Issue
50− 572](https://github.com/tweag/ormolu/issues/572).
51−
52−* Fixed the bug related to the de-association of pragma comments. [Issue
53− 619](https://github.com/tweag/ormolu/issues/619).
54−
55−## Ormolu 0.1.0.0
56−
57−* Fixed rendering of type signatures concerning several identifiers. [Issue
58− 566](https://github.com/tweag/ormolu/issues/566).
59−
60−* Fixed an idempotence issue with inline comments in tuples and parentheses.
61− [Issue 450](https://github.com/tweag/ormolu/issues/450).
62−
63−* Fixed an idempotence issue when certain comments were picked up as
64− “continuation” of a series of comments [Issue
65− 449](https://github.com/tweag/ormolu/issues/449).
66−
67−* Fixed an idempotence issue related to different indentation levels in a
68− comment series. [Issue 512](https://github.com/tweag/ormolu/issues/512).
69−
70−* Fixed an idempotence issue related to comments which may happen to be
71− separated from the elements they are attached to by the equality sign.
72− [Issue 340](https://github.com/tweag/ormolu/issues/340).
73−
74−* Fixed an idempotence issue with type synonym and data declarations where
75− the type has a Haddock. [Issue
76− 578](https://github.com/tweag/ormolu/issues/578).
77−
78−* Fix the false positive about AST differences in presence of comments with
79− multiple blank lines in a row. [Issue
80− 518](https://github.com/tweag/ormolu/issues/518).
81−
82−* Fixed rendering of comments around if expressions. [Issue
83− 458](https://github.com/tweag/ormolu/issues/458).
84−
85−* Unnamed fields of data constructors are now documented using the `-- ^`
86− syntax. [Issue 445](https://github.com/tweag/ormolu/issues/445) and [Issue
87− 428](https://github.com/tweag/ormolu/issues/428).
88−
89−* Fixed non-idempotent transformation of partly documented data definition.
90− [Issue 590](https://github.com/tweag/ormolu/issues/590).
91−
92−* Fixed an idempotence issue related to operators. [Issue
93− 522](https://github.com/tweag/ormolu/issues/522).
94−
95−* Renamed the `--check-idempotency` flag to `--check-idempotence`.
96− Apparently only the latter is correct.
97−
98−## Ormolu 0.0.5.0
99−
100* Grouping of statements in `do`-blocks is now preserved. [Issue
3* Grouping of statements in `do`-blocks is now preserved. [Issue
101 74](https://github.com/tweag/ormolu/issues/74).
4 74](https://github.com/tweag/ormolu/issues/74).
102
5
@@ -109,16 +12,6 @@
109* Ormolu can now be enabled and disabled via special comments. [Issue
12* Ormolu can now be enabled and disabled via special comments. [Issue
110 435](https://github.com/tweag/ormolu/issues/435).
13 435](https://github.com/tweag/ormolu/issues/435).
111
14
112−* Added experimental support for simple CPP. [Issue
113− 415](https://github.com/tweag/ormolu/issues/415).
114−
115−* Added two new options `--start-line` and `--end-line` that allow us to
116− select a region to format. [Issue
117− 516](https://github.com/tweag/ormolu/issues/516).
118−
119−* Fixed rendering of module headers in the presence of preceding comments or
120− Haddocks. [Issue 561](https://github.com/tweag/ormolu/issues/561).
121−
122## Ormolu 0.0.4.0
15## Ormolu 0.0.4.0
123
16
124* When given several files to format, Ormolu does not stop on the first
17* When given several files to format, Ormolu does not stop on the first
CONTRIBUTING.md+1−1
@@ -30,7 +30,7 @@ Testing is performed as following:
30* The result of printing is parsed back again and the AST is compared to the
30* The result of printing is parsed back again and the AST is compared to the
31 AST obtained from the original file. They should match.
31 AST obtained from the original file. They should match.
32* The output of printer is checked against the expected output.
32* The output of printer is checked against the expected output.
33−* Idempotence property is verified: formatting already formatted code
33+* Idempotency property is verified: formatting already formatted code
34 results in exactly the same output.
34 results in exactly the same output.
35
35
36Examples can be organized in sub-directories, see the existing ones for
36Examples can be organized in sub-directories, see the existing ones for
DESIGN.md+11−11
@@ -24,7 +24,7 @@ It also includes recommendations for future implementers.
24
24
25We set for the following goals (mostly taken from
25We set for the following goals (mostly taken from
26[brittany](https://github.com/lspitzner/brittany)):
26[brittany](https://github.com/lspitzner/brittany)):
27−* Preserve the meaning of the formatted functions when no CPP is used;
27+* Preserve the meaning of the formatted functions;
28* Make reasonable use of screen space;
28* Make reasonable use of screen space;
29* Use linear space and computation time on the size of the input;
29* Use linear space and computation time on the size of the input;
30* Preserve comments;
30* Preserve comments;
@@ -140,10 +140,8 @@ impossible to guess what they'll be called on.
140
140
141### CPP
141### CPP
142
142
143−We allow CPP directives in the input, but we forgo the goal to preserve the
143+Formatting a module which uses CPP directives won't be supported. Instead,
144−meaning of the formatted functions in that case.
145−Instead of supporting CPP better, we hope for a solution to replace CPP to
146−do conditional compilation.
144+we hope for a solution to replace CPP to do conditional compilation.
147
145
148There are the following challenges when formatting a module with CPP:
146There are the following challenges when formatting a module with CPP:
149
147
@@ -182,15 +180,14 @@ True
182```
180```
183
181
184At the time of this writing, formatting this program with Hindent
182At the time of this writing, formatting this program with Hindent
185−or Ormolu produces the same output we would get if the CPP directives
183+produces the same output we would get if the CPP directives were
186−were considered comments:
184+considered comments:
187
185
188```
186```
189−$ ormolu --version
187+$ hindent --version
190−ormolu 0.0.5.0 HEAD fc64eada5c4da7a5b07d2872e253671b48aec115
188+hindent 5.2.7
191−using ghc-lib-parser 8.10.1.20200412
192
189
193−$ ormolu --mode inplace test.hs
190+$ hindent test.hs
194
191
195$ cat test.hs
192$ cat test.hs
196{-# LANGUAGE CPP #-}
193{-# LANGUAGE CPP #-}
@@ -230,6 +227,9 @@ to parse Haskell modules. If CPP is replaced with some language
230extension or mechanism to do conditional compilation, all tools
227extension or mechanism to do conditional compilation, all tools
231will benefit from it.
228will benefit from it.
232
229
230+Therefore, CPP won't be supported. If the CPP extension
231+is enabled, we should signal an error right away.
232+
233### Printing
233### Printing
234
234
235Just pretty-printing code (following the approach of Hindent) seems sane. It
235Just pretty-printing code (following the approach of Hindent) seems sane. It
README.md+13−33
@@ -22,7 +22,7 @@ the following goals in mind:
22* That formatting style aims to result in minimal diffs while still
22* That formatting style aims to result in minimal diffs while still
23 remaining very close to “conventional” Haskell formatting people use.
23 remaining very close to “conventional” Haskell formatting people use.
24* Choose a style compatible with modern dialects of Haskell. As new Haskell
24* Choose a style compatible with modern dialects of Haskell. As new Haskell
25− extensions enter broad use, we may change the style to accommodate them.
25+ extensions enter broad use, we may change the style to accomodate them.
26* Idempotence: formatting already formatted code doesn't change it.
26* Idempotence: formatting already formatted code doesn't change it.
27* Be well-tested and robust to the point that it can be used in large
27* Be well-tested and robust to the point that it can be used in large
28 projects without exposing unfortunate, disappointing bugs here and there.
28 projects without exposing unfortunate, disappointing bugs here and there.
@@ -45,12 +45,11 @@ Alternatively, `stack` could be used with a `stack.yaml` file as follows.
45
45
46```console
46```console
47$ cat stack.yaml
47$ cat stack.yaml
48−resolver: lts-16.0
48+resolver: lts-14.3
49packages:
49packages:
50- '.'
50- '.'
51
51
52−$ stack build # to build
52+$ stack build
53−$ stack install # to install
54```
53```
55
54
56To use Ormolu directly from GitHub with Nix, this snippet may come in handy:
55To use Ormolu directly from GitHub with Nix, this snippet may come in handy:
@@ -92,12 +91,6 @@ formatted output.
92$ ormolu --mode inplace Module.hs
91$ ormolu --mode inplace Module.hs
93```
92```
94
93
95−Use `find` to format a tree recursively:
96−
97−```console
98−$ ormolu --mode inplace $(find . -name '*.hs')
99−```
100−
101## Magic comments
94## Magic comments
102
95
103Ormolu understands two magic comments:
96Ormolu understands two magic comments:
@@ -121,15 +114,19 @@ independent top-level definitions.
121
114
122## Current limitations
115## Current limitations
123
116
124−* CPP support is experimental. CPP is virtually impossible to handle
117+* Does not handle CPP (wontfix, see [the design document][design]).
125− correctly, so we process them as a sort of unchangeable snippets. This
126− works only in simple cases when CPP conditionals surround top-level
127− declarations. See the [CPP][design-cpp] section in the design notes for
128− a discussion of the dangers.
129* Input modules should be parsable by Haddock, which is a bit stricter
118* Input modules should be parsable by Haddock, which is a bit stricter
130 criterion than just being valid Haskell modules.
119 criterion than just being valid Haskell modules.
131* Various minor idempotence issues, most of them are related to comments.
120* Various minor idempotence issues, most of them are related to comments.
132
121
122+## Editor integration
123+
124+We know of the following editor integrations:
125+
126+* [Emacs][emacs-package]
127+* [VS Code][vs-code-plugin]
128+* vim: [neoformat][neoformat], [vim-ormolu][vim-ormolu]
129+
133## Running on Hackage
130## Running on Hackage
134
131
135It's possible to try Ormolu on arbitrary packages from Hackage. For that
132It's possible to try Ormolu on arbitrary packages from Hackage. For that
@@ -144,22 +141,6 @@ also contain formatted `.hs` files for inspection and original inputs with
144`.hs-original` extension (those are with CPP dropped, exactly what is fed
141`.hs-original` extension (those are with CPP dropped, exactly what is fed
145into Ormolu).
142into Ormolu).
146
143
147−## Editor integration
148−
149−We know of the following editor integrations:
150−
151−* [Emacs][emacs-package]
152−* [VS Code][vs-code-plugin]
153−* vim: [neoformat][neoformat], [vim-ormolu][vim-ormolu]
154−
155−## Arch Linux
156−
157−To install Ormolu on Arch Linux, one can use [the package on AUR][aur]:
158−
159−```console
160−yay -S ormolu
161−```
162−
163## Contributing
144## Contributing
164
145
165See [CONTRIBUTING.md][contributing].
146See [CONTRIBUTING.md][contributing].
@@ -170,7 +151,7 @@ See [LICENSE.md][license].
170
151
171Copyright © 2018–present Tweag I/O
152Copyright © 2018–present Tweag I/O
172
153
173−[design-cpp]: https://github.com/tweag/ormolu/blob/master/DESIGN.md#cpp
154+[design]: https://github.com/tweag/ormolu/blob/master/DESIGN.md#cpp
174[contributing]: https://github.com/tweag/ormolu/blob/master/CONTRIBUTING.md
155[contributing]: https://github.com/tweag/ormolu/blob/master/CONTRIBUTING.md
175[license]: https://github.com/tweag/ormolu/blob/master/LICENSE.md
156[license]: https://github.com/tweag/ormolu/blob/master/LICENSE.md
176[haskell-src-exts]: https://hackage.haskell.org/package/haskell-src-exts
157[haskell-src-exts]: https://hackage.haskell.org/package/haskell-src-exts
@@ -178,4 +159,3 @@ Copyright © 2018–present Tweag I/O
178[vs-code-plugin]: https://marketplace.visualstudio.com/items?itemName=sjurmillidahl.ormolu-vscode
159[vs-code-plugin]: https://marketplace.visualstudio.com/items?itemName=sjurmillidahl.ormolu-vscode
179[vim-ormolu]: https://github.com/sdiehl/vim-ormolu
160[vim-ormolu]: https://github.com/sdiehl/vim-ormolu
180[neoformat]: https://github.com/sbdchd/neoformat
161[neoformat]: https://github.com/sbdchd/neoformat
181−[aur]: https://aur.archlinux.org/packages/ormolu
app/Main.hs+26−40
@@ -4,11 +4,13 @@
4{-# LANGUAGE TemplateHaskell #-}
4{-# LANGUAGE TemplateHaskell #-}
5{-# LANGUAGE TypeApplications #-}
5{-# LANGUAGE TypeApplications #-}
6
6
7−module Main (main) where
7+module Main
8+ ( main,
9+ )
10+where
8
11
9import Control.Exception (SomeException, displayException, try)
12import Control.Exception (SomeException, displayException, try)
10import Control.Monad
13import Control.Monad
11−import Data.Bool (bool)
12import Data.Either (lefts)
14import Data.Either (lefts)
13import Data.List (intercalate, sort)
15import Data.List (intercalate, sort)
14import qualified Data.Text.IO as TIO
16import qualified Data.Text.IO as TIO
@@ -45,7 +47,7 @@ formatOne ::
45 -- | Mode of operation
47 -- | Mode of operation
46 Mode ->
48 Mode ->
47 -- | Configuration
49 -- | Configuration
48− Config RegionIndices ->
50+ Config ->
49 -- | File to format or stdin as 'Nothing'
51 -- | File to format or stdin as 'Nothing'
50 Maybe FilePath ->
52 Maybe FilePath ->
51 IO ()
53 IO ()
@@ -61,19 +63,15 @@ formatOne mode config = \case
61 -- 101 is different from all the other exit codes we already use.
63 -- 101 is different from all the other exit codes we already use.
62 exitWith (ExitFailure 101)
64 exitWith (ExitFailure 101)
63 Just inputFile -> do
65 Just inputFile -> do
64− originalInput <- TIO.readFile inputFile
65− formattedInput <- ormoluFile config inputFile
66+ r <- ormoluFile config inputFile
66 case mode of
67 case mode of
67 Stdout ->
68 Stdout ->
68− TIO.putStr formattedInput
69+ TIO.putStr r
69− InPlace -> do
70+ InPlace ->
70− -- Only write when the contents have changed, in order to avoid
71− -- updating the modified timestamp if the file was already correctly
72− -- formatted.
73− when (formattedInput /= originalInput) $
74− TIO.writeFile inputFile formattedInput
71+ TIO.writeFile inputFile r
75 Check -> do
72 Check -> do
76− when (formattedInput /= originalInput) $
73+ r' <- TIO.readFile inputFile
74+ when (r /= r') $
77 -- 100 is different to all the other exit code that are emitted
75 -- 100 is different to all the other exit code that are emitted
78 -- either from an 'OrmoluException' or from 'error' and
76 -- either from an 'OrmoluException' or from 'error' and
79 -- 'notImplemented'.
77 -- 'notImplemented'.
@@ -86,7 +84,7 @@ data Opts = Opts
86 { -- | Mode of operation
84 { -- | Mode of operation
87 optMode :: !Mode,
85 optMode :: !Mode,
88 -- | Ormolu 'Config'
86 -- | Ormolu 'Config'
89− optConfig :: !(Config RegionIndices),
87+ optConfig :: !Config,
90 -- | Haskell source files to format or stdin (when the list is empty)
88 -- | Haskell source files to format or stdin (when the list is empty)
91 optInputFiles :: ![FilePath]
89 optInputFiles :: ![FilePath]
92 }
90 }
@@ -139,25 +137,20 @@ optsParserInfo =
139optsParser :: Parser Opts
137optsParser :: Parser Opts
140optsParser =
138optsParser =
141 Opts
139 Opts
142− <$> ( (fmap (bool Stdout InPlace) . switch . mconcat)
143− [ short 'i',
144− help "A shortcut for --mode inplace"
145− ]
146− <|> (option parseMode . mconcat)
140+ <$> (option parseMode . mconcat)
147− [ long "mode",
141+ [ long "mode",
148− short 'm',
142+ short 'm',
149− metavar "MODE",
143+ metavar "MODE",
150− value Stdout,
144+ value Stdout,
151− help "Mode of operation: 'stdout' (default), 'inplace', or 'check'"
145+ help "Mode of operation: 'stdout' (default), 'inplace', or 'check'"
152− ]
146+ ]
153− )
154 <*> configParser
147 <*> configParser
155 <*> (many . strArgument . mconcat)
148 <*> (many . strArgument . mconcat)
156 [ metavar "FILE",
149 [ metavar "FILE",
157 help "Haskell source files to format or stdin (default)"
150 help "Haskell source files to format or stdin (default)"
158 ]
151 ]
159
152
160−configParser :: Parser (Config RegionIndices)
153+configParser :: Parser Config
161configParser =
154configParser =
162 Config
155 Config
163 <$> (fmap (fmap DynOption) . many . strOption . mconcat)
156 <$> (fmap (fmap DynOption) . many . strOption . mconcat)
@@ -177,22 +170,15 @@ configParser =
177 help "Output information useful for debugging"
170 help "Output information useful for debugging"
178 ]
171 ]
179 <*> (switch . mconcat)
172 <*> (switch . mconcat)
180− [ long "check-idempotence",
173+ [ long "tolerate-cpp",
174+ short 'p',
175+ help "Do not fail if CPP pragma is present"
176+ ]
177+ <*> (switch . mconcat)
178+ [ long "check-idempotency",
181 short 'c',
179 short 'c',
182 help "Fail if formatting is not idempotent"
180 help "Fail if formatting is not idempotent"
183 ]
181 ]
184− <*> ( RegionIndices
185− <$> (optional . option auto . mconcat)
186− [ long "start-line",
187− metavar "START",
188− help "Start line of the region to format (starts from 1)"
189− ]
190− <*> (optional . option auto . mconcat)
191− [ long "end-line",
192− metavar "END",
193− help "End line of the region to format (inclusive)"
194− ]
195− )
196
182
197----------------------------------------------------------------------------
183----------------------------------------------------------------------------
198-- Helpers
184-- Helpers
data/examples/declaration/annotation/annotation-out.hs−1
@@ -18,5 +18,4 @@ foo = 5
18
18
19data Foo = Foo Int
19data Foo = Foo Int
20{-# ANN type Foo ("HLint: ignore") #-}
20{-# ANN type Foo ("HLint: ignore") #-}
21−
22{- Comment -}
21{- Comment -}
data/examples/declaration/data/gadt/multiline-out.hs+1−1
@@ -8,7 +8,7 @@ data Foo a where
8 Foo ::
8 Foo ::
9 forall a b.
9 forall a b.
10 (Show a, Eq b) => -- foo
10 (Show a, Eq b) => -- foo
11− -- bar
11+ -- bar
12 a ->
12 a ->
13 b ->
13 b ->
14 Foo 'Int
14 Foo 'Int
data/examples/declaration/data/multiline-arg-parens-out.hs+1−1
@@ -5,6 +5,6 @@ data Foo
5 = Foo
5 = Foo
6 Bar
6 Bar
7 (Set Baz) -- and here we go
7 (Set Baz) -- and here we go
8− -- and that's it
8+ -- and that's it
9 Text
9 Text
10 deriving (Eq)
10 deriving (Eq)
data/examples/declaration/data/partly-documented-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−data Optimisation
2− = PETransform
3− | -- | partial eval and associated transforms
4− GeneralisedNatHack
5− deriving (Show, Eq, Generic)
data/examples/declaration/data/partly-documented.hsdeleted−2
@@ -1,2 +0,0 @@
1−data Optimisation = PETransform | GeneralisedNatHack -- ^ partial eval and associated transforms
2− deriving (Show, Eq, Generic)
data/examples/declaration/data/unnamed-field-comment-0-out.hsdeleted−7
@@ -1,7 +0,0 @@
1−data Foo
2− = -- | Bar
3− Bar
4− Field1
5− -- ^ Field 1
6− Field2
7− -- ^ Field 2
data/examples/declaration/data/unnamed-field-comment-0.hsdeleted−5
@@ -1,5 +0,0 @@
1−data Foo
2− = -- | Bar
3− Bar
4− Field1 -- ^ Field 1
5− Field2 -- ^ Field 2
data/examples/declaration/data/unnamed-field-comment-1-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−data X
2− = B
3− !Int
4− -- ^ y
5− C
data/examples/declaration/data/unnamed-field-comment-1.hsdeleted−4
@@ -1,4 +0,0 @@
1−data X
2− = B
3− !Int -- ^ y
4− C
data/examples/declaration/data/with-comment-out.hsdeleted−4
@@ -1,4 +0,0 @@
1−data A
2− = B -- C
3− | -- D
4− E
data/examples/declaration/data/with-comment.hsdeleted−5
@@ -1,5 +0,0 @@
1−data A =
2− B -- C
3−
4− -- D
5− | E
data/examples/declaration/data/with-weird-haddock-out.hsdeleted−4
@@ -1,4 +0,0 @@
1−data PlusLevel' t
2− = -- | @n + ℓ@.
3− Plus Integer (LevelAtom' t)
4− deriving (Show, Data)
data/examples/declaration/data/with-weird-haddock.hsdeleted−2
@@ -1,2 +0,0 @@
1−data PlusLevel' t = Plus Integer (LevelAtom' t) -- ^ @n + ℓ@.
2− deriving (Show, Data)
data/examples/declaration/signature/type/infix-promoted-type-constructor-out.hs+1
@@ -1,2 +1,3 @@
1fun1 :: Def ('[Ref s (Stored Uint32), IBool] 'T.:-> IBool)
1fun1 :: Def ('[Ref s (Stored Uint32), IBool] 'T.:-> IBool)
2+
2fun2 :: Def ('[Ref s (Stored Uint32), IBool] ':-> IBool)
3fun2 :: Def ('[Ref s (Stored Uint32), IBool] ':-> IBool)
data/examples/declaration/signature/type/multi-value-out.hs−5
@@ -2,11 +2,6 @@ foo, bar :: Int
2foo = 1
2foo = 1
3bar = 2
3bar = 2
4
4
5−a, b, c :: Int
6−a = 1
7−b = 2
8−c = 3
9−
10foo,
5foo,
11 bar,
6 bar,
12 baz ::
7 baz ::
data/examples/declaration/signature/type/multi-value.hs−5
@@ -2,11 +2,6 @@ foo, bar :: Int
2foo = 1
2foo = 1
3bar = 2
3bar = 2
4
4
5−a, b, c :: Int
6−a = 1
7−b = 2
8−c = 3
9−
10foo,
5foo,
11 bar,
6 bar,
12 baz :: Int
7 baz :: Int
data/examples/declaration/signature/type/unrelated-out.hsdeleted−4
@@ -1,4 +0,0 @@
1−clientFunc1 :: SomeType1
2−clientFunc2 :: SomeType2
3−clientFunc3 :: SomeType3
4−clientFunc1 :<|> clientFunc2 :<|> clientFunc3 = hoistClient foo bar baz
data/examples/declaration/signature/type/unrelated.hsdeleted−4
@@ -1,4 +0,0 @@
1−clientFunc1 :: SomeType1
2−clientFunc2 :: SomeType2
3−clientFunc3 :: SomeType3
4−clientFunc1 :<|> clientFunc2 :<|> clientFunc3 = hoistClient foo bar baz
data/examples/declaration/type-synonyms/with-weird-haddock-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−type Elims =
2− -- | eliminations ordered left-to-right.
3− [Elim]
data/examples/declaration/type-synonyms/with-weird-haddock.hsdeleted−1
@@ -1 +0,0 @@
1−type Elims = [Elim] -- ^ eliminations ordered left-to-right.
data/examples/declaration/value/function/arg-breakpoints-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−foo
2− bar =
3− body
data/examples/declaration/value/function/arg-breakpoints.hsdeleted−3
@@ -1,3 +0,0 @@
1−foo
2− bar =
3− body
data/examples/declaration/value/function/arrow/proc-do-complex-out.hs+1−1
@@ -40,7 +40,7 @@ foo
40 )
40 )
41 else do
41 else do
42 let u = x -- Let bindings bind expressions, not commands
42 let u = x -- Let bindings bind expressions, not commands
43− -- Could pattern match directly on x
43+ -- Could pattern match directly on x
44 i <- case u of
44 i <- case u of
45 0 -> (g . h -< u)
45 0 -> (g . h -< u)
46 n ->
46 n ->
data/examples/declaration/value/function/awkward-comment-0-out.hsdeleted−6
@@ -1,6 +0,0 @@
1−mergeErrorReply :: ParseError -> Reply s u a -> Reply s u a
2−mergeErrorReply err1 reply -- XXX where to put it?
3− =
4− case reply of
5− Ok x state err2 -> Ok x state (mergeError err1 err2)
6− Error err2 -> Error (mergeError err1 err2)
data/examples/declaration/value/function/awkward-comment-0.hsdeleted−5
@@ -1,5 +0,0 @@
1−mergeErrorReply :: ParseError -> Reply s u a -> Reply s u a
2−mergeErrorReply err1 reply -- XXX where to put it?
3− = case reply of
4− Ok x state err2 -> Ok x state (mergeError err1 err2)
5− Error err2 -> Error (mergeError err1 err2)
data/examples/declaration/value/function/awkward-comment-1-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−doForeign :: Vars -> [Name] -> [Term] -> Idris LExp
2−doForeign x = x
3− where
4− splitArg tm | (_, [_, _, l, r]) <- unApply tm -- pair, two implicits
5− =
6− do
7− let l' = toFDesc l
8− r' <- irTerm (sMN 0 "__foreignCall") vs env r
9− return (l', r')
data/examples/declaration/value/function/awkward-comment-1.hsdeleted−7
@@ -1,7 +0,0 @@
1−doForeign :: Vars -> [Name] -> [Term] -> Idris LExp
2−doForeign x = x
3− where
4− splitArg tm | (_, [_,_,l,r]) <- unApply tm -- pair, two implicits
5− = do let l' = toFDesc l
6− r' <- irTerm (sMN 0 "__foreignCall") vs env r
7− return (l', r')
data/examples/declaration/value/function/blank-lines-let-out.hsdeleted−6
@@ -1,6 +0,0 @@
1−foo =
2− let x = 10
3−
4− y = 11
5− z = 12
6− in x + y + z
data/examples/declaration/value/function/blank-lines-let.hsdeleted−9
@@ -1,9 +0,0 @@
1−foo =
2− let
3−
4− x = 10
5−
6− y = 11
7− z = 12
8−
9− in x + y + z
data/examples/declaration/value/function/blank-lines-where-out.hsdeleted−6
@@ -1,6 +0,0 @@
1−foo = x + y + z
2− where
3− x = 10
4−
5− y = 11
6− z = 12
data/examples/declaration/value/function/blank-lines-where.hsdeleted−7
@@ -1,7 +0,0 @@
1−foo = x + y + z
2− where
3−
4− x = 10
5−
6− y = 11
7− z = 12
data/examples/declaration/value/function/if-with-comment-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−foo =
2− if undefined
3− then -- then comment
4− undefined
5− else -- else comment
6−
7− do
8− undefined
data/examples/declaration/value/function/if-with-comment.hsdeleted−8
@@ -1,8 +0,0 @@
1−foo =
2− if undefined
3− -- then comment
4− then undefined
5− -- else comment
6− else
7− do
8− undefined
data/examples/declaration/value/function/implicit-params-out.hs−1
@@ -1,7 +1,6 @@
1{-# LANGUAGE ImplicitParams #-}
1{-# LANGUAGE ImplicitParams #-}
2
2
3sortBy :: (a -> a -> Bool) -> [a] -> [a]
3sortBy :: (a -> a -> Bool) -> [a] -> [a]
4−sortBy = undefined
5
4
6sort :: (?cmp :: a -> a -> Bool) => [a] -> [a]
5sort :: (?cmp :: a -> a -> Bool) => [a] -> [a]
7sort = sortBy ?cmp
6sort = sortBy ?cmp
data/examples/declaration/value/function/implicit-params.hs−2
@@ -1,8 +1,6 @@
1{-# LANGUAGE ImplicitParams #-}
1{-# LANGUAGE ImplicitParams #-}
2sortBy :: (a -> a -> Bool) -> [a] -> [a]
2sortBy :: (a -> a -> Bool) -> [a] -> [a]
3
3
4−sortBy = undefined
5−
6sort :: (?cmp :: a -> a -> Bool) => [a] -> [a]
4sort :: (?cmp :: a -> a -> Bool) => [a] -> [a]
7sort = sortBy ?cmp
5sort = sortBy ?cmp
8
6
data/examples/declaration/value/function/infix/dollar-chains-out.hs+3−3
@@ -13,9 +13,9 @@ foo =
13 throwIO (OrmoluCppEnabled path)
13 throwIO (OrmoluCppEnabled path)
14
14
15foo =
15foo =
16− bar $
16+ bar
17− baz $
17+ $ baz
18− quux
18+ $ quux
19
19
20x =
20x =
21 case l of { A -> B } $
21 case l of { A -> B } $
data/examples/declaration/value/function/infix/hanging-out.hs+3−4
@@ -17,7 +17,6 @@ update =
17 `catch` \case
17 `catch` \case
18 a -> a
18 a -> a
19
19
20−foo =
20+foo = bar
21− bar
22− ++ case foo of
21+ ++ case foo of
23− a -> a
22+ a -> a
data/examples/declaration/value/function/infix/lenses-out.hs+7−8
@@ -1,12 +1,11 @@
1lenses =
1lenses =
2− Just $
3− M.fromList $
2+ Just $ M.fromList $
4− "type" .= ("user.connection" :: Text)
3+ "type" .= ("user.connection" :: Text)
5− # "connection" .= uc
4+ # "connection" .= uc
6− # "user" .= case name of
5+ # "user" .= case name of
7− Just n -> Just $ object ["name" .= n]
6+ Just n -> Just $ object ["name" .= n]
8− Nothing -> Nothing
7+ Nothing -> Nothing
9− # []
8+ # []
10
9
11foo =
10foo =
12 a
11 a
data/examples/declaration/value/function/list-notation-0-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−foo =
2− testCase "Foo" testFoo :
3− testCase "Bar" testBar :
4− testCase "Baz" testBaz :
5− []
data/examples/declaration/value/function/list-notation-0.hsdeleted−5
@@ -1,5 +0,0 @@
1−foo =
2− testCase "Foo" testFoo :
3− testCase "Bar" testBar :
4− testCase "Baz" testBaz :
5− []
data/examples/declaration/value/function/list-notation-1-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−instance A.ToJSON UpdateTable where
2− toJSON a =
3− A.object $
4− "TableName" .= updateTableName a :
5− "ProvisionedThroughput" .= updateProvisionedThroughput a :
6− case updateGlobalSecondaryIndexUpdates a of
7− [] -> []
8− l -> ["GlobalSecondaryIndexUpdates" .= l]
data/examples/declaration/value/function/list-notation-1.hsdeleted−7
@@ -1,7 +0,0 @@
1−instance A.ToJSON UpdateTable where
2− toJSON a = A.object
3− $ "TableName" .= updateTableName a
4− : "ProvisionedThroughput" .= updateProvisionedThroughput a
5− : case updateGlobalSecondaryIndexUpdates a of
6− [] -> []
7− l -> [ "GlobalSecondaryIndexUpdates" .= l ]
data/examples/declaration/value/function/list-notation-2-out.hsdeleted−6
@@ -1,6 +0,0 @@
1−-- A list of the element and all its parents up to the root node.
2−getPath tree t =
3− t :
4− case Map.lookup (getId t) tree of
5− Nothing -> []
6− Just parent -> getPath tree parent
data/examples/declaration/value/function/list-notation-2.hsdeleted−5
@@ -1,5 +0,0 @@
1−-- A list of the element and all its parents up to the root node.
2−getPath tree t = t :
3− case Map.lookup (getId t) tree of
4− Nothing -> []
5− Just parent -> getPath tree parent
data/examples/declaration/value/function/list-notation-3-out.hsdeleted−12
@@ -1,12 +0,0 @@
1−foo =
2− reportSDoc "tc.cc" 30 $
3− sep $ do
4− (prettyTCM q <+> " before compilation") : do
5− map (prettyTCM . map unArg . clPats) cls
6−
7−foo =
8− reportSDoc "tc.cc" 30 $
9− sep $ do
10− (prettyTCM q <+> " before compilation") :
11− do
12− map (prettyTCM . map unArg . clPats) cls
data/examples/declaration/value/function/list-notation-3.hsdeleted−10
@@ -1,10 +0,0 @@
1−foo =
2− reportSDoc "tc.cc" 30 $ sep $ do
3− (prettyTCM q <+> " before compilation") : do
4− map (prettyTCM . map unArg . clPats) cls
5−
6−foo =
7− reportSDoc "tc.cc" 30 $ sep $ do
8− (prettyTCM q <+> " before compilation") :
9− do
10− map (prettyTCM . map unArg . clPats) cls
data/examples/declaration/value/function/multi-way-if-out.hs+2−4
@@ -3,14 +3,12 @@
3foo x = if | x == 5 -> 5
3foo x = if | x == 5 -> 5
4
4
5bar x y =
5bar x y =
6− if
7− | x > y -> x
6+ if | x > y -> x
8 | x < y ->
7 | x < y ->
9 y
8 y
10 | otherwise -> x
9 | otherwise -> x
11
10
12baz =
11baz =
13− if
12+ if | p -> f
14− | p -> f
15 | otherwise -> g
13 | otherwise -> g
16 x
14 x
data/examples/declaration/value/function/operator-comments-2-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−x =
2− y
3− ++ f g -- commentA
4− -- commentB
5− -- commentC
data/examples/declaration/value/function/operator-comments-2.hsdeleted−4
@@ -1,4 +0,0 @@
1−x =
2− y ++ -- commentA
3−-- commentB
4− f g -- commentC
data/examples/declaration/value/function/operators-1-out.hsdeleted−4
@@ -1,4 +0,0 @@
1−foo =
2− f
3− . g
4− =<< h . i
data/examples/declaration/value/function/operators-1.hsdeleted−3
@@ -1,3 +0,0 @@
1−foo = f
2− . g
3− =<< h . i
data/examples/declaration/value/function/operators-2-out.hsdeleted−4
@@ -1,4 +0,0 @@
1−foo n
2− | x || y && z || n ** x
3− || x && n =
4− 42
data/examples/declaration/value/function/operators-2.hsdeleted−4
@@ -1,4 +0,0 @@
1−foo n
2− | x || y && z || n ** x
3− || x && n =
4− 42
data/examples/declaration/value/function/operators-3-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−foo =
2− op <> n <+> colon <+> prettySe <+> text "="
3− <+> prettySe <> text sc
data/examples/declaration/value/function/operators-3.hsdeleted−3
@@ -1,3 +0,0 @@
1−foo =
2− op <> n <+> colon <+> prettySe <+> text "=" <+>
3− prettySe <> text sc
data/examples/declaration/value/function/operators-4-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−foo =
2− line <> bindingOf <+> text "=" <+> tPretty <+> colon
3− <+> align <> prettyPs
data/examples/declaration/value/function/operators-4.hsdeleted−3
@@ -1,3 +0,0 @@
1−foo =
2− line <> bindingOf <+> text "=" <+> tPretty <+> colon <+>
3− align <> prettyPs
data/examples/declaration/value/function/operators-5-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−foo =
2− map bar $
3− [ baz
4− ]
5− ++ quux
data/examples/declaration/value/function/operators-5.hsdeleted−4
@@ -1,4 +0,0 @@
1−foo =
2− map bar $
3− [ baz
4− ] ++ quux
data/examples/declaration/value/function/operators-6-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−type PermuteRef =
2− "a"
3− :> ( "b" :> "c" :> End
4− :<|> "c" :> "b" :> End
5− )
6− :<|> "b"
7− :> ( "a" :> "c" :> End
8− :<|> "c" :> "a" :> End
9− )
data/examples/declaration/value/function/operators-6.hsdeleted−7
@@ -1,7 +0,0 @@
1−type PermuteRef =
2− "a" :> ( "b" :> "c" :> End
3− :<|> "c" :> "b" :> End
4− )
5− :<|> "b" :> ( "a" :> "c" :> End
6− :<|> "c" :> "a" :> End
7− )
data/examples/declaration/value/function/operators-0-out.hs → data/examples/declaration/value/function/operators-out.hsrenamed

The content is the same.

data/examples/declaration/value/function/operators-0.hs → data/examples/declaration/value/function/operators.hsrenamed

The content is the same.

data/examples/declaration/value/function/record/constructors-out.hs → data/examples/declaration/value/function/record-constructors-out.hsrenamed

The content is the same.

data/examples/declaration/value/function/record/constructors.hs → data/examples/declaration/value/function/record-constructors.hsrenamed

The content is the same.

data/examples/declaration/value/function/record/dot-out.hs → data/examples/declaration/value/function/record-dot-out.hsrenamed

The content is the same.

data/examples/declaration/value/function/record/dot.hs → data/examples/declaration/value/function/record-dot.hsrenamed

The content is the same.

data/examples/declaration/value/function/record/inter-comments-out.hs → data/examples/declaration/value/function/record-inter-comments-out.hsrenamed

The content is the same.

data/examples/declaration/value/function/record/inter-comments.hs → data/examples/declaration/value/function/record-inter-comments.hsrenamed

The content is the same.

data/examples/declaration/value/function/record/updaters-out.hs → data/examples/declaration/value/function/record-updaters-out.hsrenamed

The content is the same.

data/examples/declaration/value/function/record/updaters.hs → data/examples/declaration/value/function/record-updaters.hsrenamed

The content is the same.

data/examples/declaration/value/function/record/wildcards-out.hs → data/examples/declaration/value/function/record-wildcards-out.hsrenamed

The content is the same.

data/examples/declaration/value/function/record/wildcards.hs → data/examples/declaration/value/function/record-wildcards.hsrenamed

The content is the same.

data/examples/declaration/value/function/record/hanging-after-equal-con-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−foo =
2− Foo
3− { foo =
4− -- Blah blah
5− case x of
6− Blah -> 1
7− Blim -> 2
8− }
data/examples/declaration/value/function/record/hanging-after-equal-con.hsdeleted−7
@@ -1,7 +0,0 @@
1−foo = Foo
2− { foo =
3− -- Blah blah
4− case x of
5− Blah -> 1
6− Blim -> 2
7− }
data/examples/declaration/value/function/record/hanging-after-equal-update-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−foo =
2− foo
3− { foo =
4− -- Blah blah
5− case x of
6− Blah -> 1
7− Blim -> 2
8− }
data/examples/declaration/value/function/record/hanging-after-equal-update.hsdeleted−7
@@ -1,7 +0,0 @@
1−foo = foo
2− { foo =
3− -- Blah blah
4− case x of
5− Blah -> 1
6− Blim -> 2
7− }
data/examples/declaration/value/function/type-applications-and-splice-out.hsdeleted−4
@@ -1,4 +0,0 @@
1−{-# LANGUAGE TemplateHaskell #-}
2−{-# LANGUAGE TypeApplications #-}
3−
4−staticKey name = [|sing @ $(symFQN name)|]
data/examples/declaration/value/function/type-applications-and-splice.hsdeleted−4
@@ -1,4 +0,0 @@
1−{-# LANGUAGE TemplateHaskell #-}
2−{-# LANGUAGE TypeApplications #-}
3−
4−staticKey name = [| sing @ $(symFQN name) |]
data/examples/import/deduplication-bug-out.hsdeleted−6
@@ -1,6 +0,0 @@
1−import Foo1 (Bar1 (..), Baz1)
2−import Foo2 (Bar2 (..), Baz2)
3−import Foo3 (Bar3 (x1, x2, x3))
4−import Foo4 (Bar4 (x1, x2))
5−import Foo5 (Bar5 (x1))
6−import Foo6 (Bar6 (..))
data/examples/import/deduplication-bug.hsdeleted−6
@@ -1,6 +0,0 @@
1−import Foo1 (Bar1, Baz1, Bar1(..))
2−import Foo2 (Bar2(..), Baz2, Bar2)
3−import Foo3 (Bar3(x1,x3), Bar3(x1, x2))
4−import Foo4 (Bar4(x1), Bar4(x2))
5−import Foo5 (Bar5, Bar5(x1))
6−import Foo6 (Bar6(x1), Bar6(..))
data/examples/import/explicit-imports-out.hs+4−4
@@ -1,12 +1,12 @@
1import qualified MegaModule as M
1import qualified MegaModule as M
2+ ( (<<<),
3+ (>>>),
2− ( Either,
4+ Either,
3 Maybe (Just, Nothing),
5 Maybe (Just, Nothing),
4 MaybeT (..),
6 MaybeT (..),
5− Monad (return, (>>), (>>=)),
7+ Monad ((>>), (>>=), return),
6 MonadBaseControl,
8 MonadBaseControl,
7 join,
9 join,
8 liftIO,
10 liftIO,
9 void,
11 void,
10− (<<<),
11− (>>>),
12 )
12 )
data/examples/import/explicit-imports-with-comments-out.hs+2−3
@@ -1,7 +1,6 @@
1import qualified MegaModule as M
1import qualified MegaModule as M
2 ( -- (1)
2 ( -- (1)
3− -- (2)
4− Either, -- (3)
5− (<<<),
3+ (<<<), -- (2)
6 (>>>),
4 (>>>),
5+ Either, -- (3)
7 )
6 )
data/examples/import/merging-0-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−import Foo
2−import Foo (bar, foo)
3−import Foo as F
data/examples/import/merging-0.hsdeleted−4
@@ -1,4 +0,0 @@
1−import Foo
2−import Foo (foo)
3−import Foo (bar)
4−import Foo as F
data/examples/import/merging-1-out.hsdeleted−2
@@ -1,2 +0,0 @@
1−import "bar" Foo (bar)
2−import "foo" Foo (baz, foo)
data/examples/import/merging-1.hsdeleted−3
@@ -1,3 +0,0 @@
1−import "foo" Foo (foo)
2−import "bar" Foo (bar)
3−import "foo" Foo (baz)
data/examples/import/merging-2-out.hsdeleted−2
@@ -1,2 +0,0 @@
1−import Foo hiding (bar4, foo2)
2−import qualified Foo (bar3, foo1)
data/examples/import/merging-2.hsdeleted−4
@@ -1,4 +0,0 @@
1−import qualified Foo (foo1)
2−import Foo hiding (foo2)
3−import qualified Foo (bar3)
4−import Foo hiding (bar4)
data/examples/import/misc-out.hs+6
@@ -1,5 +1,11 @@
1import A hiding
1import A hiding
2 ( foobarbazqux,
2 ( foobarbazqux,
3+ foobarbazqux,
4+ foobarbazqux,
5+ foobarbazqux,
6+ foobarbazqux,
7+ foobarbazqux,
8+ foobarbazqux,
3 )
9 )
4import {-# SOURCE #-} safe qualified Module as M hiding (a, b, c, d, e, f)
10import {-# SOURCE #-} safe qualified Module as M hiding (a, b, c, d, e, f)
5import Name hiding ()
11import Name hiding ()
data/examples/import/nested-explicit-imports-out.hs+6−6
@@ -1,10 +1,10 @@
1import qualified MegaModule as M
1import qualified MegaModule as M
2+ ( (<<<),
3+ (>>>),
2− ( Either,
4+ Either,
3 Monad
5 Monad
4− ( return,
5− (>>),
6+ ( (>>),
6− (>>=)
7+ (>>=),
8+ return
7 ),
9 ),
8− (<<<),
9− (>>>),
10 )
10 )
data/examples/import/qualified-post-out.hs+1−1
@@ -1,5 +1,5 @@
1{-# LANGUAGE ImportQualifiedPost #-}
1{-# LANGUAGE ImportQualifiedPost #-}
2
2
3+import Data.Text qualified as T
3import Data.Text qualified (a, b, c)
4import Data.Text qualified (a, b, c)
4import Data.Text qualified hiding (a, b, c)
5import Data.Text qualified hiding (a, b, c)
5−import Data.Text qualified as T
data/examples/import/qualified-prelude-out.hs+1−1
@@ -1,4 +1,4 @@
1module P where
1module P where
2
2
3−import Prelude hiding (id, (.))
4import qualified Prelude
3import qualified Prelude
4+import Prelude hiding ((.), id)
data/examples/import/simple-out.hs+3−2
@@ -1,5 +1,6 @@
1import Data.Text
1import Data.Text
2+import Data.Text
3+import qualified Data.Text as T
4+import qualified Data.Text (a, b, c)
2import Data.Text (a, b, c)
5import Data.Text (a, b, c)
3import Data.Text hiding (a, b, c)
6import Data.Text hiding (a, b, c)
4−import qualified Data.Text (a, b, c)
5−import qualified Data.Text as T
data/examples/import/simple.hs−2
@@ -4,5 +4,3 @@ import qualified Data.Text as T
4import qualified Data.Text (a, c, b)
4import qualified Data.Text (a, c, b)
5import Data.Text (a, b, c)
5import Data.Text (a, b, c)
6import Data.Text hiding (c, b, a)
6import Data.Text hiding (c, b, a)
7−import Data.Text (a, b, c, b, a)
8−import Data.Text hiding (c, b, a, b, c)
data/examples/import/sorted-export-list-out.hsdeleted−1
@@ -1 +0,0 @@
1−import Linear.Vector (Additive (..), (*^), (^*))
data/examples/import/sorted-export-list.hsdeleted−1
@@ -1 +0,0 @@
1−import Linear.Vector (Additive (..), (*^), (^*))
data/examples/module-header/double-dot-with-names-out.hs+6−1
@@ -1,6 +1,11 @@
1{-# LANGUAGE PatternSynonyms #-}
1{-# LANGUAGE PatternSynonyms #-}
2
2
3−module ExportSyntax (A (.., NoA), Q (F, ..), G (T, .., U)) where
3+module ExportSyntax
4+ ( A (.., NoA),
5+ Q (F, ..),
6+ G (T, .., U),
7+ )
8+where
4
9
5data A = A | B
10data A = A | B
6
11
data/examples/module-header/multiline2.hs+2−2
@@ -1,2 +1,2 @@
1−module Foo (
1+module Foo
2− foo, bar, baz) where
2+ (foo, bar, baz) where
data/examples/module-header/preceding-comment-with-haddock-out.hs+4−1
@@ -3,6 +3,9 @@
3-}
3-}
4
4
5-- | This is the module's Haddock.
5-- | This is the module's Haddock.
6−module Main (main) where
6+module Main
7+ ( main,
8+ )
9+where
7
10
8main = return ()
11main = return ()
data/examples/module-header/singleline-empty-out.hs+4−1
@@ -1,2 +1,5 @@
1-- | This demonstrates a BUG.
1-- | This demonstrates a BUG.
2−module Foo () where
2+module Foo
3+ (
4+ )
5+where
data/examples/module-header/stack-header-0-out.hs−1
@@ -3,5 +3,4 @@
3{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE OverloadedStrings #-}
4
4
5main = return ()
5main = return ()
6−
7-- stack runhaskell
6-- stack runhaskell
data/examples/module-header/stack-header-1-out.hs−1
@@ -4,5 +4,4 @@
4{-# LANGUAGE OverloadedStrings #-}
4{-# LANGUAGE OverloadedStrings #-}
5
5
6main = return ()
6main = return ()
7−
8-- stack runhaskell
7-- stack runhaskell
data/examples/module-header/warning-pragma-multiline-out.hs+4−1
@@ -1,6 +1,9 @@
1module Test
1module Test
2 {-# DEPRECATED "This module is unstable" #-}
2 {-# DEPRECATED "This module is unstable" #-}
3− (foo, bar, baz)
3+ ( foo,
4+ bar,
5+ baz,
6+ )
4where
7where
5
8
6import Blah
9import Blah
data/examples/module-header/warning-pragma-out.hs+1−3
@@ -1,5 +1,3 @@
1module Test
1module Test
2− {-# WARNING
3− "This module is very internal"
2+ {-# WARNING "This module is very internal" #-}
4− #-}
5where
3where
data/examples/other/argument-comment-out.hs+1
@@ -9,6 +9,7 @@ foo ::
9 -- | Foo
9 -- | Foo
10 Int ->
10 Int ->
11 Int
11 Int
12+
12foo ::
13foo ::
13 Foo a =>
14 Foo a =>
14 -- | Foo
15 -- | Foo
data/examples/other/comment-glued-together-out.hsdeleted−7
@@ -1,7 +0,0 @@
1−module Main (main) where
2−
3−-- | Foo.
4−
5−-- Bar
6−main :: IO ()
7−main = return ()
data/examples/other/comment-glued-together.hsdeleted−6
@@ -1,6 +0,0 @@
1−module Main (main) where
2−
3−{- | Foo. -}
4−-- Bar
5−main :: IO ()
6−main = return ()
data/examples/other/comment-trailing-space-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−data T
2− = {-
3−
4− some multi-line comment
5−
6− with empty lines
7−
8− -}
9− A
data/examples/other/comment-trailing-space.hsdeleted−9
@@ -1,9 +0,0 @@
1−data T
2− = {-
3−
4− some multi-line comment
5−
6− with empty lines
7−
8− -}
9− A
data/examples/other/comment-two-blocks-out.hs+2−2
@@ -2,7 +2,7 @@ newNames :: [(String, String)]
2newNames =
2newNames =
3 let (*) = flip (,)
3 let (*) = flip (,)
4 in [ "Control" * "Monad"
4 in [ "Control" * "Monad"
5− -- Foo
5+ -- Foo
6
6
7− -- Bar
7+ -- Bar
8 ]
8 ]
data/examples/other/cpp/continuation-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−foo :: Int
2−foo = 5
3−
4−#define message_for(a, b) \
5− printf(#a " and " #b ": We love you!\n")
6−
7−bar :: Int
8−bar = 6
data/examples/other/cpp/continuation.hsdeleted−8
@@ -1,8 +0,0 @@
1−foo :: Int
2−foo = 5
3−
4−#define message_for(a, b) \
5− printf(#a " and " #b ": We love you!\n")
6−
7−bar :: Int
8−bar = 6
data/examples/other/cpp/lonely-hash-out.hsdeleted−14
@@ -1,14 +0,0 @@
1−module Main (main) where
2−
3−import Data.Void
4−import Test.Hspec
5−import Test.Hspec.Megaparsec
6−import Text.Megaparsec
7−import Text.Megaparsec.Char
8−
9−# if !MIN_VERSION_base(4,13,0)
10−import Data.Semigroup ((<>))
11−# endif
12−
13−main :: IO ()
14−main = return ()
data/examples/other/cpp/lonely-hash.hsdeleted−14
@@ -1,14 +0,0 @@
1−module Main (main) where
2−
3−import Data.Void
4−import Test.Hspec
5−import Test.Hspec.Megaparsec
6−import Text.Megaparsec
7−import Text.Megaparsec.Char
8−
9−# if !MIN_VERSION_base(4,13,0)
10−import Data.Semigroup ((<>))
11−# endif
12−
13−main :: IO ()
14−main = return ()
data/examples/other/cpp/separation-0a-out.hsdeleted−7
@@ -1,7 +0,0 @@
1−instance Stream s => Monad (ParsecT e s m) where
2− return = pure
3− (>>=) = pBind
4−
5−#if !(MIN_VERSION_base(4,13,0))
6− fail = Fail.fail
7−#endif
data/examples/other/cpp/separation-0a.hsdeleted−6
@@ -1,6 +0,0 @@
1−instance Stream s => Monad (ParsecT e s m) where
2− return = pure
3− (>>=) = pBind
4−#if !(MIN_VERSION_base(4,13,0))
5− fail = Fail.fail
6−#endif
data/examples/other/cpp/separation-0b-out.hsdeleted−10
@@ -1,10 +0,0 @@
1−instance Stream s => Monad (ParsecT e s m) where
2− return = pure
3− (>>=) = pBind
4−
5−#if !(MIN_VERSION_base(4,13,0))
6− fail = Fail.fail
7−#endif
8−
9−foo :: Int
10−foo = undefined
data/examples/other/cpp/separation-0b.hsdeleted−9
@@ -1,9 +0,0 @@
1−instance Stream s => Monad (ParsecT e s m) where
2− return = pure
3− (>>=) = pBind
4−#if !(MIN_VERSION_base(4,13,0))
5− fail = Fail.fail
6−#endif
7−
8−foo :: Int
9−foo = undefined
data/examples/other/cpp/separation-1a-out.hsdeleted−12
@@ -1,12 +0,0 @@
1−decompressingPipe ::
2− (PrimMonad m, MonadThrow m, MonadResource m) =>
3− CompressionMethod ->
4− ConduitT ByteString ByteString m ()
5−decompressingPipe Store = C.awaitForever C.yield
6−decompressingPipe Deflate = Z.decompress $ Z.WindowBits (-15)
7−
8−#ifdef ENABLE_BZIP2
9−decompressingPipe BZip2 = BZ.bunzip2
10−#else
11−decompressingPipe BZip2 = throwM BZip2Unsupported
12−#endif
data/examples/other/cpp/separation-1a.hsdeleted−11
@@ -1,11 +0,0 @@
1−decompressingPipe
2− :: (PrimMonad m, MonadThrow m, MonadResource m)
3− => CompressionMethod
4− -> ConduitT ByteString ByteString m ()
5−decompressingPipe Store = C.awaitForever C.yield
6−decompressingPipe Deflate = Z.decompress $ Z.WindowBits (-15)
7−#ifdef ENABLE_BZIP2
8−decompressingPipe BZip2 = BZ.bunzip2
9−#else
10−decompressingPipe BZip2 = throwM BZip2Unsupported
11−#endif
data/examples/other/cpp/separation-1b-out.hsdeleted−15
@@ -1,15 +0,0 @@
1−decompressingPipe ::
2− (PrimMonad m, MonadThrow m, MonadResource m) =>
3− CompressionMethod ->
4− ConduitT ByteString ByteString m ()
5−decompressingPipe Store = C.awaitForever C.yield
6−decompressingPipe Deflate = Z.decompress $ Z.WindowBits (-15)
7−
8−#ifdef ENABLE_BZIP2
9−decompressingPipe BZip2 = BZ.bunzip2
10−#else
11−decompressingPipe BZip2 = throwM BZip2Unsupported
12−#endif
13−
14−foo :: Int
15−foo = undefined
data/examples/other/cpp/separation-1b.hsdeleted−14
@@ -1,14 +0,0 @@
1−decompressingPipe
2− :: (PrimMonad m, MonadThrow m, MonadResource m)
3− => CompressionMethod
4− -> ConduitT ByteString ByteString m ()
5−decompressingPipe Store = C.awaitForever C.yield
6−decompressingPipe Deflate = Z.decompress $ Z.WindowBits (-15)
7−#ifdef ENABLE_BZIP2
8−decompressingPipe BZip2 = BZ.bunzip2
9−#else
10−decompressingPipe BZip2 = throwM BZip2Unsupported
11−#endif
12−
13−foo :: Int
14−foo = undefined
data/examples/other/cpp/separation-2a-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−ffff, ffffffff :: Natural
2−
3−#ifdef HASKELL_ZIP_DEV_MODE
4−ffff = 200
5−ffffffff = 5000
6−#else
7−ffff = 0xffff
8−ffffffff = 0xffffffff
9−#endif
data/examples/other/cpp/separation-2a.hsdeleted−8
@@ -1,8 +0,0 @@
1−ffff, ffffffff :: Natural
2−#ifdef HASKELL_ZIP_DEV_MODE
3−ffff = 200
4−ffffffff = 5000
5−#else
6−ffff = 0xffff
7−ffffffff = 0xffffffff
8−#endif
data/examples/other/cpp/separation-2b-out.hsdeleted−11
@@ -1,11 +0,0 @@
1−ffff, ffffffff :: Natural
2−#ifdef HASKELL_ZIP_DEV_MODE
3−ffff = 200
4−ffffffff = 5000
5−#else
6−ffff = 0xffff
7−ffffffff = 0xffffffff
8−#endif
9−
10−foo :: Int
11−foo = undefined
data/examples/other/cpp/separation-2b.hsdeleted−11
@@ -1,11 +0,0 @@
1−ffff, ffffffff :: Natural
2−#ifdef HASKELL_ZIP_DEV_MODE
3−ffff = 200
4−ffffffff = 5000
5−#else
6−ffff = 0xffff
7−ffffffff = 0xffffffff
8−#endif
9−
10−foo :: Int
11−foo = undefined
data/examples/other/cpp/shifted-out.hsdeleted−21
@@ -1,21 +0,0 @@
1−sinkData h compression = do
2− (uncompressedSize, crc32, compressedSize) <-
3− case compression of
4− Store ->
5− withCompression
6− dataSink
7− Deflate ->
8− withCompression $
9− Z.compress 9 (Z.WindowBits (-15)) .| dataSink
10−#ifdef ENABLE_BZIP2
11− BZip2 -> withCompression $
12− BZ.bzip2 .| dataSink
13−#else
14− BZip2 -> throwM BZip2Unsupported
15−#endif
16− return
17− DataDescriptor
18− { ddCRC32 = fromIntegral crc32,
19− ddCompressedSize = compressedSize,
20− ddUncompressedSize = uncompressedSize
21− }
data/examples/other/cpp/shifted.hsdeleted−17
@@ -1,17 +0,0 @@
1−sinkData h compression = do
2− (uncompressedSize, crc32, compressedSize) <-
3− case compression of
4− Store -> withCompression
5− dataSink
6− Deflate -> withCompression $
7− Z.compress 9 (Z.WindowBits (-15)) .| dataSink
8−#ifdef ENABLE_BZIP2
9− BZip2 -> withCompression $
10− BZ.bzip2 .| dataSink
11−#else
12− BZip2 -> throwM BZip2Unsupported
13−#endif
14− return DataDescriptor
15− { ddCRC32 = fromIntegral crc32
16− , ddCompressedSize = compressedSize
17− , ddUncompressedSize = uncompressedSize }
data/examples/other/cpp/simple-import-out.hsdeleted−14
@@ -1,14 +0,0 @@
1−module Main (main) where
2−
3−import Data.Void
4−import Test.Hspec
5−import Test.Hspec.Megaparsec
6−import Text.Megaparsec
7−import Text.Megaparsec.Char
8−
9−#if !MIN_VERSION_base(4,13,0)
10−import Data.Semigroup ((<>))
11−#endif
12−
13−main :: IO ()
14−main = return ()
data/examples/other/cpp/simple-import.hsdeleted−14
@@ -1,14 +0,0 @@
1−module Main (main) where
2−
3−import Data.Void
4−import Test.Hspec
5−import Test.Hspec.Megaparsec
6−import Text.Megaparsec
7−import Text.Megaparsec.Char
8−
9−#if !MIN_VERSION_base(4,13,0)
10−import Data.Semigroup ((<>))
11−#endif
12−
13−main :: IO ()
14−main = return ()
data/examples/other/disabling/indented-fragment-out.hsdeleted−7
@@ -1,7 +0,0 @@
1−foo =
2− {- ORMOLU_DISABLE -}
3− testCase "Foo" testFoo :
4− testCase "Bar" testBar :
5− testCase "Baz" testBaz :
6− {- ORMOLU_ENABLE -}
7− []
data/examples/other/disabling/indented-fragment.hsdeleted−7
@@ -1,7 +0,0 @@
1−foo =
2− {- ORMOLU_DISABLE -}
3− testCase "Foo" testFoo :
4− testCase "Bar" testBar :
5− testCase "Baz" testBaz :
6− {- ORMOLU_ENABLE -}
7− []
data/examples/other/inline-comment-0-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−x = ({-a-} b, c)
2−
3−y = ({-a-} b)
data/examples/other/inline-comment-0.hsdeleted−3
@@ -1,3 +0,0 @@
1−x = ({-a-}b, c)
2−
3−y = ({-a-}b)
data/examples/other/inline-comment-1-out.hsdeleted−12
@@ -1,12 +0,0 @@
1−showPs env ((n, _, Let _ t v) : bs) =
2− " " ++ show n ++ " : "
3− ++ showEnv env ({- normalise ctxt env -} t)
4− ++ " = "
5− ++ showEnv env ({- normalise ctxt env -} v)
6− ++ "\n"
7− ++ showPs env bs
8−showPs env ((n, _, b) : bs) =
9− " " ++ show n ++ " : "
10− ++ showEnv env ({- normalise ctxt env -} (binderTy b))
11− ++ "\n"
12− ++ showPs env bs
data/examples/other/inline-comment-1.hsdeleted−9
@@ -1,9 +0,0 @@
1−showPs env ((n, _, Let _ t v):bs)
2− = " " ++ show n ++ " : " ++
3− showEnv env ({- normalise ctxt env -} t) ++ " = " ++
4− showEnv env ({- normalise ctxt env -} v) ++
5− "\n" ++ showPs env bs
6−showPs env ((n, _, b):bs)
7− = " " ++ show n ++ " : " ++
8− showEnv env ({- normalise ctxt env -} (binderTy b)) ++
9− "\n" ++ showPs env bs
data/examples/other/multiple-blank-line-comment-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−module A where
2−
3−a =
4− b
5− [ f
6− {-,
7−
8− -}
9− ]
data/examples/other/multiple-blank-line-comment.hsdeleted−10
@@ -1,10 +0,0 @@
1−module A where
2−
3−a =
4− b
5− [ f
6− {-,
7−
8−
9− -}
10− ]
data/examples/other/pragma-comments-after-out.hsdeleted−4
@@ -1,4 +0,0 @@
1−{-# LANGUAGE AllowAmbiguousTypes #-}
2−{-# LANGUAGE ConstraintKinds #-}
3−-- TODO: Fix and delete this pragma
4−{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
data/examples/other/pragma-comments-after.hsdeleted−3
@@ -1,3 +0,0 @@
1−{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} -- TODO: Fix and delete this pragma
2−{-# LANGUAGE AllowAmbiguousTypes #-}
3−{-# LANGUAGE ConstraintKinds #-}
data/examples/other/pragma-comments-out.hs+4−1
@@ -5,4 +5,7 @@
5{-# OPTIONS_GHC -fno-warn-overlapping-patterns #-}
5{-# OPTIONS_GHC -fno-warn-overlapping-patterns #-}
6
6
7-- | Header comment.
7-- | Header comment.
8−module Foo () where
8+module Foo
9+ (
10+ )
11+where
data/examples/other/pragma-out.hs+4−1
@@ -9,4 +9,7 @@
9{-# OPTIONS_HADDOCK prune, show-extensions #-}
9{-# OPTIONS_HADDOCK prune, show-extensions #-}
10
10
11-- | Header comment.
11-- | Header comment.
12−module Foo () where
12+module Foo
13+ (
14+ )
15+where
default.nix+25−69
@@ -1,6 +1,5 @@
1−{ pkgs ? (import ./nix/nixpkgs { inherit system; })
1+{ pkgs ? (import ./nix/nixpkgs)
2−, system ? builtins.currentSystem
3−, ormoluCompiler ? "ghc884" # the shell doesn't work with ghc8101 yet
2+, ormoluCompiler ? "ghc883" # the shell doesn't work with ghc8101 yet
4}:
3}:
5
4
6let
5let
@@ -17,6 +16,12 @@ let
17 };
16 };
18 ormoluOverlay = self: super: {
17 ormoluOverlay = self: super: {
19 "ormolu" = super.callCabal2nixWithOptions "ormolu" source "-fdev" { };
18 "ormolu" = super.callCabal2nixWithOptions "ormolu" source "-fdev" { };
19+ "ghc-lib-parser" = pkgs.haskell.lib.dontHaddock
20+ (super.callHackageDirect {
21+ pkg = "ghc-lib-parser";
22+ ver = "8.10.1.20200412";
23+ sha256 = "sha256-EjMzp8xRT3xVFKDI1fAfopkylGB0hv35Av2+uZeETRU=";
24+ } {});
20 };
25 };
21 ormolize = import ./nix/ormolize {
26 ormolize = import ./nix/ormolize {
22 inherit pkgs;
27 inherit pkgs;
@@ -25,19 +30,19 @@ let
25 expectedFailures = [
30 expectedFailures = [
26 "Agda"
31 "Agda"
27 "aws"
32 "aws"
33+ "brick"
28 "distributed-process"
34 "distributed-process"
29 "esqueleto"
35 "esqueleto"
30 "fay"
36 "fay"
31− "hlint"
32 "idris"
37 "idris"
33 "intero"
38 "intero"
34 "leksah"
39 "leksah"
40+ "lens"
35 "pandoc"
41 "pandoc"
36 "pipes"
42 "pipes"
37− "postgrest"
38 "purescript"
43 "purescript"
39− "tensorflow"
44+ "stack"
40− ] ++ (if ormoluCompiler == "ghc8101" then [] else ["lens"]);
45+ ];
41 ormolizedPackages = doCheck:
46 ormolizedPackages = doCheck:
42 pkgs.lib.mapAttrs (name: p: ormolize {
47 pkgs.lib.mapAttrs (name: p: ormolize {
43 package = p;
48 package = p;
@@ -49,11 +54,14 @@ let
49 }) haskellPackages;
54 }) haskellPackages;
50in {
55in {
51 ormolu = haskellPackages.ormolu;
56 ormolu = haskellPackages.ormolu;
52− # We put the derivations in another attribute set to avoid building them
57+ ormoluShell =
53− # when nix-build is run.
58+ if ormoluCompiler == "ghc8101"
54− dev = {
59+ # HACK The shell doesn't compile with GHC 8.10.1
55− ormoluShell =
60+ then haskellPackages.shellFor {
61+ packages = ps: [];
62+ buildInputs = [];
63+ }
56− haskellPackages.shellFor {
64+ else haskellPackages.shellFor {
57 packages = ps: [
65 packages = ps: [
58 ps.ormolu
66 ps.ormolu
59 ];
67 ];
@@ -62,13 +70,11 @@ in {
62 haskellPackages.ghcid
70 haskellPackages.ghcid
63 ];
71 ];
64 };
72 };
65− withOrmolu = haskellPackages.shellFor {
73+ withOrmolu = haskellPackages.shellFor {
66− packages = ps: [];
74+ packages = ps: [];
67− buildInputs = [
75+ buildInputs = [
68− haskellPackages.cabal-install
69− haskellPackages.ormolu
76+ haskellPackages.ormolu
70− ];
77+ ];
71− };
72 };
78 };
73 inherit ormoluOverlay ormoluCompiler;
79 inherit ormoluOverlay ormoluCompiler;
74 hackage = ormolizedPackages false;
80 hackage = ormolizedPackages false;
@@ -103,7 +109,6 @@ in {
103 "optics"
109 "optics"
104 "ormolu"
110 "ormolu"
105 "pandoc"
111 "pandoc"
106− "parsec3"
107 "pipes"
112 "pipes"
108 "postgrest"
113 "postgrest"
109 "purescript"
114 "purescript"
@@ -117,53 +122,4 @@ in {
117 ];
122 ];
118 in listToAttrs (map (p: nameValuePair p (ormolizedPackages true).${p}) ps)
123 in listToAttrs (map (p: nameValuePair p (ormolizedPackages true).${p}) ps)
119 );
124 );
120− regionTests = pkgs.stdenv.mkDerivation {
121− name = "ormolu-region-tests";
122− src = ./region-tests;
123− buildInputs = [
124− haskellPackages.ormolu
125− pkgs.diffutils
126− ];
127− doCheck = true;
128− buildPhase = ''
129− cp src.hs result-all-implicit.hs
130− ormolu --check-idempotence --mode inplace result-all-implicit.hs
131− cp src.hs result-all-explicit.hs
132− ormolu --check-idempotence --mode inplace --start-line 1 --end-line 18 result-all-explicit.hs
133− cp src.hs result-only-start.hs
134− ormolu --check-idempotence --mode inplace --start-line 1 result-only-start.hs
135− cp src.hs result-only-end.hs
136− ormolu --check-idempotence --mode inplace --end-line 18 result-only-end.hs
137− cp src.hs result-6-7.hs
138− ormolu --check-idempotence --mode inplace --start-line 6 --end-line 7 result-6-7.hs
139− cp src.hs result-6-8.hs
140− ormolu --check-idempotence --mode inplace --start-line 6 --end-line 8 result-6-8.hs
141− cp src.hs result-9-12.hs
142− ormolu --check-idempotence --mode inplace --start-line 9 --end-line 12 result-9-12.hs
143− cp src.hs result-17-18.hs
144− ormolu --check-idempotence --mode inplace --start-line 17 --end-line 18 result-17-18.hs
145− '';
146− checkPhase = ''
147− echo result-all-implicit.hs
148− diff --color=always expected-result-all.hs result-all-implicit.hs
149− echo result-all-explicit.hs
150− diff --color=always expected-result-all.hs result-all-explicit.hs
151− echo result-only-start.hs
152− diff --color=always expected-result-all.hs result-only-start.hs
153− echo result-only-end.hs
154− diff --color=always expected-result-all.hs result-only-end.hs
155− echo result-6-7.hs
156− diff --color=always expected-result-6-7.hs result-6-7.hs
157− echo result-6-8.hs
158− diff --color=always expected-result-6-8.hs result-6-8.hs
159− echo result-9-12.hs
160− diff --color=always expected-result-9-12.hs result-9-12.hs
161− echo result-17-18.hs
162− diff --color=always expected-result-17-18.hs result-17-18.hs
163− '';
164− installPhase = ''
165− mkdir "$out"
166− find . -name '*.hs' -exec cp --parents {} $out \;
167− '';
168− };
169}
125}
expected-failures/Agda.txt+29−6
@@ -1,11 +1,34 @@
1Formatting is not idempotent:
1Formatting is not idempotent:
2− dist/build/Agda/Syntax/Parser/Lexer.hs<rendered>:1602:17
2+ src/full/Agda/Auto/CaseSplit.hs<rendered>:176:54
3− before: " = (check_ac"
3+ before: ", pats') = applyperm"
4− after: " =\n "
4+ after: ", pats') =\n "
5Please, consider reporting the bug.
5Please, consider reporting the bug.
6
6
7Formatting is not idempotent:
7Formatting is not idempotent:
8− src/full/Agda/Syntax/Translation/InternalToAbstract.hs<rendered>:769:4
8+ src/full/Agda/Syntax/Internal.hs<rendered>:236:12
9+ before: "pe Elims = -- | elim"
10+ after: "pe Elims =\n -- | el"
11+Please, consider reporting the bug.
12+
13+Parsing of formatted code failed:
14+ src/full/Agda/Syntax/Translation/ConcreteToAbstract.hs<rendered>:524:7-13
15+ parse error on input `C.QName'
16+Please, consider reporting the bug.
17+
18+Formatting is not idempotent:
19+ src/full/Agda/Termination/CallGraph.hs<rendered>:152:38
9− before: " nes\n\n "
20+ before: "2, old2) = -- TODO: "
10− after: " nes\n\n -- Andreas"
21+ after: "2, old2) =\n -"
22+Please, consider reporting the bug.
23+
24+Formatting is not idempotent:
25+ src/full/Agda/TypeChecking/MetaVars.hs<rendered>:1448:16
26+ before: "ubstCand = -- | a po"
27+ after: "ubstCand =\n -- | a "
28+Please, consider reporting the bug.
29+
30+Formatting is not idempotent:
31+ src/full/Agda/Utils/List.hs<rendered>:186:15
32+ before: "Prefix a = -- | The "
33+ after: "Prefix a =\n -- | Th"
11Please, consider reporting the bug.
34Please, consider reporting the bug.
expected-failures/brick.txtnew file+5
@@ -0,0 +1,5 @@
1+Formatting is not idempotent:
2+ src/Brick/Widgets/List.hs<rendered>:573:3
3+ before: "t at i\n in -- If t"
4+ after: "t at i\n -"
5+Please, consider reporting the bug.
expected-failures/esqueleto.txt+1−1
@@ -3,5 +3,5 @@ The GHC parser (in Haddock mode) failed:
3 lexical error in string/character literal at character 's'
3 lexical error in string/character literal at character 's'
4
4
5The GHC parser (in Haddock mode) failed:
5The GHC parser (in Haddock mode) failed:
6− test/PostgreSQL/Test.hs:562:9-41
6+ test/PostgreSQL/Test.hs:510:9-41
7 parse error on input `-- | Check the result is not null'
7 parse error on input `-- | Check the result is not null'
expected-failures/hlint.txtdeleted−11
@@ -1,11 +0,0 @@
1−Formatting is not idempotent:
2− src/Extension.hs<rendered>:19:22
3− before: "DoRec , -} Recursive"
4− after: "DoRec , -}\n "
5−Please, consider reporting the bug.
6−
7−Formatting is not idempotent:
8− src/Hint/Bracket.hs<rendered>:249:50
9− before: "\" x y [r]) {ideaSpan"
10− after: "\" x y [r])\n "
11−Please, consider reporting the bug.
expected-failures/idris.txt+94
@@ -1,7 +1,101 @@
1+Formatting is not idempotent:
2+ src/Idris/AbsSyntaxTree.hs<rendered>:2105:48
3+ before: "t_impl ppo && uname "
4+ after: "t_impl ppo\n "
5+Please, consider reporting the bug.
6+
7+Formatting is not idempotent:
8+ src/Idris/Core/ProofState.hs<rendered>:163:20
9+ before: "++ showEnv env (\n "
10+ after: "++ showEnv\n "
11+Please, consider reporting the bug.
12+
13+Formatting is not idempotent:
14+ src/Idris/Core/ProofTerm.hs<rendered>:351:19
15+ before: "f c e pt = -- @(PT p"
16+ after: "f c e pt =\n -- @(PT"
17+Please, consider reporting the bug.
18+
19+Formatting is not idempotent:
20+ src/Idris/Core/TT.hs<rendered>:1963:13
21+ before: " text op <> pretty"
22+ after: " text op\n <"
23+Please, consider reporting the bug.
24+
25+Formatting is not idempotent:
26+ src/Idris/Core/WHNF.hs<rendered>:110:46
27+ before: " n b sc) = -- stk mu"
28+ after: " n b sc) =\n -- "
29+Please, consider reporting the bug.
30+
31+Formatting is not idempotent:
32+ src/Idris/Delaborate.hs<rendered>:627:6
33+ before: "ity\n -- Issue #"
34+ after: "ity\n -- Issue"
35+Please, consider reporting the bug.
36+
37+Formatting is not idempotent:
38+ src/Idris/Elab/Term.hs<rendered>:432:47
39+ before: "K\" _ _)) = -- for ch"
40+ after: "K\" _ _)) =\n -- "
41+Please, consider reporting the bug.
42+
43+Formatting is not idempotent:
44+ src/Idris/ModeCommon.hs<rendered>:40:26
45+ before: "s toline = -- furthe"
46+ after: "s toline =\n -- furt"
47+Please, consider reporting the bug.
48+
49+Formatting is not idempotent:
50+ src/Idris/Options.hs<rendered>:177:17
51+ before: "timisation = PETrans"
52+ after: "timisation\n = PETra"
53+Please, consider reporting the bug.
54+
1The GHC parser (in Haddock mode) failed:
55The GHC parser (in Haddock mode) failed:
2 src/Idris/Parser.hs:1052:1
56 src/Idris/Parser.hs:1052:1
3 parse error on input `@'
57 parse error on input `@'
4
58
59+AST of input and AST of formatted code differ.
60+ at src/Idris/Parser/Data.hs:281:1-29
61+Please, consider reporting the bug.
62+
5The GHC parser (in Haddock mode) failed:
63The GHC parser (in Haddock mode) failed:
6 src/Idris/Parser/Expr.hs:75:1
64 src/Idris/Parser/Expr.hs:75:1
7 parse error on input `@'
65 parse error on input `@'
66+
67+Formatting is not idempotent:
68+ src/Idris/PartialEval.hs<rendered>:281:42
69+ before: ": ns) as = -- Droppe"
70+ after: ": ns) as =\n -- "
71+Please, consider reporting the bug.
72+
73+Formatting is not idempotent:
74+ src/Idris/ProofSearch.hs<rendered>:487:20
75+ before: "OK ty hs = -- if any"
76+ after: "OK ty hs =\n -- "
77+Please, consider reporting the bug.
78+
79+Formatting is not idempotent:
80+ src/Idris/Prover.hs<rendered>:244:10
81+ before: " line <> bindin"
82+ after: " line\n <"
83+Please, consider reporting the bug.
84+
85+Formatting is not idempotent:
86+ src/Idris/REPL.hs<rendered>:1270:33
87+ before: "ht c) _) = -- consta"
88+ after: "ht c) _) =\n -- cons"
89+Please, consider reporting the bug.
90+
91+Formatting is not idempotent:
92+ src/Idris/Reflection.hs<rendered>:934:27
93+ before: "attern _ = -- for al"
94+ after: "attern _ =\n -- for "
95+Please, consider reporting the bug.
96+
97+Formatting is not idempotent:
98+ src/Idris/Transforms.hs<rendered>:26:32
99+ before: "s, rhs)) = -- apply "
100+ after: "s, rhs)) =\n -- "
101+Please, consider reporting the bug.
expected-failures/intero.txt+3−3
@@ -1,5 +1,5 @@
1Formatting is not idempotent:
1Formatting is not idempotent:
2− src/InteractiveUI.hs<rendered>:3748:33
2+ src/InteractiveUI.hs<rendered>:2635:36
3− before: "text \"Try\" <+> doWha"
3+ before: "Decl d2) = -- A bit "
4− after: "text \"Try\"\n "
4+ after: "Decl d2) =\n -- A bi"
5Please, consider reporting the bug.
5Please, consider reporting the bug.
expected-failures/leksah.txt+7−1
@@ -1,5 +1,11 @@
1Formatting is not idempotent:
1Formatting is not idempotent:
2− src/IDE/Pane/Modules.hs<rendered>:1184:7
2+ src/IDE/Pane/Modules.hs<rendered>:1188:7
3 before: "cr\n -- show"
3 before: "cr\n -- show"
4 after: "cr\n in -- show"
4 after: "cr\n in -- show"
5Please, consider reporting the bug.
5Please, consider reporting the bug.
6+
7+Formatting is not idempotent:
8+ src/IDE/SymbolNavigation.hs<rendered>:233:8
9+ before: "\n\n return [\n {-i"
10+ after: "\n\n return\n [ {-i"
11+Please, consider reporting the bug.
expected-failures/pandoc.txt+7−1
@@ -3,7 +3,13 @@ The GHC parser (in Haddock mode) failed:
3 parse error on input `import'
3 parse error on input `import'
4
4
5Formatting is not idempotent:
5Formatting is not idempotent:
6− src/Text/Pandoc/Readers/Vimwiki.hs<rendered>:613:19
6+ src/Text/Pandoc/Readers/Vimwiki.hs<rendered>:615:19
7 before: ".softbreak <$ endlin"
7 before: ".softbreak <$ endlin"
8 after: ".softbreak\n <$ en"
8 after: ".softbreak\n <$ en"
9Please, consider reporting the bug.
9Please, consider reporting the bug.
10+
11+Formatting is not idempotent:
12+ src/Text/Pandoc/Writers/Docx.hs<rendered>:997:25
13+ before: " -- w:p\n "
14+ after: " -- w:p\n "
15+Please, consider reporting the bug.
expected-failures/postgrest.txtdeleted−5
@@ -1,5 +0,0 @@
1−Formatting is not idempotent:
2− src/PostgREST/DbRequestBuilder.hs<rendered>:149:24
3− before: " || -- clients"
4− after: " || ( origin ="
5−Please, consider reporting the bug.
expected-failures/purescript.txt+2−2
@@ -1,10 +1,10 @@
1The GHC parser (in Haddock mode) failed:
1The GHC parser (in Haddock mode) failed:
2− src/Language/PureScript/AST/Declarations.hs:479:1-17
2+ src/Language/PureScript/AST/Declarations.hs:478:1-17
3 Invalid type signature: pattern ValueDecl :: ...
3 Invalid type signature: pattern ValueDecl :: ...
4Perhaps you meant to use PatternSynonyms?
4Perhaps you meant to use PatternSynonyms?
5
5
6The GHC parser (in Haddock mode) failed:
6The GHC parser (in Haddock mode) failed:
7− src/Language/PureScript/AST/SourcePos.hs:99:1-22
7+ src/Language/PureScript/AST/SourcePos.hs:101:1-22
8 Invalid type signature: pattern NullSourceSpan :: ...
8 Invalid type signature: pattern NullSourceSpan :: ...
9Perhaps you meant to use PatternSynonyms?
9Perhaps you meant to use PatternSynonyms?
10
10
expected-failures/stack.txtnew file+5
@@ -0,0 +1,5 @@
1+Formatting is not idempotent:
2+ src/Stack/Options/DockerParser.hs<rendered>:36:10
3+ before: " <$> opti"
4+ after: " <$> option"
5+Please, consider reporting the bug.
expected-failures/tensorflow.txtdeleted−7
@@ -1,7 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− tensorflow-mnist/app/Main.hs:50:13-14
3− parse error on input `->'
4−
5−The GHC parser (in Haddock mode) failed:
6− tensorflow-ops/tests/RegressionTest.hs:3:1-6
7− parse error on input `import'
format.sh+4−6
@@ -1,5 +1,5 @@
1#!/usr/bin/env nix-shell
1#!/usr/bin/env nix-shell
2−#!nix-shell default.nix -A dev.withOrmolu -i bash --pure
2+#!nix-shell default.nix -A withOrmolu -i bash --pure
3#
3#
4# Format Ormolu using current version of Ormolu.
4# Format Ormolu using current version of Ormolu.
5
5
@@ -7,8 +7,6 @@ set -e
7
7
8export LANG="C.UTF-8"
8export LANG="C.UTF-8"
9
9
10−cabal format
11−
12−ormolu -m inplace $(find app -type f -name "*.hs")
10+ormolu -p -m inplace $(find app -type f -name "*.hs")
13−ormolu -m inplace $(find src -type f \( -name "*.hs" -o -name "*.hs-boot" \))
11+ormolu -p -m inplace $(find src -type f \( -name "*.hs" -o -name "*.hs-boot" \))
14−ormolu -m inplace $(find tests -type f -name "*.hs")
12+ormolu -p -m inplace $(find tests -type f -name "*.hs")
nix/nixpkgs/default.nix+3−7
@@ -1,13 +1,9 @@
1−{ system ? builtins.currentSystem }:
2let
1let
3− rev = "32b46dd897ab2143a609988a04d87452f0bbef59";
2+ rev = "807ca93fadd5197c2260490de0c76e500562dc05";
4− sha256 = "1gzfrpjnr1bz9zljsyg3a4zrhk8r927sz761mrgcg56dwinkhpjk";
3+ sha256 = "10yq8bnls77fh3pk5chkkb1sv5lbdgyk1rr2v9xn71rr1k2x563p";
5 nixpkgs = builtins.fetchTarball {
4 nixpkgs = builtins.fetchTarball {
6 url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
5 url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
7 inherit sha256;
6 inherit sha256;
8 };
7 };
9− pkgs = import nixpkgs {
10− inherit system;
11− config.allowUnfree = true;
8+ pkgs = import nixpkgs { config.allowUnfree = true; };
12− };
13in pkgs
9in pkgs
nix/ormolize/default.nix+5−3
@@ -10,9 +10,11 @@
10 src = package.src;
10 src = package.src;
11 buildInputs = [
11 buildInputs = [
12 haskellPackages.cpphs
12 haskellPackages.cpphs
13+ (if doCheck
13− haskellPackages.ormolu
14+ then haskellPackages.ormolu
14− pkgs.diffutils
15+ else pkgs.haskell.lib.dontCheck haskellPackages.ormolu)
15 pkgs.glibcLocales
16 pkgs.glibcLocales
17+ pkgs.diffutils
16 ];
18 ];
17 LANG = "en_US.UTF-8";
19 LANG = "en_US.UTF-8";
18 buildPhase = ''
20 buildPhase = ''
@@ -32,7 +34,7 @@
32 cp "$hs_file" "''${hs_file}-original"
34 cp "$hs_file" "''${hs_file}-original"
33 done
35 done
34
36
35− (ormolu --check-idempotence --mode inplace $hs_files || true) 2> log.txt
37+ (ormolu --tolerate-cpp --check-idempotency --mode inplace $hs_files || true) 2> log.txt
36 '';
38 '';
37 inherit doCheck;
39 inherit doCheck;
38 checkPhase =
40 checkPhase =
ormolu.cabal+159−174
@@ -1,184 +1,169 @@
1+name: ormolu
2+version: 0.0.4.0
1−cabal-version: 1.18
3+cabal-version: 1.18
2−name: ormolu
4+tested-with: GHC==8.6.5, GHC==8.8.3, GHC==8.10.1
3−version: 0.1.2.0
4−license: BSD3
5+license: BSD3
5−license-file: LICENSE.md
6+license-file: LICENSE.md
6−maintainer: Mark Karpov <mark.karpov@tweag.io>
7+maintainer: Mark Karpov <mark.karpov@tweag.io>
7−tested-with: ghc ==8.6.5 ghc ==8.8.4 ghc ==8.10.1
8−homepage: https://github.com/tweag/ormolu
8+homepage: https://github.com/tweag/ormolu
9−bug-reports: https://github.com/tweag/ormolu/issues
9+bug-reports: https://github.com/tweag/ormolu/issues
10−synopsis: A formatter for Haskell source code
11−description: A formatter for Haskell source code.
12−category: Development, Formatting
10+category: Development, Formatting
11+synopsis: A formatter for Haskell source code
13−build-type: Simple
12+build-type: Simple
14−data-files:
13+description: A formatter for Haskell source code.
14+extra-doc-files: CONTRIBUTING.md
15+ , CHANGELOG.md
16+ , DESIGN.md
17+ , README.md
15− data/examples/declaration/annotation/*.hs
18+data-files: data/examples/declaration/annotation/*.hs
16− data/examples/declaration/class/*.hs
19+ , data/examples/declaration/class/*.hs
17− data/examples/declaration/data/*.hs
20+ , data/examples/declaration/data/*.hs
18− data/examples/declaration/data/gadt/*.hs
21+ , data/examples/declaration/data/gadt/*.hs
19− data/examples/declaration/default/*.hs
22+ , data/examples/declaration/default/*.hs
20− data/examples/declaration/deriving/*.hs
23+ , data/examples/declaration/deriving/*.hs
21− data/examples/declaration/foreign/*.hs
24+ , data/examples/declaration/foreign/*.hs
22− data/examples/declaration/instance/*.hs
25+ , data/examples/declaration/instance/*.hs
23− data/examples/declaration/rewrite-rule/*.hs
26+ , data/examples/declaration/rewrite-rule/*.hs
24− data/examples/declaration/role-annotation/*.hs
27+ , data/examples/declaration/role-annotation/*.hs
25− data/examples/declaration/signature/complete/*.hs
28+ , data/examples/declaration/signature/complete/*.hs
26− data/examples/declaration/signature/fixity/*.hs
29+ , data/examples/declaration/signature/fixity/*.hs
27− data/examples/declaration/signature/inline/*.hs
30+ , data/examples/declaration/signature/inline/*.hs
28− data/examples/declaration/signature/minimal/*.hs
31+ , data/examples/declaration/signature/minimal/*.hs
29− data/examples/declaration/signature/pattern/*.hs
32+ , data/examples/declaration/signature/pattern/*.hs
30− data/examples/declaration/signature/set-cost-centre/*.hs
33+ , data/examples/declaration/signature/set-cost-centre/*.hs
31− data/examples/declaration/signature/specialize/*.hs
34+ , data/examples/declaration/signature/specialize/*.hs
32− data/examples/declaration/signature/type/*.hs
35+ , data/examples/declaration/signature/type/*.hs
33− data/examples/declaration/splice/*.hs
36+ , data/examples/declaration/splice/*.hs
34− data/examples/declaration/type-families/closed-type-family/*.hs
37+ , data/examples/declaration/type-families/closed-type-family/*.hs
35− data/examples/declaration/type-families/data-family/*.hs
38+ , data/examples/declaration/type-families/data-family/*.hs
36− data/examples/declaration/type-families/type-family/*.hs
39+ , data/examples/declaration/type-families/type-family/*.hs
37− data/examples/declaration/type-synonyms/*.hs
40+ , data/examples/declaration/type-synonyms/*.hs
38− data/examples/declaration/type/*.hs
41+ , data/examples/declaration/type/*.hs
39− data/examples/declaration/value/function/*.hs
42+ , data/examples/declaration/value/function/*.hs
40− data/examples/declaration/value/function/arrow/*.hs
43+ , data/examples/declaration/value/function/arrow/*.hs
41− data/examples/declaration/value/function/comprehension/*.hs
44+ , data/examples/declaration/value/function/comprehension/*.hs
42− data/examples/declaration/value/function/do/*.hs
45+ , data/examples/declaration/value/function/do/*.hs
43− data/examples/declaration/value/function/infix/*.hs
46+ , data/examples/declaration/value/function/infix/*.hs
44− data/examples/declaration/value/function/pattern/*.hs
47+ , data/examples/declaration/value/function/pattern/*.hs
45− data/examples/declaration/value/other/*.hs
48+ , data/examples/declaration/value/other/*.hs
46− data/examples/declaration/value/pattern-synonyms/*.hs
49+ , data/examples/declaration/value/pattern-synonyms/*.hs
47− data/examples/declaration/warning/*.hs
50+ , data/examples/declaration/warning/*.hs
48− data/examples/import/*.hs
51+ , data/examples/import/*.hs
49− data/examples/module-header/*.hs
52+ , data/examples/module-header/*.hs
50− data/examples/other/*.hs
53+ , data/examples/other/*.hs
51−
52−extra-doc-files:
53− CONTRIBUTING.md
54− CHANGELOG.md
55− DESIGN.md
56− README.md
57
54
58source-repository head
55source-repository head
59− type: git
56+ type: git
60− location: https://github.com/tweag/ormolu.git
57+ location: https://github.com/tweag/ormolu.git
61
58
62flag dev
59flag dev
63− description: Turn on development settings.
60+ description: Turn on development settings.
64− default: False
65− manual: True
61+ manual: True
62+ default: False
66
63
67library
64library
65+ hs-source-dirs: src
66+ build-depends: base >= 4.12 && < 5.0
67+ , bytestring >= 0.2 && < 0.11
68+ , containers >= 0.5 && < 0.7
69+ , dlist >= 0.8 && < 0.9
70+ , exceptions >= 0.6 && < 0.11
71+ , ghc-lib-parser >= 8.10 && < 8.11
72+ , mtl >= 2.0 && < 3.0
73+ , syb >= 0.7 && < 0.8
74+ , text >= 0.2 && < 1.3
68− exposed-modules:
75+ exposed-modules: Ormolu
69− Ormolu
70− Ormolu.Config
76+ , Ormolu.Config
71− Ormolu.Diff
77+ , Ormolu.Diff
72− Ormolu.Exception
78+ , Ormolu.Exception
73− Ormolu.Imports
79+ , Ormolu.Imports
74− Ormolu.Parser
80+ , Ormolu.Parser
75− Ormolu.Parser.Anns
81+ , Ormolu.Parser.Anns
76− Ormolu.Parser.CommentStream
82+ , Ormolu.Parser.CommentStream
77− Ormolu.Parser.Pragma
83+ , Ormolu.Parser.Pragma
78− Ormolu.Parser.Result
84+ , Ormolu.Parser.Result
79− Ormolu.Parser.Shebang
85+ , Ormolu.Parser.Shebang
80− Ormolu.Printer
86+ , Ormolu.Printer
81− Ormolu.Printer.Combinators
87+ , Ormolu.Printer.Combinators
82− Ormolu.Printer.Comments
88+ , Ormolu.Printer.Comments
83− Ormolu.Printer.Internal
89+ , Ormolu.Printer.Internal
84− Ormolu.Printer.Meat.Common
90+ , Ormolu.Printer.Meat.Common
85− Ormolu.Printer.Meat.Declaration
91+ , Ormolu.Printer.Meat.Declaration
86− Ormolu.Printer.Meat.Declaration.Annotation
92+ , Ormolu.Printer.Meat.Declaration.Annotation
87− Ormolu.Printer.Meat.Declaration.Class
93+ , Ormolu.Printer.Meat.Declaration.Class
88− Ormolu.Printer.Meat.Declaration.Data
94+ , Ormolu.Printer.Meat.Declaration.Data
89− Ormolu.Printer.Meat.Declaration.Default
95+ , Ormolu.Printer.Meat.Declaration.Default
90− Ormolu.Printer.Meat.Declaration.Foreign
96+ , Ormolu.Printer.Meat.Declaration.Foreign
91− Ormolu.Printer.Meat.Declaration.Instance
97+ , Ormolu.Printer.Meat.Declaration.Instance
92− Ormolu.Printer.Meat.Declaration.RoleAnnotation
98+ , Ormolu.Printer.Meat.Declaration.RoleAnnotation
93− Ormolu.Printer.Meat.Declaration.Rule
99+ , Ormolu.Printer.Meat.Declaration.Rule
94− Ormolu.Printer.Meat.Declaration.Signature
100+ , Ormolu.Printer.Meat.Declaration.Signature
95− Ormolu.Printer.Meat.Declaration.Splice
101+ , Ormolu.Printer.Meat.Declaration.Splice
96− Ormolu.Printer.Meat.Declaration.Type
102+ , Ormolu.Printer.Meat.Declaration.Type
97− Ormolu.Printer.Meat.Declaration.TypeFamily
103+ , Ormolu.Printer.Meat.Declaration.TypeFamily
98− Ormolu.Printer.Meat.Declaration.Value
104+ , Ormolu.Printer.Meat.Declaration.Value
99− Ormolu.Printer.Meat.Declaration.Warning
105+ , Ormolu.Printer.Meat.Declaration.Warning
100− Ormolu.Printer.Meat.ImportExport
106+ , Ormolu.Printer.Meat.ImportExport
101− Ormolu.Printer.Meat.Module
107+ , Ormolu.Printer.Meat.Module
102− Ormolu.Printer.Meat.Pragma
108+ , Ormolu.Printer.Meat.Pragma
103− Ormolu.Printer.Meat.Type
109+ , Ormolu.Printer.Meat.Type
104− Ormolu.Printer.Operators
110+ , Ormolu.Printer.Operators
105− Ormolu.Printer.SpanStream
111+ , Ormolu.Printer.SpanStream
106− Ormolu.Processing.Common
112+ , Ormolu.Processing.Common
107− Ormolu.Processing.Cpp
108− Ormolu.Processing.Postprocess
113+ , Ormolu.Processing.Postprocess
109− Ormolu.Processing.Preprocess
114+ , Ormolu.Processing.Preprocess
110− Ormolu.Utils
115+ , Ormolu.Utils
111−
112− hs-source-dirs: src
113− other-modules:
116+ other-modules: GHC
114− GHC
115− GHC.DynFlags
117+ , GHC.DynFlags
116−
117− default-language: Haskell2010
118− build-depends:
119− base >=4.12 && <5.0,
120− bytestring >=0.2 && <0.11,
121− containers >=0.5 && <0.7,
122− dlist >=0.8 && <2.0,
123− exceptions >=0.6 && <0.11,
124− ghc-lib-parser >=8.10 && <8.11,
125− mtl >=2.0 && <3.0,
126− syb >=0.7 && <0.8,
127− text >=0.2 && <1.3
128−
129− if flag(dev)
118+ if flag(dev)
130− ghc-options:
119+ ghc-options: -Wall -Werror -Wcompat
131− -Wall -Werror -Wcompat -Wincomplete-record-updates
120+ -Wincomplete-record-updates
121+ -Wincomplete-uni-patterns
132− -Wincomplete-uni-patterns -Wnoncanonical-monad-instances
122+ -Wnoncanonical-monad-instances
123+ -- https://github.com/haskell/haddock/issues/1116
133− -Wno-missing-home-modules
124+ -Wno-missing-home-modules
134−
135− else
125+ else
136− ghc-options: -O2 -Wall
126+ ghc-options: -O2 -Wall
137−
138−executable ormolu
139− main-is: Main.hs
140− hs-source-dirs: app
141− other-modules: Paths_ormolu
142− default-language: Haskell2010
127+ default-language: Haskell2010
143− build-depends:
144− base >=4.12 && <5.0,
145− ghc-lib-parser >=8.10 && <8.11,
146− gitrev >=1.3 && <1.4,
147− optparse-applicative >=0.14 && <0.17,
148− ormolu -any,
149− text >=0.2 && <1.3
150−
151− if flag(dev)
152− ghc-options:
153− -Wall -Werror -Wcompat -Wincomplete-record-updates
154− -Wincomplete-uni-patterns -Wnoncanonical-monad-instances
155− -optP-Wno-nonportable-include-path
156−
157− else
158− ghc-options: -O2 -Wall -rtsopts
159
128
160test-suite tests
129test-suite tests
161− type: exitcode-stdio-1.0
162− main-is: Spec.hs
130+ main-is: Spec.hs
163− build-tools: hspec-discover >=2.0 && <3.0
164− hs-source-dirs: tests
131+ hs-source-dirs: tests
132+ type: exitcode-stdio-1.0
133+ build-depends: base >= 4.12 && < 5.0
134+ , containers >= 0.5 && < 0.7
135+ , filepath >= 1.2 && < 1.5
136+ , hspec >= 2.0 && < 3.0
137+ , ormolu
138+ , path >= 0.6 && < 0.8
139+ , path-io >= 1.4.2 && < 2.0
140+ , text >= 0.2 && < 1.3
141+ build-tools: hspec-discover >= 2.0 && < 3.0
165− other-modules:
142+ other-modules:
166− Ormolu.Parser.PragmaSpec
143+ Ormolu.Parser.PragmaSpec
167− Ormolu.PrinterSpec
144+ , Ormolu.PrinterSpec
168
145
146+ if flag(dev)
147+ ghc-options: -Wall -Werror
148+ else
149+ ghc-options: -O2 -Wall
169− default-language: Haskell2010
150+ default-language: Haskell2010
170− build-depends:
171− base >=4.12 && <5.0,
172− containers >=0.5 && <0.7,
173− filepath >=1.2 && <1.5,
174− hspec >=2.0 && <3.0,
175− ormolu -any,
176− path >=0.6 && <0.8,
177− path-io >=1.4.2 && <2.0,
178− text >=0.2 && <1.3
179
151
152+executable ormolu
153+ main-is: Main.hs
154+ hs-source-dirs: app
155+ build-depends: base >= 4.12 && < 5.0
156+ , ghc-lib-parser >= 8.10 && < 8.11
157+ , gitrev >= 1.3 && < 1.4
158+ , optparse-applicative >= 0.14 && < 0.16
159+ , ormolu
160+ , text >= 0.2 && < 1.3
161+ other-modules: Paths_ormolu
180− if flag(dev)
162+ if flag(dev)
181− ghc-options: -Wall -Werror
163+ ghc-options: -Wall -Werror -Wcompat
182−
164+ -Wincomplete-record-updates
165+ -Wincomplete-uni-patterns
166+ -Wnoncanonical-monad-instances
183− else
167+ else
184− ghc-options: -O2 -Wall
168+ ghc-options: -O2 -Wall -rtsopts
169+ default-language: Haskell2010
region-tests/expected-result-17-18.hsdeleted−17
@@ -1,17 +0,0 @@
1−{-# LANGUAGE LambdaCase #-}
2−
3−module Foo (
4− foo, bar, baz) where
5−
6−foo :: Int
7−foo = 5
8−
9−bar :: Int -> Int
10−bar = \case
11− 0 -> foo
12− x -> x - foo
13−
14−baz :: Int -> Int
15−baz = gege
16− where
17− gege = 1 + 2
region-tests/expected-result-6-7.hsdeleted−17
@@ -1,17 +0,0 @@
1−{-# LANGUAGE LambdaCase #-}
2−
3−module Foo (
4− foo, bar, baz) where
5−
6−foo :: Int
7−foo = 5
8−
9−bar :: Int -> Int
10−bar = \case
11− 0 -> foo
12− x -> x - foo
13−
14−baz :: Int -> Int
15−baz = gege
16− where
17− gege = 1 + 2
region-tests/expected-result-6-8.hsdeleted−16
@@ -1,16 +0,0 @@
1−{-# LANGUAGE LambdaCase #-}
2−
3−module Foo (
4− foo, bar, baz) where
5−
6−foo :: Int
7−foo = 5
8−bar :: Int -> Int
9−bar = \case
10− 0 -> foo
11− x -> x - foo
12−
13−baz :: Int -> Int
14−baz = gege
15− where
16− gege = 1 + 2
region-tests/expected-result-9-12.hsdeleted−17
@@ -1,17 +0,0 @@
1−{-# LANGUAGE LambdaCase #-}
2−
3−module Foo (
4− foo, bar, baz) where
5−
6−foo :: Int
7−foo = 5
8−
9−bar :: Int -> Int
10−bar = \case
11− 0 -> foo
12− x -> x - foo
13−
14−baz :: Int -> Int
15−baz = gege
16− where
17− gege = 1 + 2
region-tests/expected-result-all.hsdeleted−21
@@ -1,21 +0,0 @@
1−{-# LANGUAGE LambdaCase #-}
2−
3−module Foo
4− ( foo,
5− bar,
6− baz,
7− )
8−where
9−
10−foo :: Int
11−foo = 5
12−
13−bar :: Int -> Int
14−bar = \case
15− 0 -> foo
16− x -> x - foo
17−
18−baz :: Int -> Int
19−baz = gege
20− where
21− gege = 1 + 2
region-tests/src.hsdeleted−17
@@ -1,17 +0,0 @@
1−{-# LANGUAGE LambdaCase #-}
2−
3−module Foo (
4− foo, bar, baz) where
5−
6−foo :: Int
7−foo = 5
8−
9−bar :: Int -> Int
10−bar = \case
11− 0 -> foo
12− x -> x - foo
13−
14−baz :: Int -> Int
15−baz = gege
16− where
17− gege = 1 + 2
shell.nix+2−4
@@ -1,5 +1,3 @@
1−{ pkgs ? (import ./nix/nixpkgs { inherit system; })
1+{ pkgs ? (import ./nix/nixpkgs) }:
2−, system ? builtins.currentSystem
3−}:
4
2
5−(import ./default.nix { inherit pkgs; }).dev.ormoluShell
3+(import ./default.nix { inherit pkgs; }).ormoluShell
src/GHC.hs+3
@@ -1,5 +1,6 @@
1module GHC
1module GHC
2 ( module X,
2 ( module X,
3+ ParsedSource,
3 )
4 )
4where
5where
5
6
@@ -10,3 +11,5 @@ import GHC.Hs.Instances as X ()
10import Module as X
11import Module as X
11import RdrName as X
12import RdrName as X
12import SrcLoc as X
13import SrcLoc as X
14+
15+type ParsedSource = Located (HsModule GhcPs)
src/Ormolu.hs+7−10
@@ -6,7 +6,6 @@ module Ormolu
6 ormoluFile,
6 ormoluFile,
7 ormoluStdin,
7 ormoluStdin,
8 Config (..),
8 Config (..),
9− RegionIndices (..),
10 defaultConfig,
9 defaultConfig,
11 DynOption (..),
10 DynOption (..),
12 OrmoluException (..),
11 OrmoluException (..),
@@ -43,15 +42,13 @@ import qualified SrcLoc as GHC
43ormolu ::
42ormolu ::
44 MonadIO m =>
43 MonadIO m =>
45 -- | Ormolu configuration
44 -- | Ormolu configuration
46− Config RegionIndices ->
45+ Config ->
47 -- | Location of source file
46 -- | Location of source file
48 FilePath ->
47 FilePath ->
49 -- | Input to format
48 -- | Input to format
50 String ->
49 String ->
51 m Text
50 m Text
52−ormolu cfgWithIndices path str = do
51+ormolu cfg path str = do
53− let totalLines = length (lines str)
54− cfg = regionIndicesToDeltas totalLines <$> cfgWithIndices
55 (warnings, result0) <-
52 (warnings, result0) <-
56 parseModule' cfg OrmoluParsingFailed path str
53 parseModule' cfg OrmoluParsingFailed path str
57 when (cfgDebug cfg) $ do
54 when (cfgDebug cfg) $ do
@@ -63,7 +60,7 @@ ormolu cfgWithIndices path str = do
63 -- to parse the rendered code back, inside of GHC monad wrapper which will
60 -- to parse the rendered code back, inside of GHC monad wrapper which will
64 -- lead to error messages presenting the exceptions as GHC bugs.
61 -- lead to error messages presenting the exceptions as GHC bugs.
65 let !txt = printModule result0
62 let !txt = printModule result0
66− when (not (cfgUnsafe cfg) || cfgCheckIdempotence cfg) $ do
63+ when (not (cfgUnsafe cfg) || cfgCheckIdempotency cfg) $ do
67 let pathRendered = path ++ "<rendered>"
64 let pathRendered = path ++ "<rendered>"
68 -- Parse the result of pretty-printing again and make sure that AST
65 -- Parse the result of pretty-printing again and make sure that AST
69 -- is the same as AST of original snippet module span positions.
66 -- is the same as AST of original snippet module span positions.
@@ -79,7 +76,7 @@ ormolu cfgWithIndices path str = do
79 Different ss -> liftIO $ throwIO (OrmoluASTDiffers path ss)
76 Different ss -> liftIO $ throwIO (OrmoluASTDiffers path ss)
80 -- Try re-formatting the formatted result to check if we get exactly
77 -- Try re-formatting the formatted result to check if we get exactly
81 -- the same output.
78 -- the same output.
82− when (cfgCheckIdempotence cfg) $
79+ when (cfgCheckIdempotency cfg) $
83 let txt2 = printModule result1
80 let txt2 = printModule result1
84 in case diffText txt txt2 pathRendered of
81 in case diffText txt txt2 pathRendered of
85 Nothing -> return ()
82 Nothing -> return ()
@@ -96,7 +93,7 @@ ormolu cfgWithIndices path str = do
96ormoluFile ::
93ormoluFile ::
97 MonadIO m =>
94 MonadIO m =>
98 -- | Ormolu configuration
95 -- | Ormolu configuration
99− Config RegionIndices ->
96+ Config ->
100 -- | Location of source file
97 -- | Location of source file
101 FilePath ->
98 FilePath ->
102 -- | Resulting rendition
99 -- | Resulting rendition
@@ -111,7 +108,7 @@ ormoluFile cfg path =
111ormoluStdin ::
108ormoluStdin ::
112 MonadIO m =>
109 MonadIO m =>
113 -- | Ormolu configuration
110 -- | Ormolu configuration
114− Config RegionIndices ->
111+ Config ->
115 -- | Resulting rendition
112 -- | Resulting rendition
116 m Text
113 m Text
117ormoluStdin cfg =
114ormoluStdin cfg =
@@ -124,7 +121,7 @@ ormoluStdin cfg =
124parseModule' ::
121parseModule' ::
125 MonadIO m =>
122 MonadIO m =>
126 -- | Ormolu configuration
123 -- | Ormolu configuration
127− Config RegionDeltas ->
124+ Config ->
128 -- | How to obtain 'OrmoluException' to throw when parsing fails
125 -- | How to obtain 'OrmoluException' to throw when parsing fails
129 (GHC.SrcSpan -> String -> OrmoluException) ->
126 (GHC.SrcSpan -> String -> OrmoluException) ->
130 -- | File name to use in errors
127 -- | File name to use in errors
src/Ormolu/Config.hs+11−52
@@ -1,13 +1,7 @@
1−{-# LANGUAGE DeriveFunctor #-}
2−{-# LANGUAGE RecordWildCards #-}
3−
4-- | Configuration options used by the tool.
1-- | Configuration options used by the tool.
5module Ormolu.Config
2module Ormolu.Config
6 ( Config (..),
3 ( Config (..),
7− RegionIndices (..),
8− RegionDeltas (..),
9 defaultConfig,
4 defaultConfig,
10− regionIndicesToDeltas,
11 DynOption (..),
5 DynOption (..),
12 dynOptionToLocatedStr,
6 dynOptionToLocatedStr,
13 )
7 )
@@ -16,66 +10,31 @@ where
16import qualified SrcLoc as GHC
10import qualified SrcLoc as GHC
17
11
18-- | Ormolu configuration.
12-- | Ormolu configuration.
19−data Config region = Config
13+data Config = Config
20 { -- | Dynamic options to pass to GHC parser
14 { -- | Dynamic options to pass to GHC parser
21 cfgDynOptions :: ![DynOption],
15 cfgDynOptions :: ![DynOption],
22 -- | Do formatting faster but without automatic detection of defects
16 -- | Do formatting faster but without automatic detection of defects
23 cfgUnsafe :: !Bool,
17 cfgUnsafe :: !Bool,
24 -- | Output information useful for debugging
18 -- | Output information useful for debugging
25 cfgDebug :: !Bool,
19 cfgDebug :: !Bool,
20+ -- | Do not fail if CPP pragma is present (still doesn't handle CPP but
21+ -- useful for formatting of files that enable the extension without
22+ -- actually containing CPP macros)
23+ cfgTolerateCpp :: !Bool,
26− -- | Checks if re-formatting the result is idempotent
24+ -- | Checks if re-formatting the result is idempotent.
27− cfgCheckIdempotence :: !Bool,
25+ cfgCheckIdempotency :: !Bool
28− -- | Region selection
29− cfgRegion :: !region
30− }
31− deriving (Eq, Show, Functor)
32−
33−-- | Region selection as the combination of start and end line numbers.
34−data RegionIndices = RegionIndices
35− { -- | Start line of the region to format
36− regionStartLine :: !(Maybe Int),
37− -- | End line of the region to format
38− regionEndLine :: !(Maybe Int)
39− }
40− deriving (Eq, Show)
41−
42−-- | Region selection as the length of the literal prefix and the literal
43−-- suffix.
44−data RegionDeltas = RegionDeltas
45− { -- | Prefix length in number of lines
46− regionPrefixLength :: !Int,
47− -- | Suffix length in number of lines
48− regionSuffixLength :: !Int
49 }
26 }
50 deriving (Eq, Show)
27 deriving (Eq, Show)
51
28
52−-- | Default @'Config' 'RegionIndices'@.
29+-- | Default 'Config'.
53−defaultConfig :: Config RegionIndices
30+defaultConfig :: Config
54defaultConfig =
31defaultConfig =
55 Config
32 Config
56 { cfgDynOptions = [],
33 { cfgDynOptions = [],
57 cfgUnsafe = False,
34 cfgUnsafe = False,
58 cfgDebug = False,
35 cfgDebug = False,
59− cfgCheckIdempotence = False,
36+ cfgTolerateCpp = False,
60− cfgRegion =
37+ cfgCheckIdempotency = False
61− RegionIndices
62− { regionStartLine = Nothing,
63− regionEndLine = Nothing
64− }
65− }
66−
67−-- | Convert 'RegionIndices' into 'RegionDeltas'.
68−regionIndicesToDeltas ::
69− -- | Total number of lines in the input
70− Int ->
71− -- | Region indices
72− RegionIndices ->
73− -- | Region deltas
74− RegionDeltas
75−regionIndicesToDeltas total RegionIndices {..} =
76− RegionDeltas
77− { regionPrefixLength = maybe 0 (subtract 1) regionStartLine,
78− regionSuffixLength = maybe 0 (total -) regionEndLine
79 }
38 }
80
39
81-- | A wrapper for dynamic options.
40-- | A wrapper for dynamic options.
src/Ormolu/Diff.hs+12−15
@@ -14,8 +14,7 @@ import Data.Text (Text)
14import qualified Data.Text as T
14import qualified Data.Text as T
15import qualified FastString as GHC
15import qualified FastString as GHC
16import GHC
16import GHC
17−import Ormolu.Imports (normalizeImports)
17+import Ormolu.Imports (sortImports)
18−import Ormolu.Parser.CommentStream
19import Ormolu.Parser.Result
18import Ormolu.Parser.Result
20import Ormolu.Utils
19import Ormolu.Utils
21
20
@@ -39,16 +38,14 @@ diffParseResult :: ParseResult -> ParseResult -> Diff
39diffParseResult
38diffParseResult
40 ParseResult
39 ParseResult
41 { prCommentStream = cstream0,
40 { prCommentStream = cstream0,
42− prParsedSource = hs0
41+ prParsedSource = ps0
43 }
42 }
44 ParseResult
43 ParseResult
45 { prCommentStream = cstream1,
44 { prCommentStream = cstream1,
46− prParsedSource = hs1
45+ prParsedSource = ps1
47 } =
46 } =
48 matchIgnoringSrcSpans cstream0 cstream1
47 matchIgnoringSrcSpans cstream0 cstream1
49− <> matchIgnoringSrcSpans
48+ <> matchIgnoringSrcSpans ps0 ps1
50− hs0 {hsmodImports = normalizeImports (hsmodImports hs0)}
51− hs1 {hsmodImports = normalizeImports (hsmodImports hs1)}
52
49
53-- | Compare two values for equality disregarding differences in 'SrcSpan's
50-- | Compare two values for equality disregarding differences in 'SrcSpan's
54-- and the ordering of import lists.
51-- and the ordering of import lists.
@@ -70,7 +67,7 @@ matchIgnoringSrcSpans = genericQuery
70 gzipWithQ
67 gzipWithQ
71 ( genericQuery
68 ( genericQuery
72 `extQ` srcSpanEq
69 `extQ` srcSpanEq
73− `extQ` commentEq
70+ `extQ` hsModuleEq
74 `extQ` sourceTextEq
71 `extQ` sourceTextEq
75 `extQ` hsDocStringEq
72 `extQ` hsDocStringEq
76 `extQ` importDeclQualifiedStyleEq
73 `extQ` importDeclQualifiedStyleEq
@@ -81,14 +78,14 @@ matchIgnoringSrcSpans = genericQuery
81 | otherwise = Different []
78 | otherwise = Different []
82 srcSpanEq :: SrcSpan -> GenericQ Diff
79 srcSpanEq :: SrcSpan -> GenericQ Diff
83 srcSpanEq _ _ = Same
80 srcSpanEq _ _ = Same
84− commentEq :: Comment -> GenericQ Diff
81+ hsModuleEq :: HsModule GhcPs -> GenericQ Diff
85− commentEq (Comment _ x) d =
82+ hsModuleEq hs0 hs1' =
86− case cast d :: Maybe Comment of
83+ case cast hs1' :: Maybe (HsModule GhcPs) of
87 Nothing -> Different []
84 Nothing -> Different []
88− Just (Comment _ y) ->
85+ Just hs1 ->
89− if x == y
86+ matchIgnoringSrcSpans
90− then Same
87+ hs0 {hsmodImports = sortImports (hsmodImports hs0)}
91− else Different []
88+ hs1 {hsmodImports = sortImports (hsmodImports hs1)}
92 sourceTextEq :: SourceText -> GenericQ Diff
89 sourceTextEq :: SourceText -> GenericQ Diff
93 sourceTextEq _ _ = Same
90 sourceTextEq _ _ = Same
94 importDeclQualifiedStyleEq :: ImportDeclQualifiedStyle -> GenericQ Diff
91 importDeclQualifiedStyleEq :: ImportDeclQualifiedStyle -> GenericQ Diff
src/Ormolu/Exception.hs+10−3
@@ -19,7 +19,9 @@ import System.IO
19
19
20-- | Ormolu exception representing all cases when Ormolu can fail.
20-- | Ormolu exception representing all cases when Ormolu can fail.
21data OrmoluException
21data OrmoluException
22+ = -- | Ormolu does not work with source files that use CPP
23+ OrmoluCppEnabled FilePath
22− = -- | Parsing of original source code failed
24+ | -- | Parsing of original source code failed
23 OrmoluParsingFailed GHC.SrcSpan String
25 OrmoluParsingFailed GHC.SrcSpan String
24 | -- | Parsing of formatted source code failed
26 | -- | Parsing of formatted source code failed
25 OrmoluOutputParsingFailed GHC.SrcSpan String
27 OrmoluOutputParsingFailed GHC.SrcSpan String
@@ -33,6 +35,11 @@ data OrmoluException
33
35
34instance Exception OrmoluException where
36instance Exception OrmoluException where
35 displayException = \case
37 displayException = \case
38+ OrmoluCppEnabled path ->
39+ unlines
40+ [ "CPP is not supported:",
41+ withIndent path
42+ ]
36 OrmoluParsingFailed s e ->
43 OrmoluParsingFailed s e ->
37 showParsingErr "The GHC parser (in Haddock mode) failed:" s [e]
44 showParsingErr "The GHC parser (in Haddock mode) failed:" s [e]
38 OrmoluOutputParsingFailed s e ->
45 OrmoluOutputParsingFailed s e ->
@@ -74,8 +81,8 @@ withPrettyOrmoluExceptions m = m `catch` h
74 hPutStrLn stderr (displayException e)
81 hPutStrLn stderr (displayException e)
75 exitWith . ExitFailure $
82 exitWith . ExitFailure $
76 case e of
83 case e of
77− -- Error code 1 is for 'error' or 'notImplemented'
84+ -- Error code 1 is for `error` or `notImplemented`
78− -- 2 used to be for erroring out on CPP
85+ OrmoluCppEnabled {} -> 2
79 OrmoluParsingFailed {} -> 3
86 OrmoluParsingFailed {} -> 3
80 OrmoluOutputParsingFailed {} -> 4
87 OrmoluOutputParsingFailed {} -> 4
81 OrmoluASTDiffers {} -> 5
88 OrmoluASTDiffers {} -> 5
src/Ormolu/Imports.hs+44−161
@@ -4,199 +4,82 @@
4
4
5-- | Manipulations on import lists.
5-- | Manipulations on import lists.
6module Ormolu.Imports
6module Ormolu.Imports
7− ( normalizeImports,
7+ ( sortImports,
8 )
8 )
9where
9where
10
10
11import Data.Bifunctor
11import Data.Bifunctor
12−import Data.Char (isAlphaNum)
13import Data.Function (on)
12import Data.Function (on)
14−import Data.List (foldl', nubBy, sortBy, sortOn)
13+import Data.Generics (gcompare)
15−import Data.Map.Strict (Map)
14+import Data.List (sortBy)
16−import qualified Data.Map.Strict as M
17−import FastString (FastString)
18import GHC hiding (GhcPs, IE)
15import GHC hiding (GhcPs, IE)
19import GHC.Hs.Extension
16import GHC.Hs.Extension
20import GHC.Hs.ImpExp (IE (..))
17import GHC.Hs.ImpExp (IE (..))
21−import Ormolu.Utils (notImplemented, showOutputable)
18+import Ormolu.Utils (notImplemented)
22
19
23−-- | Sort and normalize imports.
20+-- | Sort imports by module name. This also sorts explicit import lists for
21+-- each declaration.
24−normalizeImports :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]
22+sortImports :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]
25−normalizeImports =
23+sortImports = sortBy compareIdecl . fmap (fmap sortImportLists)
26− fmap snd
27− . M.toAscList
28− . M.fromListWith combineImports
29− . fmap (\x -> (importId x, g x))
30 where
24 where
31− g (L l ImportDecl {..}) =
25+ sortImportLists :: ImportDecl GhcPs -> ImportDecl GhcPs
32− L
26+ sortImportLists = \case
33− l
27+ ImportDecl {..} ->
34 ImportDecl
28 ImportDecl
35− { ideclHiding = second (fmap normalizeLies) <$> ideclHiding,
29+ { ideclHiding = second (fmap sortLies) <$> ideclHiding,
36 ..
30 ..
37 }
31 }
38− g _ = notImplemented "XImportDecl"
32+ XImportDecl x -> noExtCon x
39
33
40−-- | Combine two import declarations. It should be assumed that 'ImportId's
41−-- are equal.
42−combineImports ::
43− LImportDecl GhcPs ->
44− LImportDecl GhcPs ->
34+-- | Compare two @'LImportDecl' 'GhcPs'@ things.
45− LImportDecl GhcPs
35+compareIdecl :: LImportDecl GhcPs -> LImportDecl GhcPs -> Ordering
46−combineImports (L lx ImportDecl {..}) (L _ y) =
36+compareIdecl (L _ m0) (L _ m1) =
47− L
37+ case (isPrelude n0, isPrelude n1) of
48− lx
38+ (False, False) -> n0 `compare` n1
49− ImportDecl
39+ (True, False) -> GT
50− { ideclHiding = case (ideclHiding, GHC.ideclHiding y) of
40+ (False, True) -> LT
51− (Just (hiding, L l' xs), Just (_, L _ ys)) ->
41+ (True, True) -> m0 `gcompare` m1
52− Just (hiding, (L l' (normalizeLies (xs ++ ys))))
53− _ -> Nothing,
54− ..
55− }
56−combineImports _ _ = notImplemented "XImportDecl"
57−
58−-- | Import id, a collection of all things that justify having a separate
59−-- import entry. This is used for merging of imports. If two imports have
60−-- the same 'ImportId' they can be merged.
61−data ImportId = ImportId
62− { importIsPrelude :: Bool,
63− importIdName :: ModuleName,
64− importPkgQual :: Maybe FastString,
65− importSource :: Bool,
66− importSafe :: Bool,
67− importQualified :: Bool,
68− importImplicit :: Bool,
69− importAs :: Maybe ModuleName,
70− importHiding :: Maybe Bool
71− }
72− deriving (Eq, Ord)
73−
74−-- | Obtain an 'ImportId' for a given import.
75−importId :: LImportDecl GhcPs -> ImportId
76−importId (L _ ImportDecl {..}) =
77− ImportId
78− { importIsPrelude = isPrelude,
79− importIdName = moduleName,
80− importPkgQual = sl_fs <$> ideclPkgQual,
81− importSource = ideclSource,
82− importSafe = ideclSafe,
83− importQualified = case ideclQualified of
84− QualifiedPre -> True
85− QualifiedPost -> True
86− NotQualified -> False,
87− importImplicit = ideclImplicit,
88− importAs = unLoc <$> ideclAs,
89− importHiding = fst <$> ideclHiding
90− }
91 where
42 where
43+ n0 = unLoc (ideclName m0)
44+ n1 = unLoc (ideclName m1)
92− isPrelude = moduleNameString moduleName == "Prelude"
45+ isPrelude = (== "Prelude") . moduleNameString
93− moduleName = unLoc ideclName
94−importId _ = notImplemented "XImportDecl"
95
46
96−-- | Normalize a collection of import\/export items.
47+-- | Sort located import or export.
97−normalizeLies :: [LIE GhcPs] -> [LIE GhcPs]
48+sortLies :: [LIE GhcPs] -> [LIE GhcPs]
98−normalizeLies = sortOn (getIewn . unLoc) . M.elems . foldl' combine M.empty
49+sortLies = sortBy (compareIE `on` unLoc) . fmap (fmap sortThings)
99− where
100− combine ::
101− Map IEWrappedNameOrd (LIE GhcPs) ->
102− LIE GhcPs ->
103− Map IEWrappedNameOrd (LIE GhcPs)
104− combine m (L new_l new) =
105− let wname = getIewn new
106− normalizeWNames =
107− nubBy (\x y -> compareLIewn x y == EQ) . sortBy compareLIewn
108− alter = \case
109− Nothing -> Just . L new_l $
110− case new of
111− IEThingWith NoExtField n wildcard g flbl ->
112− IEThingWith NoExtField n wildcard (normalizeWNames g) flbl
113− other -> other
114− Just old ->
115− let f = \case
116− IEVar NoExtField n -> IEVar NoExtField n
117− IEThingAbs NoExtField _ -> new
118− IEThingAll NoExtField n -> IEThingAll NoExtField n
119− IEThingWith NoExtField n wildcard g flbl ->
120− case new of
121− IEVar NoExtField _ ->
122− error "Ormolu.Imports broken presupposition"
123− IEThingAbs NoExtField _ ->
124− IEThingWith NoExtField n wildcard g flbl
125− IEThingAll NoExtField n' ->
126− IEThingAll NoExtField n'
127− IEThingWith NoExtField n' wildcard' g' flbl' ->
128− let combinedWildcard =
129− case (wildcard, wildcard') of
130− (IEWildcard _, _) -> IEWildcard 0
131− (_, IEWildcard _) -> IEWildcard 0
132− _ -> NoIEWildcard
133− in IEThingWith
134− NoExtField
135− n'
136− combinedWildcard
137− (normalizeWNames (g <> g'))
138− flbl'
139− IEModuleContents NoExtField _ -> notImplemented "IEModuleContents"
140− IEGroup NoExtField _ _ -> notImplemented "IEGroup"
141− IEDoc NoExtField _ -> notImplemented "IEDoc"
142− IEDocNamed NoExtField _ -> notImplemented "IEDocNamed"
143− XIE x -> noExtCon x
144− IEModuleContents NoExtField _ -> notImplemented "IEModuleContents"
145− IEGroup NoExtField _ _ -> notImplemented "IEGroup"
146− IEDoc NoExtField _ -> notImplemented "IEDoc"
147− IEDocNamed NoExtField _ -> notImplemented "IEDocNamed"
148− XIE x -> noExtCon x
149− in Just (f <$> old)
150− in M.alter alter wname m
151
50
152−-- | A wrapper for @'IEWrappedName' 'RdrName'@ that allows us to define an
51+-- | Sort imports\/exports inside of 'IEThingWith'.
153−-- 'Ord' instance for it.
52+sortThings :: IE GhcPs -> IE GhcPs
154−newtype IEWrappedNameOrd = IEWrappedNameOrd (IEWrappedName RdrName)
53+sortThings = \case
155− deriving (Eq)
54+ IEThingWith NoExtField x w xs fl ->
55+ IEThingWith NoExtField x w (sortBy (compareIewn `on` unLoc) xs) fl
56+ other -> other
156
57
157−instance Ord IEWrappedNameOrd where
58+-- | Compare two located imports or exports.
158− compare (IEWrappedNameOrd x) (IEWrappedNameOrd y) = compareIewn x y
59+compareIE :: IE GhcPs -> IE GhcPs -> Ordering
60+compareIE = compareIewn `on` getIewn
159
61
160-- | Project @'IEWrappedName' 'RdrName'@ from @'IE' 'GhcPs'@.
62-- | Project @'IEWrappedName' 'RdrName'@ from @'IE' 'GhcPs'@.
161−getIewn :: IE GhcPs -> IEWrappedNameOrd
63+getIewn :: IE GhcPs -> IEWrappedName RdrName
162getIewn = \case
64getIewn = \case
163− IEVar NoExtField x -> IEWrappedNameOrd (unLoc x)
65+ IEVar NoExtField x -> unLoc x
164− IEThingAbs NoExtField x -> IEWrappedNameOrd (unLoc x)
66+ IEThingAbs NoExtField x -> unLoc x
165− IEThingAll NoExtField x -> IEWrappedNameOrd (unLoc x)
67+ IEThingAll NoExtField x -> unLoc x
166− IEThingWith NoExtField x _ _ _ -> IEWrappedNameOrd (unLoc x)
68+ IEThingWith NoExtField x _ _ _ -> unLoc x
167 IEModuleContents NoExtField _ -> notImplemented "IEModuleContents"
69 IEModuleContents NoExtField _ -> notImplemented "IEModuleContents"
168 IEGroup NoExtField _ _ -> notImplemented "IEGroup"
70 IEGroup NoExtField _ _ -> notImplemented "IEGroup"
169 IEDoc NoExtField _ -> notImplemented "IEDoc"
71 IEDoc NoExtField _ -> notImplemented "IEDoc"
170 IEDocNamed NoExtField _ -> notImplemented "IEDocNamed"
72 IEDocNamed NoExtField _ -> notImplemented "IEDocNamed"
171 XIE x -> noExtCon x
73 XIE x -> noExtCon x
172
74
173−-- | Like 'compareIewn' for located wrapped names.
174−compareLIewn :: LIEWrappedName RdrName -> LIEWrappedName RdrName -> Ordering
175−compareLIewn = compareIewn `on` unLoc
176−
177-- | Compare two @'IEWrapppedName' 'RdrName'@ things.
75-- | Compare two @'IEWrapppedName' 'RdrName'@ things.
178compareIewn :: IEWrappedName RdrName -> IEWrappedName RdrName -> Ordering
76compareIewn :: IEWrappedName RdrName -> IEWrappedName RdrName -> Ordering
179−compareIewn (IEName x) (IEName y) = unLoc x `compareRdrName` unLoc y
77+compareIewn (IEName x) (IEName y) = unLoc x `compare` unLoc y
180compareIewn (IEName _) (IEPattern _) = LT
78compareIewn (IEName _) (IEPattern _) = LT
181compareIewn (IEName _) (IEType _) = LT
79compareIewn (IEName _) (IEType _) = LT
182compareIewn (IEPattern _) (IEName _) = GT
80compareIewn (IEPattern _) (IEName _) = GT
183−compareIewn (IEPattern x) (IEPattern y) = unLoc x `compareRdrName` unLoc y
81+compareIewn (IEPattern x) (IEPattern y) = unLoc x `compare` unLoc y
184compareIewn (IEPattern _) (IEType _) = LT
82compareIewn (IEPattern _) (IEType _) = LT
185compareIewn (IEType _) (IEName _) = GT
83compareIewn (IEType _) (IEName _) = GT
186compareIewn (IEType _) (IEPattern _) = GT
84compareIewn (IEType _) (IEPattern _) = GT
187−compareIewn (IEType x) (IEType y) = unLoc x `compareRdrName` unLoc y
85+compareIewn (IEType x) (IEType y) = unLoc x `compare` unLoc y
188−
189−compareRdrName :: RdrName -> RdrName -> Ordering
190−compareRdrName x y =
191− case (getNameStr x, getNameStr y) of
192− ([], []) -> EQ
193− ((_ : _), []) -> GT
194− ([], (_ : _)) -> LT
195− ((x' : _), (y' : _)) ->
196− case (isAlphaNum x', isAlphaNum y') of
197− (False, False) -> x `compare` y
198− (True, False) -> LT
199− (False, True) -> GT
200− (True, True) -> x `compare` y
201− where
202− getNameStr = showOutputable . rdrNameOcc
src/Ormolu/Parser.hs+13−20
@@ -12,11 +12,11 @@ where
12import Bag (bagToList)
12import Bag (bagToList)
13import qualified CmdLineParser as GHC
13import qualified CmdLineParser as GHC
14import Control.Exception
14import Control.Exception
15+import Control.Monad
15import Control.Monad.IO.Class
16import Control.Monad.IO.Class
16import qualified Data.List as L
17import qualified Data.List as L
17import qualified Data.List.NonEmpty as NE
18import qualified Data.List.NonEmpty as NE
18import Data.Ord (Down (Down))
19import Data.Ord (Down (Down))
19−import qualified Data.Text as T
20import DynFlags as GHC
20import DynFlags as GHC
21import ErrUtils (Severity (..), errMsgSeverity, errMsgSpan)
21import ErrUtils (Severity (..), errMsgSeverity, errMsgSpan)
22import qualified FastString as GHC
22import qualified FastString as GHC
@@ -32,7 +32,6 @@ import Ormolu.Parser.Anns
32import Ormolu.Parser.CommentStream
32import Ormolu.Parser.CommentStream
33import Ormolu.Parser.Result
33import Ormolu.Parser.Result
34import Ormolu.Processing.Preprocess (preprocess)
34import Ormolu.Processing.Preprocess (preprocess)
35−import Ormolu.Utils (incSpanLine, removeIndentation)
36import qualified Panic as GHC
35import qualified Panic as GHC
37import qualified Parser as GHC
36import qualified Parser as GHC
38import qualified StringBuffer as GHC
37import qualified StringBuffer as GHC
@@ -41,7 +40,7 @@ import qualified StringBuffer as GHC
41parseModule ::
40parseModule ::
42 MonadIO m =>
41 MonadIO m =>
43 -- | Ormolu configuration
42 -- | Ormolu configuration
44− Config RegionDeltas ->
43+ Config ->
45 -- | File name (only for source location annotations)
44 -- | File name (only for source location annotations)
46 FilePath ->
45 FilePath ->
47 -- | Input for parser
46 -- | Input for parser
@@ -50,10 +49,8 @@ parseModule ::
50 ( [GHC.Warn],
49 ( [GHC.Warn],
51 Either (SrcSpan, String) ParseResult
50 Either (SrcSpan, String) ParseResult
52 )
51 )
53−parseModule Config {..} path rawInput = liftIO $ do
52+parseModule Config {..} path input' = liftIO $ do
54− let (literalPrefix, indentedInput, literalSuffix, extraComments) =
53+ let (input, extraComments) = preprocess path input'
55− preprocess path rawInput cfgRegion
56− (input, indent) = removeIndentation indentedInput
57 -- It's important that 'setDefaultExts' is done before
54 -- It's important that 'setDefaultExts' is done before
58 -- 'parsePragmasIntoDynFlags', because otherwise we might enable an
55 -- 'parsePragmasIntoDynFlags', because otherwise we might enable an
59 -- extension that was explicitly disabled in the file.
56 -- extension that was explicitly disabled in the file.
@@ -63,7 +60,7 @@ parseModule Config {..} path rawInput = liftIO $ do
63 (setDefaultExts baseDynFlags)
60 (setDefaultExts baseDynFlags)
64 extraOpts = dynOptionToLocatedStr <$> cfgDynOptions
61 extraOpts = dynOptionToLocatedStr <$> cfgDynOptions
65 (warnings, dynFlags) <-
62 (warnings, dynFlags) <-
66− parsePragmasIntoDynFlags baseFlags extraOpts path rawInput >>= \case
63+ parsePragmasIntoDynFlags baseFlags extraOpts path input' >>= \case
67 Right res -> pure res
64 Right res -> pure res
68 Left err ->
65 Left err ->
69 let loc =
66 let loc =
@@ -71,6 +68,8 @@ parseModule Config {..} path rawInput = liftIO $ do
71 (mkSrcLoc (GHC.mkFastString path) 1 1)
68 (mkSrcLoc (GHC.mkFastString path) 1 1)
72 (mkSrcLoc (GHC.mkFastString path) 1 1)
69 (mkSrcLoc (GHC.mkFastString path) 1 1)
73 in throwIO (OrmoluParsingFailed loc err)
70 in throwIO (OrmoluParsingFailed loc err)
71+ when (GHC.xopt Cpp dynFlags && not cfgTolerateCpp) $
72+ throwIO (OrmoluCppEnabled path)
74 let useRecordDot =
73 let useRecordDot =
75 "record-dot-preprocessor" == pgm_F dynFlags
74 "record-dot-preprocessor" == pgm_F dynFlags
76 || any
75 || any
@@ -78,18 +77,15 @@ parseModule Config {..} path rawInput = liftIO $ do
78 (pluginModNames dynFlags)
77 (pluginModNames dynFlags)
79 pStateErrors = \pstate ->
78 pStateErrors = \pstate ->
80 let errs = bagToList $ GHC.getErrorMessages pstate dynFlags
79 let errs = bagToList $ GHC.getErrorMessages pstate dynFlags
81− fixupErrSpan = incSpanLine (regionPrefixLength cfgRegion)
82 in case L.sortOn (Down . SeverityOrd . errMsgSeverity) errs of
80 in case L.sortOn (Down . SeverityOrd . errMsgSeverity) errs of
83 [] -> Nothing
81 [] -> Nothing
84− err : _ ->
85− -- Show instance returns a short error message
82+ err : _ -> Just (errMsgSpan err, show err) -- Show instance returns a short error message
86− Just (fixupErrSpan (errMsgSpan err), show err)
87 r = case runParser GHC.parseModule dynFlags path input of
83 r = case runParser GHC.parseModule dynFlags path input of
88 GHC.PFailed pstate ->
84 GHC.PFailed pstate ->
89 case pStateErrors pstate of
85 case pStateErrors pstate of
90 Just err -> Left err
86 Just err -> Left err
91− Nothing -> error "PFailed does not have an error"
87+ Nothing -> error "invariant violation: PFailed does not have an error"
92− GHC.POk pstate (L _ hsModule) ->
88+ GHC.POk pstate pmod ->
93 case pStateErrors pstate of
89 case pStateErrors pstate of
94 -- Some parse errors (pattern/arrow syntax in expr context)
90 -- Some parse errors (pattern/arrow syntax in expr context)
95 -- do not cause a parse error, but they are replaced with "_"
91 -- do not cause a parse error, but they are replaced with "_"
@@ -98,10 +94,10 @@ parseModule Config {..} path rawInput = liftIO $ do
98 Just err -> Left err
94 Just err -> Left err
99 Nothing ->
95 Nothing ->
100 let (stackHeader, shebangs, pragmas, comments) =
96 let (stackHeader, shebangs, pragmas, comments) =
101− mkCommentStream input extraComments pstate
97+ mkCommentStream extraComments pstate
102 in Right
98 in Right
103 ParseResult
99 ParseResult
104− { prParsedSource = hsModule,
100+ { prParsedSource = pmod,
105 prAnns = mkAnns pstate,
101 prAnns = mkAnns pstate,
106 prStackHeader = stackHeader,
102 prStackHeader = stackHeader,
107 prShebangs = shebangs,
103 prShebangs = shebangs,
@@ -109,10 +105,7 @@ parseModule Config {..} path rawInput = liftIO $ do
109 prCommentStream = comments,
105 prCommentStream = comments,
110 prUseRecordDot = useRecordDot,
106 prUseRecordDot = useRecordDot,
111 prImportQualifiedPost =
107 prImportQualifiedPost =
112− GHC.xopt ImportQualifiedPost dynFlags,
108+ GHC.xopt ImportQualifiedPost dynFlags
113− prLiteralPrefix = T.pack literalPrefix,
114− prLiteralSuffix = T.pack literalSuffix,
115− prIndent = indent
116 }
109 }
117 return (warnings, r)
110 return (warnings, r)
118
111
src/Ormolu/Parser/CommentStream.hs+60−126
@@ -4,16 +4,12 @@
4
4
5-- | Functions for working with comment stream.
5-- | Functions for working with comment stream.
6module Ormolu.Parser.CommentStream
6module Ormolu.Parser.CommentStream
7− ( -- * Comment stream
8− CommentStream (..),
7+ ( CommentStream (..),
9− mkCommentStream,
10− showCommentStream,
11−
12− -- * Comment
13 Comment (..),
8 Comment (..),
14− unComment,
9+ mkCommentStream,
15− hasAtomsBefore,
10+ isPrevHaddock,
16 isMultilineComment,
11 isMultilineComment,
12+ showCommentStream,
17 )
13 )
18where
14where
19
15
@@ -27,24 +23,23 @@ import qualified GHC
27import qualified Lexer as GHC
23import qualified Lexer as GHC
28import Ormolu.Parser.Pragma
24import Ormolu.Parser.Pragma
29import Ormolu.Parser.Shebang
25import Ormolu.Parser.Shebang
30−import Ormolu.Processing.Common
31−import Ormolu.Utils (onTheSameLine, showOutputable)
26+import Ormolu.Utils (showOutputable)
32import SrcLoc
27import SrcLoc
33
28
34−----------------------------------------------------------------------------
35−-- Comment stream
36−
37-- | A stream of 'RealLocated' 'Comment's in ascending order with respect to
29-- | A stream of 'RealLocated' 'Comment's in ascending order with respect to
38-- beginning of corresponding spans.
30-- beginning of corresponding spans.
39newtype CommentStream = CommentStream [RealLocated Comment]
31newtype CommentStream = CommentStream [RealLocated Comment]
40 deriving (Eq, Data, Semigroup, Monoid)
32 deriving (Eq, Data, Semigroup, Monoid)
41
33
34+-- | A wrapper for a single comment. The 'NonEmpty' list inside contains
35+-- lines of multiline comment @{- … -}@ or just single item\/line otherwise.
36+newtype Comment = Comment (NonEmpty String)
37+ deriving (Eq, Show, Data)
38+
42-- | Create 'CommentStream' from 'GHC.PState'. The pragmas and shebangs are
39-- | Create 'CommentStream' from 'GHC.PState'. The pragmas and shebangs are
43-- removed from the 'CommentStream'. Shebangs are only extracted from the
40-- removed from the 'CommentStream'. Shebangs are only extracted from the
44-- comments that come from the first argument.
41-- comments that come from the first argument.
45mkCommentStream ::
42mkCommentStream ::
46− -- | Original input
47− String ->
48 -- | Extra comments to include
43 -- | Extra comments to include
49 [Located String] ->
44 [Located String] ->
50 -- | Parser state to use for comment extraction
45 -- | Parser state to use for comment extraction
@@ -55,14 +50,14 @@ mkCommentStream ::
55 [([RealLocated Comment], Pragma)],
50 [([RealLocated Comment], Pragma)],
56 CommentStream
51 CommentStream
57 )
52 )
58−mkCommentStream input extraComments pstate =
53+mkCommentStream extraComments pstate =
59 ( mstackHeader,
54 ( mstackHeader,
60 shebangs,
55 shebangs,
61 pragmas,
56 pragmas,
62 CommentStream comments
57 CommentStream comments
63 )
58 )
64 where
59 where
65− (comments, pragmas) = extractPragmas input rawComments1
60+ (comments, pragmas) = extractPragmas rawComments1
66 (rawComments1, mstackHeader) = extractStackHeader rawComments0
61 (rawComments1, mstackHeader) = extractStackHeader rawComments0
67 rawComments0 =
62 rawComments0 =
68 L.sortOn (realSrcSpanStart . getRealSrcSpan) . mapMaybe toRealSpan $
63 L.sortOn (realSrcSpanStart . getRealSrcSpan) . mapMaybe toRealSpan $
@@ -73,6 +68,15 @@ mkCommentStream input extraComments pstate =
73 (GHC.annotations_comments pstate)
68 (GHC.annotations_comments pstate)
74 (shebangs, otherExtraComments) = extractShebangs extraComments
69 (shebangs, otherExtraComments) = extractShebangs extraComments
75
70
71+-- | Test whether a 'Comment' looks like a Haddock following a definition,
72+-- i.e. something starting with @-- ^@.
73+isPrevHaddock :: Comment -> Bool
74+isPrevHaddock (Comment (x :| _)) = "-- ^" `L.isPrefixOf` x
75+
76+-- | Is this comment multiline-style?
77+isMultilineComment :: Comment -> Bool
78+isMultilineComment (Comment (x :| _)) = "{-" `L.isPrefixOf` x
79+
76-- | Pretty-print a 'CommentStream'.
80-- | Pretty-print a 'CommentStream'.
77showCommentStream :: CommentStream -> String
81showCommentStream :: CommentStream -> String
78showCommentStream (CommentStream xs) =
82showCommentStream (CommentStream xs) =
@@ -82,145 +86,75 @@ showCommentStream (CommentStream xs) =
82 showComment (GHC.L l str) = showOutputable l ++ " " ++ show str
86 showComment (GHC.L l str) = showOutputable l ++ " " ++ show str
83
87
84----------------------------------------------------------------------------
88----------------------------------------------------------------------------
85−-- Comment
89+-- Helpers
86−
87−-- | A wrapper for a single comment. The 'Bool' indicates whether there were
88−-- atoms before beginning of the comment in the original input. The
89−-- 'NonEmpty' list inside contains lines of multiline comment @{- … -}@ or
90−-- just single item\/line otherwise.
91−data Comment = Comment Bool (NonEmpty String)
92− deriving (Eq, Show, Data)
93
90
94-- | Normalize comment string. Sometimes one multi-line comment is turned
91-- | Normalize comment string. Sometimes one multi-line comment is turned
95-- into several lines for subsequent outputting with correct indentation for
92-- into several lines for subsequent outputting with correct indentation for
96-- each line.
93-- each line.
97−mkComment ::
94+mkComment :: RealLocated String -> RealLocated Comment
98− -- | Lines of original input with their indices
95+mkComment (L l s) =
99− [(Int, String)] ->
96+ L l . Comment . fmap dropTrailing $
100− -- | Raw comment string
97+ if "{-" `L.isPrefixOf` s
101− RealLocated String ->
98+ then case NE.nonEmpty (lines s) of
102− -- | Remaining lines of original input and the constructed 'Comment'
99+ Nothing -> s :| []
103− ([(Int, String)], RealLocated Comment)
100+ Just (x :| xs) ->
104−mkComment ls (L l s) = (ls', comment)
101+ let getIndent y =
102+ if all isSpace y
103+ then startIndent
104+ else length (takeWhile isSpace y)
105+ n = minimum (startIndent : fmap getIndent xs)
106+ in x :| (drop n <$> xs)
107+ else s :| []
105 where
108 where
106− comment =
107− L l . Comment atomsBefore . removeConseqBlanks . fmap dropTrailing $
108− if "{-" `L.isPrefixOf` s
109− then case NE.nonEmpty (lines s) of
110− Nothing -> s :| []
111− Just (x :| xs) ->
112− let getIndent y =
113− if all isSpace y || y == endDisabling
114− then startIndent
115− else length (takeWhile isSpace y)
116− n = minimum (startIndent : fmap getIndent xs)
117− removeIndent y =
118− if y == endDisabling
119− then y
120− else drop n y
121− in x :| (removeIndent <$> xs)
122− else s :| []
123− (atomsBefore, ls') =
124− case dropWhile ((< commentLine) . fst) ls of
125− [] -> (False, [])
126− ((_, i) : ls'') ->
127− case take 2 (dropWhile isSpace i) of
128− "--" -> (False, ls'')
129− "{-" -> (False, ls'')
130− _ -> (True, ls'')
131 dropTrailing = L.dropWhileEnd isSpace
109 dropTrailing = L.dropWhileEnd isSpace
132 startIndent = srcSpanStartCol l - 1
110 startIndent = srcSpanStartCol l - 1
133− commentLine = srcSpanStartLine l
134−
135−-- | Get a collection of lines from a 'Comment'.
136−unComment :: Comment -> NonEmpty String
137−unComment (Comment _ xs) = xs
138
111
139−-- | Check whether the 'Comment' had some non-whitespace atoms in front of
112+-- | Get a 'String' from 'GHC.AnnotationComment'.
140−-- it in the original input.
113+unAnnotationComment :: GHC.AnnotationComment -> Maybe String
141−hasAtomsBefore :: Comment -> Bool
114+unAnnotationComment = \case
142−hasAtomsBefore (Comment atomsBefore _) = atomsBefore
115+ GHC.AnnDocCommentNext _ -> Nothing -- @-- |@
116+ GHC.AnnDocCommentPrev _ -> Nothing -- @-- ^@
117+ GHC.AnnDocCommentNamed _ -> Nothing -- @-- $@
118+ GHC.AnnDocSection _ _ -> Nothing -- @-- *@
119+ GHC.AnnDocOptions s -> Just s
120+ GHC.AnnLineComment s -> Just s
121+ GHC.AnnBlockComment s -> Just s
143
122
144−-- | Is this comment multiline-style?
123+liftMaybe :: Located (Maybe a) -> Maybe (Located a)
145−isMultilineComment :: Comment -> Bool
124+liftMaybe = \case
146−isMultilineComment (Comment _ (x :| _)) = "{-" `L.isPrefixOf` x
125+ L _ Nothing -> Nothing
126+ L l (Just a) -> Just (L l a)
147
127
148−----------------------------------------------------------------------------
128+toRealSpan :: Located a -> Maybe (RealLocated a)
149−-- Helpers
129+toRealSpan (L (RealSrcSpan l) a) = Just (L l a)
130+toRealSpan _ = Nothing
150
131
151-- | Detect and extract stack header if it is present.
132-- | Detect and extract stack header if it is present.
152extractStackHeader ::
133extractStackHeader ::
153− -- | Comment stream to analyze
154 [RealLocated String] ->
134 [RealLocated String] ->
155 ([RealLocated String], Maybe (RealLocated Comment))
135 ([RealLocated String], Maybe (RealLocated Comment))
156extractStackHeader = \case
136extractStackHeader = \case
157 [] -> ([], Nothing)
137 [] -> ([], Nothing)
158 (x : xs) ->
138 (x : xs) ->
159− let comment = snd (mkComment [] x)
139+ let comment = mkComment x
160 in if isStackHeader (unRealSrcSpan comment)
140 in if isStackHeader (unRealSrcSpan comment)
161 then (xs, Just comment)
141 then (xs, Just comment)
162 else (x : xs, Nothing)
142 else (x : xs, Nothing)
163 where
143 where
164− isStackHeader (Comment _ (x :| _)) =
144+ isStackHeader (Comment (x :| _)) =
165 "stack" `L.isPrefixOf` dropWhile isSpace (drop 2 x)
145 "stack" `L.isPrefixOf` dropWhile isSpace (drop 2 x)
166
146
167-- | Extract pragmas and their associated comments.
147-- | Extract pragmas and their associated comments.
168extractPragmas ::
148extractPragmas ::
169− -- | Input
170− String ->
171− -- | Comment stream to analyze
172 [RealLocated String] ->
149 [RealLocated String] ->
173 ([RealLocated Comment], [([RealLocated Comment], Pragma)])
150 ([RealLocated Comment], [([RealLocated Comment], Pragma)])
174−extractPragmas input = go initialLs id id
151+extractPragmas = go id id
175 where
152 where
176− initialLs = zip [1 ..] (lines input)
177− go ls csSoFar pragmasSoFar = \case
153+ go csSoFar pragmasSoFar = \case
178 [] -> (csSoFar [], pragmasSoFar [])
154 [] -> (csSoFar [], pragmasSoFar [])
179 (x : xs) ->
155 (x : xs) ->
180 case parsePragma (unRealSrcSpan x) of
156 case parsePragma (unRealSrcSpan x) of
181− Nothing ->
182− let (ls', x') = mkComment ls x
183− in go ls' (csSoFar . (x' :)) pragmasSoFar xs
157+ Nothing -> go (csSoFar . (mkComment x :)) pragmasSoFar xs
184 Just pragma ->
158 Just pragma ->
185− let combined ys = (csSoFar ys, pragma)
159+ let combined = (csSoFar [], pragma)
186− go' ls' ys rest = go ls' id (pragmasSoFar . (combined ys :)) rest
160+ in go id (pragmasSoFar . (combined :)) xs
187− in case xs of
188− [] -> go' ls [] xs
189− (y : ys) ->
190− let (ls', y') = mkComment ls y
191− in if onTheSameLine
192− (RealSrcSpan (getRealSrcSpan x))
193− (RealSrcSpan (getRealSrcSpan y))
194− then go' ls' [y'] ys
195− else go' ls [] xs
196−
197−-- | Get a 'String' from 'GHC.AnnotationComment'.
198−unAnnotationComment :: GHC.AnnotationComment -> Maybe String
199−unAnnotationComment = \case
200− GHC.AnnDocCommentNext _ -> Nothing -- @-- |@
201− GHC.AnnDocCommentPrev _ -> Nothing -- @-- ^@
202− GHC.AnnDocCommentNamed _ -> Nothing -- @-- $@
203− GHC.AnnDocSection _ _ -> Nothing -- @-- *@
204− GHC.AnnDocOptions s -> Just s
205− GHC.AnnLineComment s -> Just s
206− GHC.AnnBlockComment s -> Just s
207−
208−liftMaybe :: Located (Maybe a) -> Maybe (Located a)
209−liftMaybe = \case
210− L _ Nothing -> Nothing
211− L l (Just a) -> Just (L l a)
212−
213−toRealSpan :: Located a -> Maybe (RealLocated a)
214−toRealSpan (L (RealSrcSpan l) a) = Just (L l a)
215−toRealSpan _ = Nothing
216−
217−-- | Remove consecutive blank lines.
218−removeConseqBlanks :: NonEmpty String -> NonEmpty String
219−removeConseqBlanks (x :| xs) = x :| go (null x) id xs
220− where
221− go seenBlank acc = \case
222− [] -> acc []
223− (y : ys) ->
224− if seenBlank && null y
225− then go True acc ys
226− else go (null y) (acc . (y :)) ys
src/Ormolu/Parser/Result.hs+2−9
@@ -7,7 +7,6 @@ module Ormolu.Parser.Result
7 )
7 )
8where
8where
9
9
10−import Data.Text (Text)
11import GHC
10import GHC
12import Ormolu.Parser.Anns
11import Ormolu.Parser.Anns
13import Ormolu.Parser.CommentStream
12import Ormolu.Parser.CommentStream
@@ -17,7 +16,7 @@ import Ormolu.Parser.Shebang (Shebang)
17-- | A collection of data that represents a parsed module in Ormolu.
16-- | A collection of data that represents a parsed module in Ormolu.
18data ParseResult = ParseResult
17data ParseResult = ParseResult
19 { -- | 'ParsedSource' from GHC
18 { -- | 'ParsedSource' from GHC
20− prParsedSource :: HsModule GhcPs,
19+ prParsedSource :: ParsedSource,
21 -- | Ormolu-specfic representation of annotations
20 -- | Ormolu-specfic representation of annotations
22 prAnns :: Anns,
21 prAnns :: Anns,
23 -- | Stack header
22 -- | Stack header
@@ -31,13 +30,7 @@ data ParseResult = ParseResult
31 -- | Whether or not record dot syntax is enabled
30 -- | Whether or not record dot syntax is enabled
32 prUseRecordDot :: Bool,
31 prUseRecordDot :: Bool,
33 -- | Whether or not ImportQualifiedPost is enabled
32 -- | Whether or not ImportQualifiedPost is enabled
34− prImportQualifiedPost :: Bool,
33+ prImportQualifiedPost :: Bool
35− -- | Literal prefix
36− prLiteralPrefix :: Text,
37− -- | Literal suffix
38− prLiteralSuffix :: Text,
39− -- | Indentation level, can be non-zero in case of region formatting
40− prIndent :: Int
41 }
34 }
42
35
43-- | Pretty-print a 'ParseResult'.
36-- | Pretty-print a 'ParseResult'.
src/Ormolu/Printer.hs+13−16
@@ -20,19 +20,16 @@ printModule ::
20 -- | Resulting rendition
20 -- | Resulting rendition
21 Text
21 Text
22printModule ParseResult {..} =
22printModule ParseResult {..} =
23− prLiteralPrefix <> region <> prLiteralSuffix
24− where
25− region =
26− postprocess prIndent $
23+ postprocess $
27− runR
24+ runR
28− ( p_hsModule
25+ ( p_hsModule
29− prStackHeader
26+ prStackHeader
30− prShebangs
27+ prShebangs
31− prPragmas
28+ prPragmas
32− prImportQualifiedPost
29+ prImportQualifiedPost
33− prParsedSource
30+ prParsedSource
34− )
31+ )
35− (mkSpanStream prParsedSource)
32+ (mkSpanStream prParsedSource)
36− prCommentStream
33+ prCommentStream
37− prAnns
34+ prAnns
38− prUseRecordDot
35+ prUseRecordDot
src/Ormolu/Printer/Combinators.hs+26−34
@@ -21,7 +21,6 @@ module Ormolu.Printer.Combinators
21 space,
21 space,
22 newline,
22 newline,
23 inci,
23 inci,
24− inciIf,
25 located,
24 located,
26 located',
25 located',
27 switchLayout,
26 switchLayout,
@@ -52,8 +51,6 @@ module Ormolu.Printer.Combinators
52
51
53 -- ** Literals
52 -- ** Literals
54 comma,
53 comma,
55− commaDel,
56− equals,
57
54
58 -- ** Stateful markers
55 -- ** Stateful markers
59 SpanMark (..),
56 SpanMark (..),
@@ -65,44 +62,48 @@ module Ormolu.Printer.Combinators
65where
62where
66
63
67import Control.Monad
64import Control.Monad
65+import Data.Data (Data)
68import Data.List (intersperse)
66import Data.List (intersperse)
69import Data.Text (Text)
67import Data.Text (Text)
70import Ormolu.Printer.Comments
68import Ormolu.Printer.Comments
71import Ormolu.Printer.Internal
69import Ormolu.Printer.Internal
70+import Ormolu.Utils (isModule)
72import SrcLoc
71import SrcLoc
73
72
74----------------------------------------------------------------------------
73----------------------------------------------------------------------------
75-- Basic
74-- Basic
76
75
77−-- | Indent the inner expression if the first argument is 'True'.
78−inciIf ::
79− -- | Whether to indent
80− Bool ->
81− -- | The expression to indent
82− R () ->
83− R ()
84−inciIf b m = if b then inci m else m
85−
86-- | Enter a 'Located' entity. This combinator handles outputting comments
76-- | Enter a 'Located' entity. This combinator handles outputting comments
87-- and sets layout (single-line vs multi-line) for the inner computation.
77-- and sets layout (single-line vs multi-line) for the inner computation.
88-- Roughly, the rule for using 'located' is that every time there is a
78-- Roughly, the rule for using 'located' is that every time there is a
89-- 'Located' wrapper, it should be “discharged” with a corresponding
79-- 'Located' wrapper, it should be “discharged” with a corresponding
90-- 'located' invocation.
80-- 'located' invocation.
91located ::
81located ::
82+ Data a =>
92 -- | Thing to enter
83 -- | Thing to enter
93 Located a ->
84 Located a ->
94 -- | How to render inner value
85 -- | How to render inner value
95 (a -> R ()) ->
86 (a -> R ()) ->
96 R ()
87 R ()
97−located (L (UnhelpfulSpan _) a) f = f a
88+located loc f = do
98−located (L (RealSrcSpan l) a) f = do
89+ let withRealLocated (L l a) g =
90+ case l of
91+ UnhelpfulSpan _ -> return ()
92+ RealSrcSpan l' -> g (L l' a)
99− spitPrecedingComments l
93+ withRealLocated loc spitPrecedingComments
94+ let setEnclosingSpan =
95+ case getLoc loc of
96+ UnhelpfulSpan _ -> id
97+ RealSrcSpan orf ->
98+ if isModule (unLoc loc)
99+ then id
100− withEnclosingSpan l $
100+ else withEnclosingSpan orf
101− switchLayout [RealSrcSpan l] (f a)
101+ setEnclosingSpan $ switchLayout [getLoc loc] (f (unLoc loc))
102− spitFollowingComments l
102+ withRealLocated loc spitFollowingComments
103
103
104-- | A version of 'located' with arguments flipped.
104-- | A version of 'located' with arguments flipped.
105located' ::
105located' ::
106+ Data a =>
106 -- | How to render inner value
107 -- | How to render inner value
107 (a -> R ()) ->
108 (a -> R ()) ->
108 -- | Thing to enter
109 -- | Thing to enter
@@ -185,12 +186,10 @@ sepSemi f xs = vlayout singleLine multiLine
185 xs' ->
186 xs' ->
186 if ub
187 if ub
187 then do
188 then do
188− txt "{"
189+ txt "{ "
189− space
190− sep (txt ";" >> space) (dontUseBraces . f) xs'
190+ sep (txt "; ") (dontUseBraces . f) xs'
191− space
192− txt "}"
191+ txt " }"
193− else sep (txt ";" >> space) f xs'
192+ else sep (txt "; ") f xs'
194 multiLine =
193 multiLine =
195 sep newline (dontUseBraces . f) xs
194 sep newline (dontUseBraces . f) xs
196
195
@@ -203,7 +202,6 @@ data BracketStyle
203 N
202 N
204 | -- | Shifted one level
203 | -- | Shifted one level
205 S
204 S
206− deriving (Eq, Show)
207
205
208-- | Surround given entity by backticks.
206-- | Surround given entity by backticks.
209backticks :: R () -> R ()
207backticks :: R () -> R ()
@@ -280,7 +278,9 @@ brackets_ needBreaks open close style m = sitcc (vlayout singleLine multiLine)
280 then newline >> inci m
278 then newline >> inci m
281 else space >> sitcc m
279 else space >> sitcc m
282 newline
280 newline
281+ case style of
282+ N -> txt close
283− inciIf (style == S) (txt close)
283+ S -> inci (txt close)
284
284
285----------------------------------------------------------------------------
285----------------------------------------------------------------------------
286-- Literals
286-- Literals
@@ -288,11 +288,3 @@ brackets_ needBreaks open close style m = sitcc (vlayout singleLine multiLine)
288-- | Print @,@.
288-- | Print @,@.
289comma :: R ()
289comma :: R ()
290comma = txt ","
290comma = txt ","
291−
292−-- | Delimiting combination with 'comma'. To be used with 'sep'.
293−commaDel :: R ()
294−commaDel = comma >> breakpoint
295−
296−-- | Print @=@. Do not use @'txt' "="@.
297−equals :: R ()
298−equals = interferingTxt "="
src/Ormolu/Printer/Comments.hs+52−46
@@ -13,11 +13,13 @@ module Ormolu.Printer.Comments
13where
13where
14
14
15import Control.Monad
15import Control.Monad
16+import Data.Coerce (coerce)
17+import Data.Data (Data)
16import qualified Data.List.NonEmpty as NE
18import qualified Data.List.NonEmpty as NE
17−import Data.Maybe (listToMaybe)
18import qualified Data.Text as T
19import qualified Data.Text as T
19import Ormolu.Parser.CommentStream
20import Ormolu.Parser.CommentStream
20import Ormolu.Printer.Internal
21import Ormolu.Printer.Internal
22+import Ormolu.Utils (isModule)
21import SrcLoc
23import SrcLoc
22
24
23----------------------------------------------------------------------------
25----------------------------------------------------------------------------
@@ -25,8 +27,9 @@ import SrcLoc
25
27
26-- | Output all preceding comments for an element at given location.
28-- | Output all preceding comments for an element at given location.
27spitPrecedingComments ::
29spitPrecedingComments ::
30+ Data a =>
28− -- | Span of the element to attach comments to
31+ -- | AST element to attach comments to
29− RealSrcSpan ->
32+ RealLocated a ->
30 R ()
33 R ()
31spitPrecedingComments ref = do
34spitPrecedingComments ref = do
32 gotSome <- handleCommentSeries (spitPrecedingComment ref)
35 gotSome <- handleCommentSeries (spitPrecedingComment ref)
@@ -34,65 +37,70 @@ spitPrecedingComments ref = do
34 lastMark <- getSpanMark
37 lastMark <- getSpanMark
35 -- Insert a blank line between the preceding comments and the thing
38 -- Insert a blank line between the preceding comments and the thing
36 -- after them if there was a blank line in the input.
39 -- after them if there was a blank line in the input.
37− when (needsNewlineBefore ref lastMark) newline
40+ when (needsNewlineBefore (getRealSrcSpan ref) lastMark) newline
38
41
39-- | Output all comments following an element at given location.
42-- | Output all comments following an element at given location.
40spitFollowingComments ::
43spitFollowingComments ::
44+ Data a =>
41− -- | Span of the element to attach comments to
45+ -- | AST element of attach comments to
42− RealSrcSpan ->
46+ RealLocated a ->
43 R ()
47 R ()
44spitFollowingComments ref = do
48spitFollowingComments ref = do
45− trimSpanStream ref
49+ trimSpanStream (getRealSrcSpan ref)
46 void $ handleCommentSeries (spitFollowingComment ref)
50 void $ handleCommentSeries (spitFollowingComment ref)
47
51
48-- | Output all remaining comments in the comment stream.
52-- | Output all remaining comments in the comment stream.
49spitRemainingComments :: R ()
53spitRemainingComments :: R ()
50−spitRemainingComments = do
51− -- Make sure we have a blank a line between the last definition and the
52− -- trailing comments.
53− newline
54− void $ handleCommentSeries spitRemainingComment
54+spitRemainingComments = void $ handleCommentSeries spitRemainingComment
55
55
56----------------------------------------------------------------------------
56----------------------------------------------------------------------------
57-- Single-comment functions
57-- Single-comment functions
58
58
59-- | Output a single preceding comment for an element at given location.
59-- | Output a single preceding comment for an element at given location.
60spitPrecedingComment ::
60spitPrecedingComment ::
61+ Data a =>
61− -- | Span of the element to attach comments to
62+ -- | AST element to attach comments to
62− RealSrcSpan ->
63+ RealLocated a ->
64+ -- | Location of last comment in the series
65+ Maybe SpanMark ->
63 -- | Are we done?
66 -- | Are we done?
64 R Bool
67 R Bool
65−spitPrecedingComment ref = do
68+spitPrecedingComment (L ref a) mlastMark = do
66− mlastMark <- getSpanMark
67 let p (L l _) = realSrcSpanEnd l <= realSrcSpanStart ref
69 let p (L l _) = realSrcSpanEnd l <= realSrcSpanStart ref
68 withPoppedComment p $ \l comment -> do
70 withPoppedComment p $ \l comment -> do
69− lineSpans <- thisLineSpans
71+ dirtyLine <-
70− let thisCommentLine = srcLocLine (realSrcSpanStart l)
72+ case mlastMark of
71− needsNewline =
73+ -- When the current line is dirty it means that something that can
72− case listToMaybe lineSpans of
74+ -- have comments attached to it is already on the line. To avoid
73− Nothing -> False
75+ -- problems with idempotence we cannot output the first comment
74− Just spn -> srcLocLine (realSrcSpanEnd spn) /= thisCommentLine
76+ -- immediately because it'll be attached to the previous element (on
77+ -- the same line) on the next run, so we play safe here and output
78+ -- an extra 'newline' in this case.
79+ Nothing -> isLineDirty -- only for very first preceding comment
80+ Just _ -> return False
75− when (needsNewline || needsNewlineBefore l mlastMark) newline
81+ when (dirtyLine || needsNewlineBefore l mlastMark) newline
76 spitCommentNow l comment
82 spitCommentNow l comment
77− if theSameLinePre l ref
83+ if theSameLinePre l ref && not (isModule a)
78 then space
84 then space
79 else newline
85 else newline
80
86
81-- | Output a comment that follows element at given location immediately on
87-- | Output a comment that follows element at given location immediately on
82-- the same line, if there is any.
88-- the same line, if there is any.
83spitFollowingComment ::
89spitFollowingComment ::
90+ Data a =>
84 -- | AST element to attach comments to
91 -- | AST element to attach comments to
85− RealSrcSpan ->
92+ RealLocated a ->
93+ -- | Location of last comment in the series
94+ Maybe SpanMark ->
86 -- | Are we done?
95 -- | Are we done?
87 R Bool
96 R Bool
88−spitFollowingComment ref = do
97+spitFollowingComment (L ref a) mlastMark = do
89− mlastMark <- getSpanMark
90 mnSpn <- nextEltSpan
98 mnSpn <- nextEltSpan
91 -- Get first enclosing span that is not equal to reference span, i.e. it's
99 -- Get first enclosing span that is not equal to reference span, i.e. it's
92 -- truly something enclosing the AST element.
100 -- truly something enclosing the AST element.
93 meSpn <- getEnclosingSpan (/= ref)
101 meSpn <- getEnclosingSpan (/= ref)
94 withPoppedComment (commentFollowsElt ref mnSpn meSpn mlastMark) $ \l comment ->
102 withPoppedComment (commentFollowsElt ref mnSpn meSpn mlastMark) $ \l comment ->
95− if theSameLinePost l ref
103+ if theSameLinePost l ref && not (isModule a)
96 then
104 then
97 if isMultilineComment comment
105 if isMultilineComment comment
98 then space >> spitCommentNow l comment
106 then space >> spitCommentNow l comment
@@ -104,10 +112,11 @@ spitFollowingComment ref = do
104
112
105-- | Output a single remaining comment from the comment stream.
113-- | Output a single remaining comment from the comment stream.
106spitRemainingComment ::
114spitRemainingComment ::
115+ -- | Location of last comment in the series
116+ Maybe SpanMark ->
107 -- | Are we done?
117 -- | Are we done?
108 R Bool
118 R Bool
109−spitRemainingComment = do
119+spitRemainingComment mlastMark =
110− mlastMark <- getSpanMark
111 withPoppedComment (const True) $ \l comment -> do
120 withPoppedComment (const True) $ \l comment -> do
112 when (needsNewlineBefore l mlastMark) newline
121 when (needsNewlineBefore l mlastMark) newline
113 spitCommentNow l comment
122 spitCommentNow l comment
@@ -120,13 +129,13 @@ spitRemainingComment = do
120handleCommentSeries ::
129handleCommentSeries ::
121 -- | Given location of previous comment, output the next comment
130 -- | Given location of previous comment, output the next comment
122 -- returning 'True' if we're done
131 -- returning 'True' if we're done
123− R Bool ->
132+ (Maybe SpanMark -> R Bool) ->
124 -- | Whether we printed any comments
133 -- | Whether we printed any comments
125 R Bool
134 R Bool
126handleCommentSeries f = go False
135handleCommentSeries f = go False
127 where
136 where
128 go gotSome = do
137 go gotSome = do
129− done <- f
138+ done <- getSpanMark >>= f
130 if done
139 if done
131 then return gotSome
140 then return gotSome
132 else go True
141 else go True
@@ -154,7 +163,6 @@ needsNewlineBefore ::
154 -- | Last printed comment span
163 -- | Last printed comment span
155 Maybe SpanMark ->
164 Maybe SpanMark ->
156 Bool
165 Bool
157−needsNewlineBefore _ (Just (HaddockSpan _ _)) = True
158needsNewlineBefore l mlastMark =
166needsNewlineBefore l mlastMark =
159 case spanMarkSpan <$> mlastMark of
167 case spanMarkSpan <$> mlastMark of
160 Nothing -> False
168 Nothing -> False
@@ -207,8 +215,9 @@ commentFollowsElt ref mnSpn meSpn mlastMark (L l comment) =
207 -- 2) The comment logically belongs to the element, four cases:
215 -- 2) The comment logically belongs to the element, four cases:
208 logicallyFollows =
216 logicallyFollows =
209 theSameLinePost l ref -- a) it's on the same line
217 theSameLinePost l ref -- a) it's on the same line
218+ || isPrevHaddock comment -- b) it's a Haddock string starting with -- ^
210− || continuation -- b) it's a continuation of a comment block
219+ || continuation -- c) it's a continuation of a comment block
211− || lastInEnclosing -- c) it's the last element in the enclosing construct
220+ || lastInEnclosing -- d) it's the last element in the enclosing construct
212
221
213 -- 3) There is no other AST element between this element and the comment:
222 -- 3) There is no other AST element between this element and the comment:
214 noEltBetween =
223 noEltBetween =
@@ -235,15 +244,12 @@ commentFollowsElt ref mnSpn meSpn mlastMark (L l comment) =
235 >= abs (startColumn ref - startColumn l)
244 >= abs (startColumn ref - startColumn l)
236 )
245 )
237 continuation =
246 continuation =
238− -- A comment is a continuation when it doesn't have non-whitespace
239− -- lexemes in front of it and goes right after the previous comment.
240− not (hasAtomsBefore comment)
241− && ( case mlastMark of
247+ case mlastMark of
242− Just (HaddockSpan _ _) -> False
248+ Just (HaddockSpan _ spn) ->
249+ srcSpanEndLine spn + 1 == srcSpanStartLine l
243− Just (CommentSpan spn) ->
250+ Just (CommentSpan spn) ->
244− srcSpanEndLine spn + 1 == srcSpanStartLine l
251+ srcSpanEndLine spn + 1 == srcSpanStartLine l
245− _ -> False
252+ _ -> False
246− )
247 lastInEnclosing =
253 lastInEnclosing =
248 case meSpn of
254 case meSpn of
249 -- When there is no enclosing element, return false
255 -- When there is no enclosing element, return false
@@ -265,7 +271,7 @@ spitCommentNow spn comment = do
265 . sequence_
271 . sequence_
266 . NE.intersperse newline
272 . NE.intersperse newline
267 . fmap (txt . T.pack)
273 . fmap (txt . T.pack)
268− . unComment
274+ . coerce
269 $ comment
275 $ comment
270 setSpanMark (CommentSpan spn)
276 setSpanMark (CommentSpan spn)
271
277
@@ -281,6 +287,6 @@ spitCommentPending position spn comment = do
281 . sequence_
287 . sequence_
282 . NE.toList
288 . NE.toList
283 . fmap (registerPendingCommentLine position . T.pack)
289 . fmap (registerPendingCommentLine position . T.pack)
284− . unComment
290+ . coerce
285 $ comment
291 $ comment
286 setSpanMark (CommentSpan spn)
292 setSpanMark (CommentSpan spn)
src/Ormolu/Printer/Internal.hs+52−85
@@ -14,10 +14,10 @@ module Ormolu.Printer.Internal
14
14
15 -- * Internal functions
15 -- * Internal functions
16 txt,
16 txt,
17− interferingTxt,
18 atom,
17 atom,
19 space,
18 space,
20 newline,
19 newline,
20+ isLineDirty,
21 useRecordDot,
21 useRecordDot,
22 inci,
22 inci,
23 sitcc,
23 sitcc,
@@ -39,7 +39,6 @@ module Ormolu.Printer.Internal
39 popComment,
39 popComment,
40 getEnclosingSpan,
40 getEnclosingSpan,
41 withEnclosingSpan,
41 withEnclosingSpan,
42− thisLineSpans,
43
42
44 -- * Stateful markers
43 -- * Stateful markers
45 SpanMark (..),
44 SpanMark (..),
@@ -99,19 +98,18 @@ data RC = RC
99data SC = SC
98data SC = SC
100 { -- | Index of the next column to render
99 { -- | Index of the next column to render
101 scColumn :: !Int,
100 scColumn :: !Int,
102− -- | Indentation level that was used for the current line
103− scIndent :: !Int,
104 -- | Rendered source code so far
101 -- | Rendered source code so far
105 scBuilder :: Builder,
102 scBuilder :: Builder,
106 -- | Span stream
103 -- | Span stream
107 scSpanStream :: SpanStream,
104 scSpanStream :: SpanStream,
108− -- | Spans of atoms that have been printed on the current line so far
109− scThisLineSpans :: [RealSrcSpan],
110 -- | Comment stream
105 -- | Comment stream
111 scCommentStream :: CommentStream,
106 scCommentStream :: CommentStream,
112 -- | Pending comment lines (in reverse order) to be inserted before next
107 -- | Pending comment lines (in reverse order) to be inserted before next
113 -- newline, 'Int' is the indentation level
108 -- newline, 'Int' is the indentation level
114− scPendingComments :: ![(CommentPosition, Text)],
109+ scPendingComments :: ![(CommentPosition, Int, Text)],
110+ -- | Whether the current line is “dirty”, that is, already contains
111+ -- atoms that can have comments attached to them
112+ scDirtyLine :: !Bool,
115 -- | Whether to output a space before the next output
113 -- | Whether to output a space before the next output
116 scRequestedDelimiter :: !RequestedDelimiter,
114 scRequestedDelimiter :: !RequestedDelimiter,
117 -- | An auxiliary marker for keeping track of last output element
115 -- | An auxiliary marker for keeping track of last output element
@@ -177,12 +175,11 @@ runR (R m) sstream cstream anns recDot =
177 sc =
175 sc =
178 SC
176 SC
179 { scColumn = 0,
177 { scColumn = 0,
180− scIndent = 0,
181 scBuilder = mempty,
178 scBuilder = mempty,
182 scSpanStream = sstream,
179 scSpanStream = sstream,
183− scThisLineSpans = [],
184 scCommentStream = cstream,
180 scCommentStream = cstream,
185 scPendingComments = [],
181 scPendingComments = [],
182+ scDirtyLine = False,
186 scRequestedDelimiter = VeryBeginning,
183 scRequestedDelimiter = VeryBeginning,
187 scSpanMark = Nothing
184 scSpanMark = Nothing
188 }
185 }
@@ -190,23 +187,6 @@ runR (R m) sstream cstream anns recDot =
190----------------------------------------------------------------------------
187----------------------------------------------------------------------------
191-- Internal functions
188-- Internal functions
192
189
193−-- | Type of the thing to output. Influences the primary low-level rendering
194−-- function 'spit'.
195−data SpitType
196− = -- | Simple opaque text that breaks comment series.
197− SimpleText
198− | -- | Like 'SimpleText', but assume that when this text is inserted it
199− -- will separate an 'Atom' and its pending comments, so insert an extra
200− -- 'newline' in that case to force the pending comments and continue on
201− -- a fresh line.
202− InterferingText
203− | -- | An atom that typically have span information in the AST and can
204− -- have comments attached to it.
205− Atom
206− | -- | Used for rendering comment lines.
207− CommentPart
208− deriving (Show, Eq)
209−
210-- | Output a fixed 'Text' fragment. The argument may not contain any line
190-- | Output a fixed 'Text' fragment. The argument may not contain any line
211-- breaks. 'txt' is used to output all sorts of “fixed” bits of syntax like
191-- breaks. 'txt' is used to output all sorts of “fixed” bits of syntax like
212-- keywords and pipes @|@ in functional dependencies.
192-- keywords and pipes @|@ in functional dependencies.
@@ -218,15 +198,7 @@ txt ::
218 -- | 'Text' to output
198 -- | 'Text' to output
219 Text ->
199 Text ->
220 R ()
200 R ()
221−txt = spit SimpleText
201+txt = spit False False
222−
223−-- | Similar to 'txt' but the text inserted this way is assumed to break the
224−-- “link” between the preceding atom and its pending comments.
225−interferingTxt ::
226− -- | 'Text' to output
227− Text ->
228− R ()
229−interferingTxt = spit InterferingText
230
202
231-- | Output 'Outputable' fragment of AST. This can be used to output numeric
203-- | Output 'Outputable' fragment of AST. This can be used to output numeric
232-- literals and similar. Everything that doesn't have inner structure but
204-- literals and similar. Everything that doesn't have inner structure but
@@ -235,60 +207,47 @@ atom ::
235 Outputable a =>
207 Outputable a =>
236 a ->
208 a ->
237 R ()
209 R ()
238−atom = spit Atom . T.pack . showOutputable
210+atom = spit True False . T.pack . showOutputable
239
211
240-- | Low-level non-public helper to define 'txt' and 'atom'.
212-- | Low-level non-public helper to define 'txt' and 'atom'.
241spit ::
213spit ::
242− -- | Type of the thing to spit
214+ -- | Should we mark the line as dirty?
243− SpitType ->
215+ Bool ->
216+ -- | Used during outputting of pending comments?
217+ Bool ->
244 -- | 'Text' to output
218 -- | 'Text' to output
245 Text ->
219 Text ->
246 R ()
220 R ()
247−spit _ "" = return ()
221+spit dirty printingComments txt' = do
248−spit stype text = do
249 requestedDel <- R (gets scRequestedDelimiter)
222 requestedDel <- R (gets scRequestedDelimiter)
250− pendingComments <- R (gets scPendingComments)
251− when (stype == InterferingText && not (null pendingComments)) newline
252 case requestedDel of
223 case requestedDel of
253 RequestedNewline -> do
224 RequestedNewline -> do
254 R . modify $ \sc ->
225 R . modify $ \sc ->
255 sc
226 sc
256 { scRequestedDelimiter = RequestedNothing
227 { scRequestedDelimiter = RequestedNothing
257 }
228 }
258− case stype of
229+ if printingComments
259− CommentPart -> newlineRaw
230+ then newlineRaw
260− _ -> newline
231+ else newline
261 _ -> return ()
232 _ -> return ()
262 R $ do
233 R $ do
263 i <- asks rcIndent
234 i <- asks rcIndent
264 c <- gets scColumn
235 c <- gets scColumn
265− closestEnclosing <- listToMaybe <$> asks rcEnclosingSpans
236+ let spaces =
266− let indentedTxt = spaces <> text
237+ if c < i
267− spaces = T.replicate spacesN " "
238+ then T.replicate (i - c) " "
268− spacesN =
269− if c == 0
270− then i
271− else bool 0 1 (requestedDel == RequestedSpace)
239+ else bool mempty " " (requestedDel == RequestedSpace)
240+ indentedTxt = spaces <> txt'
272 modify $ \sc ->
241 modify $ \sc ->
273 sc
242 sc
274 { scBuilder = scBuilder sc <> fromText indentedTxt,
243 { scBuilder = scBuilder sc <> fromText indentedTxt,
275 scColumn = scColumn sc + T.length indentedTxt,
244 scColumn = scColumn sc + T.length indentedTxt,
276− scIndent =
245+ scDirtyLine = scDirtyLine sc || dirty,
277− if c == 0
278− then i
279− else scIndent sc,
280− scThisLineSpans =
281− let xs = scThisLineSpans sc
282− in case stype of
283− Atom -> case closestEnclosing of
284− Nothing -> xs
285− Just x -> x : xs
286− _ -> xs,
287 scRequestedDelimiter = RequestedNothing,
246 scRequestedDelimiter = RequestedNothing,
288 scSpanMark =
247 scSpanMark =
289 -- If there are pending comments, do not reset last comment
248 -- If there are pending comments, do not reset last comment
290 -- location.
249 -- location.
291− if (stype == CommentPart) || (not . null . scPendingComments) sc
250+ if printingComments || (not . null . scPendingComments) sc
292 then scSpanMark sc
251 then scSpanMark sc
293 else Nothing
252 else Nothing
294 }
253 }
@@ -320,22 +279,21 @@ space = R . modify $ \sc ->
320-- hard to output more than one blank newline in a row.
279-- hard to output more than one blank newline in a row.
321newline :: R ()
280newline :: R ()
322newline = do
281newline = do
323− indent <- R (gets scIndent)
324 cs <- reverse <$> R (gets scPendingComments)
282 cs <- reverse <$> R (gets scPendingComments)
325 case cs of
283 case cs of
326 [] -> newlineRaw
284 [] -> newlineRaw
327− ((position, _) : _) -> do
285+ ((position, _, _) : _) -> do
328 case position of
286 case position of
329 OnTheSameLine -> space
287 OnTheSameLine -> space
330 OnNextLine -> newlineRaw
288 OnNextLine -> newlineRaw
331− R . forM_ cs $ \(_, text) ->
289+ R . forM_ cs $ \(_, indent, txt') ->
332 let modRC rc =
290 let modRC rc =
333 rc
291 rc
334 { rcIndent = indent
292 { rcIndent = indent
335 }
293 }
336 R m = do
294 R m = do
337− unless (T.null text) $
295+ unless (T.null txt') $
338− spit CommentPart text
296+ spit False True txt'
339 newlineRaw
297 newlineRaw
340 in local modRC m
298 in local modRC m
341 R . modify $ \sc ->
299 R . modify $ \sc ->
@@ -356,8 +314,7 @@ newlineRaw = R . modify $ \sc ->
356 VeryBeginning -> builderSoFar
314 VeryBeginning -> builderSoFar
357 _ -> builderSoFar <> "\n",
315 _ -> builderSoFar <> "\n",
358 scColumn = 0,
316 scColumn = 0,
359− scIndent = 0,
317+ scDirtyLine = False,
360− scThisLineSpans = [],
361 scRequestedDelimiter = case scRequestedDelimiter sc of
318 scRequestedDelimiter = case scRequestedDelimiter sc of
362 AfterNewline -> RequestedNewline
319 AfterNewline -> RequestedNewline
363 RequestedNewline -> RequestedNewline
320 RequestedNewline -> RequestedNewline
@@ -365,9 +322,14 @@ newlineRaw = R . modify $ \sc ->
365 _ -> AfterNewline
322 _ -> AfterNewline
366 }
323 }
367
324
325+-- | Check if the current line is “dirty”, that is, there is something on it
326+-- that can have comments attached to it.
327+isLineDirty :: R Bool
328+isLineDirty = R (gets scDirtyLine)
329+
368-- | Return 'True' if we should print record dot syntax.
330-- | Return 'True' if we should print record dot syntax.
369useRecordDot :: R Bool
331useRecordDot :: R Bool
370−useRecordDot = R (asks rcUseRecDot)
332+useRecordDot = R $ asks rcUseRecDot
371
333
372-- | Increase indentation level by one indentation step for the inner
334-- | Increase indentation level by one indentation step for the inner
373-- computation. 'inci' should be used when a part of code must be more
335-- computation. 'inci' should be used when a part of code must be more
@@ -384,7 +346,8 @@ inci (R m) = R (local modRC m)
384
346
385-- | Set indentation level for the inner computation equal to current
347-- | Set indentation level for the inner computation equal to current
386-- column. This makes sure that the entire inner block is uniformly
348-- column. This makes sure that the entire inner block is uniformly
387−-- \"shifted\" to the right.
349+-- \"shifted\" to the right. Only works (and makes sense) when enclosing
350+-- layout is multi-line.
388sitcc :: R () -> R ()
351sitcc :: R () -> R ()
389sitcc (R m) = do
352sitcc (R m) = do
390 requestedDel <- R (gets scRequestedDelimiter)
353 requestedDel <- R (gets scRequestedDelimiter)
@@ -392,9 +355,16 @@ sitcc (R m) = do
392 c <- R (gets scColumn)
355 c <- R (gets scColumn)
393 let modRC rc =
356 let modRC rc =
394 rc
357 rc
395− { rcIndent = max i (c + bool 0 1 (requestedDel == RequestedSpace))
358+ { rcIndent = max i c + bool 0 1 (requestedDel == RequestedSpace)
396 }
359 }
360+ vlayout (R m) . R $ do
361+ modify $ \sc ->
362+ sc
363+ { scRequestedDelimiter = case requestedDel of
364+ RequestedSpace -> RequestedNothing
365+ other -> other
366+ }
397− R (local modRC m)
367+ local modRC m
398
368
399-- | Set 'Layout' for internal computation.
369-- | Set 'Layout' for internal computation.
400enterLayout :: Layout -> R () -> R ()
370enterLayout :: Layout -> R () -> R ()
@@ -435,10 +405,11 @@ registerPendingCommentLine ::
435 -- | 'Text' to output
405 -- | 'Text' to output
436 Text ->
406 Text ->
437 R ()
407 R ()
438−registerPendingCommentLine position text = R $ do
408+registerPendingCommentLine position txt' = R $ do
409+ i <- asks rcIndent
439 modify $ \sc ->
410 modify $ \sc ->
440 sc
411 sc
441− { scPendingComments = (position, text) : scPendingComments sc
412+ { scPendingComments = (position, i, txt') : scPendingComments sc
442 }
413 }
443
414
444-- | Drop elements that begin before or at the same place as given
415-- | Drop elements that begin before or at the same place as given
@@ -497,10 +468,6 @@ withEnclosingSpan spn (R m) = R (local modRC m)
497 { rcEnclosingSpans = spn : rcEnclosingSpans rc
468 { rcEnclosingSpans = spn : rcEnclosingSpans rc
498 }
469 }
499
470
500−-- | Get spans on this line so far.
501−thisLineSpans :: R [RealSrcSpan]
502−thisLineSpans = R (gets scThisLineSpans)
503−
504----------------------------------------------------------------------------
471----------------------------------------------------------------------------
505-- Stateful markers
472-- Stateful markers
506
473
@@ -510,15 +477,15 @@ data SpanMark
510 HaddockSpan HaddockStyle RealSrcSpan
477 HaddockSpan HaddockStyle RealSrcSpan
511 | -- | Non-haddock comment
478 | -- | Non-haddock comment
512 CommentSpan RealSrcSpan
479 CommentSpan RealSrcSpan
513− | -- | A statement in a do-block and such span
480+ | -- | Non-comment span
514− StatementSpan RealSrcSpan
481+ OtherSpan RealSrcSpan
515
482
516-- | Project 'RealSrcSpan' from 'SpanMark'.
483-- | Project 'RealSrcSpan' from 'SpanMark'.
517spanMarkSpan :: SpanMark -> RealSrcSpan
484spanMarkSpan :: SpanMark -> RealSrcSpan
518spanMarkSpan = \case
485spanMarkSpan = \case
519 HaddockSpan _ s -> s
486 HaddockSpan _ s -> s
520 CommentSpan s -> s
487 CommentSpan s -> s
521− StatementSpan s -> s
488+ OtherSpan s -> s
522
489
523-- | Haddock string style.
490-- | Haddock string style.
524data HaddockStyle
491data HaddockStyle
@@ -567,7 +534,7 @@ dontUseBraces (R r) = R (local (\i -> i {rcCanUseBraces = False}) r)
567
534
568-- | Return 'True' if we can use braces in this context.
535-- | Return 'True' if we can use braces in this context.
569canUseBraces :: R Bool
536canUseBraces :: R Bool
570−canUseBraces = R (asks rcCanUseBraces)
537+canUseBraces = R $ asks rcCanUseBraces
571
538
572----------------------------------------------------------------------------
539----------------------------------------------------------------------------
573-- Constants
540-- Constants
src/Ormolu/Printer/Meat/Common.hs+10−11
@@ -114,14 +114,14 @@ p_qualName mname occName = do
114p_infixDefHelper ::
114p_infixDefHelper ::
115 -- | Whether to format in infix style
115 -- | Whether to format in infix style
116 Bool ->
116 Bool ->
117− -- | Whether to bump indentation for arguments
117+ -- | Indentation-bumping wrapper
118− Bool ->
118+ (R () -> R ()) ->
119 -- | How to print the operator\/name
119 -- | How to print the operator\/name
120 R () ->
120 R () ->
121 -- | How to print the arguments
121 -- | How to print the arguments
122 [R ()] ->
122 [R ()] ->
123 R ()
123 R ()
124−p_infixDefHelper isInfix indentArgs name args =
124+p_infixDefHelper isInfix inci' name args =
125 case (isInfix, args) of
125 case (isInfix, args) of
126 (True, p0 : p1 : ps) -> do
126 (True, p0 : p1 : ps) -> do
127 let parens' =
127 let parens' =
@@ -131,18 +131,18 @@ p_infixDefHelper isInfix indentArgs name args =
131 parens' $ do
131 parens' $ do
132 p0
132 p0
133 breakpoint
133 breakpoint
134− inci . sitcc $ do
134+ inci $ sitcc $ do
135 name
135 name
136 space
136 space
137 p1
137 p1
138− unless (null ps) . inciIf indentArgs $ do
138+ unless (null ps) . inci' $ do
139 breakpoint
139 breakpoint
140 sitcc (sep breakpoint sitcc ps)
140 sitcc (sep breakpoint sitcc ps)
141 (_, ps) -> do
141 (_, ps) -> do
142 name
142 name
143 unless (null ps) $ do
143 unless (null ps) $ do
144 breakpoint
144 breakpoint
145− inciIf indentArgs $ sitcc (sep breakpoint sitcc args)
145+ inci' $ sitcc (sep breakpoint sitcc args)
146
146
147-- | Print a Haddock.
147-- | Print a Haddock.
148p_hsDocString ::
148p_hsDocString ::
@@ -154,11 +154,10 @@ p_hsDocString ::
154 LHsDocString ->
154 LHsDocString ->
155 R ()
155 R ()
156p_hsDocString hstyle needsNewline (L l str) = do
156p_hsDocString hstyle needsNewline (L l str) = do
157− let isCommentSpan = \case
157+ goesAfterComment <- getSpanMark >>= \case
158− HaddockSpan _ _ -> True
158+ Just (HaddockSpan _ _) -> return True
159− CommentSpan _ -> True
159+ Just (CommentSpan _) -> return True
160− _ -> False
160+ _ -> return False
161− goesAfterComment <- maybe False isCommentSpan <$> getSpanMark
162 -- Make sure the Haddock is separated by a newline from other comments.
161 -- Make sure the Haddock is separated by a newline from other comments.
163 when goesAfterComment newline
162 when goesAfterComment newline
164 forM_ (zip (splitDocString str) (True : repeat False)) $ \(x, isFirst) -> do
163 forM_ (zip (splitDocString str) (True : repeat False)) $ \(x, isFirst) -> do
src/Ormolu/Printer/Meat/Declaration.hs+14−26
@@ -12,7 +12,7 @@ module Ormolu.Printer.Meat.Declaration
12where
12where
13
13
14import Data.List (sort)
14import Data.List (sort)
15−import Data.List.NonEmpty (NonEmpty (..), (<|))
15+import Data.List.NonEmpty ((<|), NonEmpty (..))
16import qualified Data.List.NonEmpty as NE
16import qualified Data.List.NonEmpty as NE
17import GHC hiding (InlinePragma)
17import GHC hiding (InlinePragma)
18import OccName (occNameFS)
18import OccName (occNameFS)
@@ -54,13 +54,12 @@ p_hsDeclsRespectGrouping :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
54p_hsDeclsRespectGrouping = p_hsDecls' Respect
54p_hsDeclsRespectGrouping = p_hsDecls' Respect
55
55
56p_hsDecls' :: UserGrouping -> FamilyStyle -> [LHsDecl GhcPs] -> R ()
56p_hsDecls' :: UserGrouping -> FamilyStyle -> [LHsDecl GhcPs] -> R ()
57−p_hsDecls' grouping style decls =
57+p_hsDecls' grouping style decls = sepSemi id $
58− sepSemi id $
59− -- Return a list of rendered declarations, adding a newline to separate
58+ -- Return a list of rendered declarations, adding a newline to separate
60− -- groups.
59+ -- groups.
61− case groupDecls decls of
60+ case groupDecls decls of
62− [] -> []
61+ [] -> []
63− (x : xs) -> renderGroup x ++ concat (zipWith renderGroupWithPrev (x : xs) xs)
62+ (x : xs) -> renderGroup x ++ concat (zipWith renderGroupWithPrev (x : xs) xs)
64 where
63 where
65 renderGroup = NE.toList . fmap (located' $ dontUseBraces . p_hsDecl style)
64 renderGroup = NE.toList . fmap (located' $ dontUseBraces . p_hsDecl style)
66 renderGroupWithPrev prev curr =
65 renderGroupWithPrev prev curr =
@@ -85,6 +84,9 @@ isDocumented = any (isHaddock . unLoc)
85 isHaddock _ = False
84 isHaddock _ = False
86
85
87-- | Group relevant declarations together.
86-- | Group relevant declarations together.
87+--
88+-- Add a declaration to a group iff it is relevant to either the first or
89+-- the preceding declaration in the group.
88groupDecls :: [LHsDecl GhcPs] -> [NonEmpty (LHsDecl GhcPs)]
90groupDecls :: [LHsDecl GhcPs] -> [NonEmpty (LHsDecl GhcPs)]
89groupDecls [] = []
91groupDecls [] = []
90groupDecls (l@(L _ DocNext) : xs) =
92groupDecls (l@(L _ DocNext) : xs) =
@@ -97,8 +99,7 @@ groupDecls (header : xs) =
97 let (grp, rest) = flip span (zip (header : xs) xs) $ \(previous, current) ->
99 let (grp, rest) = flip span (zip (header : xs) xs) $ \(previous, current) ->
98 let relevantToHdr = groupedDecls header current
100 let relevantToHdr = groupedDecls header current
99 relevantToPrev = groupedDecls previous current
101 relevantToPrev = groupedDecls previous current
100− isDeclSeries = declSeries previous current
101− in isDeclSeries || relevantToHdr || relevantToPrev
102+ in relevantToHdr || relevantToPrev
102 in (header :| map snd grp) : groupDecls (map snd rest)
103 in (header :| map snd grp) : groupDecls (map snd rest)
103
104
104p_hsDecl :: FamilyStyle -> HsDecl GhcPs -> R ()
105p_hsDecl :: FamilyStyle -> HsDecl GhcPs -> R ()
@@ -195,18 +196,6 @@ groupedDecls (L l_x x') (L l_y y') =
195 (_, DocPrev) -> True
196 (_, DocPrev) -> True
196 _ -> False
197 _ -> False
197
198
198−-- | Detect declaration series that should not have blanks between them.
199−declSeries ::
200− LHsDecl GhcPs ->
201− LHsDecl GhcPs ->
202− Bool
203−declSeries (L _ x) (L _ y) =
204− case (x, y) of
205− ( SigD NoExtField (TypeSig NoExtField _ _),
206− SigD NoExtField (TypeSig NoExtField _ _)
207− ) -> True
208− _ -> False
209−
210intersects :: Ord a => [a] -> [a] -> Bool
199intersects :: Ord a => [a] -> [a] -> Bool
211intersects a b = go (sort a) (sort b)
200intersects a b = go (sort a) (sort b)
212 where
201 where
@@ -299,10 +288,9 @@ patSigRdrNames (SigD NoExtField (PatSynSig NoExtField ns _)) = Just $ map unLoc
299patSigRdrNames _ = Nothing
288patSigRdrNames _ = Nothing
300
289
301warnSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
290warnSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
302−warnSigRdrNames (WarningD NoExtField (Warnings NoExtField _ ws)) = Just $
291+warnSigRdrNames (WarningD NoExtField (Warnings NoExtField _ ws)) = Just $ flip concatMap ws $ \case
303− flip concatMap ws $ \case
304− L _ (Warning NoExtField ns _) -> map unLoc ns
292+ L _ (Warning NoExtField ns _) -> map unLoc ns
305− L _ (XWarnDecl x) -> noExtCon x
293+ L _ (XWarnDecl x) -> noExtCon x
306warnSigRdrNames _ = Nothing
294warnSigRdrNames _ = Nothing
307
295
308patBindNames :: Pat GhcPs -> [RdrName]
296patBindNames :: Pat GhcPs -> [RdrName]
src/Ormolu/Printer/Meat/Declaration.hs-boot+1
@@ -9,4 +9,5 @@ import Ormolu.Printer.Combinators
9import Ormolu.Printer.Meat.Common
9import Ormolu.Printer.Meat.Common
10
10
11p_hsDecls :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
11p_hsDecls :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
12+
12p_hsDeclsRespectGrouping :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
13p_hsDeclsRespectGrouping :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
src/Ormolu/Printer/Meat/Declaration/Class.hs+2−2
@@ -58,7 +58,7 @@ p_classDecl ctx name HsQTvs {..} fixity fdeps csigs cdefs cats catdefs cdocs = d
58 switchLayout signatureSpans $
58 switchLayout signatureSpans $
59 p_infixDefHelper
59 p_infixDefHelper
60 (isInfix fixity)
60 (isInfix fixity)
61− True
61+ inci
62 (p_rdrName name)
62 (p_rdrName name)
63 (located' p_hsTyVarBndr <$> hsq_explicit)
63 (located' p_hsTyVarBndr <$> hsq_explicit)
64 inci (p_classFundeps fdeps)
64 inci (p_classFundeps fdeps)
@@ -82,7 +82,7 @@ p_classFundeps fdeps = unless (null fdeps) $ do
82 breakpoint
82 breakpoint
83 txt "|"
83 txt "|"
84 space
84 space
85− inci $ sep commaDel (sitcc . located' p_funDep) fdeps
85+ sitcc $ sep (comma >> breakpoint) (sitcc . located' p_funDep) fdeps
86
86
87p_funDep :: FunDep (Located RdrName) -> R ()
87p_funDep :: FunDep (Located RdrName) -> R ()
88p_funDep (before, after) = do
88p_funDep (before, after) = do
src/Ormolu/Printer/Meat/Declaration/Data.hs+31−34
@@ -41,7 +41,7 @@ p_dataDecl style name tpats fixity HsDataDefn {..} = do
41 inci $
41 inci $
42 p_infixDefHelper
42 p_infixDefHelper
43 (isInfix fixity)
43 (isInfix fixity)
44− True
44+ inci
45 (p_rdrName name)
45 (p_rdrName name)
46 (located' p_hsType <$> tpats)
46 (located' p_hsType <$> tpats)
47 case dd_kindSig of
47 case dd_kindSig of
@@ -60,26 +60,24 @@ p_dataDecl style name tpats fixity HsDataDefn {..} = do
60 txt "where"
60 txt "where"
61 breakpoint
61 breakpoint
62 sepSemi (located' (p_conDecl False)) dd_cons
62 sepSemi (located' (p_conDecl False)) dd_cons
63− else switchLayout (getLoc name : (getLoc <$> dd_cons)) . inci $ do
63+ else switchLayout (getLoc name : (getLoc <$> dd_cons))
64+ $ inci
65+ $ do
64− let singleConstRec = isSingleConstRec dd_cons
66+ let singleConstRec = isSingleConstRec dd_cons
65− if singleConstRec
67+ if singleConstRec
66− then space
68+ then space
67− else
68− if hasHaddocks dd_cons
69− then newline
70− else breakpoint
69+ else breakpoint
71− equals
70+ txt "="
72− space
71+ space
73− layout <- getLayout
74− let s =
72+ let s =
75− if layout == MultiLine || hasHaddocks dd_cons
73+ vlayout
76− then newline >> txt "|" >> space
74+ (space >> txt "|" >> space)
77− else space >> txt "|" >> space
75+ (newline >> txt "|" >> space)
78− sitcc' =
76+ sitcc' =
79− if singleConstRec
77+ if singleConstRec
80− then id
78+ then id
81− else sitcc
79+ else sitcc
82− sep s (sitcc' . located' (p_conDecl singleConstRec)) dd_cons
80+ sep s (sitcc' . located' (p_conDecl singleConstRec)) dd_cons
83 unless (null $ unLoc dd_derivs) breakpoint
81 unless (null $ unLoc dd_derivs) breakpoint
84 inci . located dd_derivs $ \xs ->
82 inci . located dd_derivs $ \xs ->
85 sep newline (located' p_hsDerivingClause) xs
83 sep newline (located' p_hsDerivingClause) xs
@@ -104,10 +102,11 @@ p_conDecl singleConstRec = \case
104 (c : cs) -> do
102 (c : cs) -> do
105 p_rdrName c
103 p_rdrName c
106 unless (null cs) . inci $ do
104 unless (null cs) . inci $ do
107− commaDel
105+ comma
106+ breakpoint
108− sep commaDel p_rdrName cs
107+ sitcc $ sep (comma >> breakpoint) p_rdrName cs
108+ space
109 inci $ do
109 inci $ do
110− space
111 txt "::"
110 txt "::"
112 let interArgBreak =
111 let interArgBreak =
113 if hasDocStrings (unLoc con_res_ty)
112 if hasDocStrings (unLoc con_res_ty)
@@ -151,11 +150,15 @@ p_conDecl singleConstRec = \case
151 PrefixCon xs -> do
150 PrefixCon xs -> do
152 p_rdrName con_name
151 p_rdrName con_name
153 unless (null xs) breakpoint
152 unless (null xs) breakpoint
154− inci . sitcc $ sep breakpoint (sitcc . located' p_hsTypePostDoc) xs
153+ inci . sitcc $ sep breakpoint (sitcc . located' p_hsType) xs
155 RecCon l -> do
154 RecCon l -> do
156 p_rdrName con_name
155 p_rdrName con_name
157 breakpoint
156 breakpoint
157+ let inci' =
158+ if singleConstRec
159+ then id
160+ else inci
158− inciIf (not singleConstRec) (located l p_conDeclFields)
161+ inci' (located l p_conDeclFields)
159 InfixCon x y -> do
162 InfixCon x y -> do
160 located x p_hsType
163 located x p_hsType
161 breakpoint
164 breakpoint
@@ -204,9 +207,9 @@ p_hsDerivingClause HsDerivingClause {..} = do
204 let derivingWhat = located deriv_clause_tys $ \case
207 let derivingWhat = located deriv_clause_tys $ \case
205 [] -> txt "()"
208 [] -> txt "()"
206 xs ->
209 xs ->
207− parens N $
210+ parens N . sitcc $
208 sep
211 sep
209− commaDel
212+ (comma >> breakpoint)
210 (sitcc . located' p_hsType . hsib_body)
213 (sitcc . located' p_hsType . hsib_body)
211 xs
214 xs
212 space
215 space
@@ -253,9 +256,3 @@ isSingleConstRec [(L _ ConDeclH98 {..})] =
253 RecCon _ -> True
256 RecCon _ -> True
254 _ -> False
257 _ -> False
255isSingleConstRec _ = False
258isSingleConstRec _ = False
256−
257−hasHaddocks :: [LConDecl GhcPs] -> Bool
258−hasHaddocks = any (f . unLoc)
259− where
260− f ConDeclH98 {..} = isJust con_doc
261− f _ = False
src/Ormolu/Printer/Meat/Declaration/Default.hs+2−2
@@ -15,6 +15,6 @@ p_defaultDecl = \case
15 DefaultDecl NoExtField ts -> do
15 DefaultDecl NoExtField ts -> do
16 txt "default"
16 txt "default"
17 breakpoint
17 breakpoint
18− inci . parens N $
18+ inci . parens N . sitcc $
19− sep commaDel (sitcc . located' p_hsType) ts
19+ sep (comma >> breakpoint) (sitcc . located' p_hsType) ts
20 XDefaultDecl x -> noExtCon x
20 XDefaultDecl x -> noExtCon x
src/Ormolu/Printer/Meat/Declaration/Instance.hs+9−5
@@ -32,7 +32,9 @@ p_standaloneDerivDecl DerivDecl {..} = do
32 txt "instance"
32 txt "instance"
33 breakpoint
33 breakpoint
34 match_overlap_mode deriv_overlap_mode breakpoint
34 match_overlap_mode deriv_overlap_mode breakpoint
35+ if toIndent
36+ then inci typesAfterInstance
35− inciIf toIndent typesAfterInstance
37+ else typesAfterInstance
36 txt "deriving"
38 txt "deriving"
37 space
39 space
38 case deriv_strategy of
40 case deriv_strategy of
@@ -88,10 +90,12 @@ p_clsInstDecl = \case
88 unless (null allDecls) $ do
90 unless (null allDecls) $ do
89 breakpoint
91 breakpoint
90 txt "where"
92 txt "where"
91− unless (null allDecls) . inci $ do
93+ unless (null allDecls)
94+ $ inci
95+ $ do
92− -- Ensure whitespace is added after where clause.
96+ -- Ensure whitespace is added after where clause.
93− breakpoint
97+ breakpoint
94− dontUseBraces $ p_hsDeclsRespectGrouping Associated allDecls
98+ dontUseBraces $ p_hsDeclsRespectGrouping Associated allDecls
95 XHsImplicitBndrs x -> noExtCon x
99 XHsImplicitBndrs x -> noExtCon x
96 XClsInstDecl x -> noExtCon x
100 XClsInstDecl x -> noExtCon x
97
101
src/Ormolu/Printer/Meat/Declaration/Rule.hs+2−2
@@ -18,7 +18,7 @@ import Ormolu.Printer.Meat.Type
18p_ruleDecls :: RuleDecls GhcPs -> R ()
18p_ruleDecls :: RuleDecls GhcPs -> R ()
19p_ruleDecls = \case
19p_ruleDecls = \case
20 HsRules NoExtField _ xs ->
20 HsRules NoExtField _ xs ->
21− pragma "RULES" $
21+ pragma "RULES" . sitcc $
22 sep breakpoint (sitcc . located' p_ruleDecl) xs
22 sep breakpoint (sitcc . located' p_ruleDecl) xs
23 XRuleDecls x -> noExtCon x
23 XRuleDecls x -> noExtCon x
24
24
@@ -43,7 +43,7 @@ p_ruleDecl = \case
43 inci $ do
43 inci $ do
44 located lhs p_hsExpr
44 located lhs p_hsExpr
45 space
45 space
46− equals
46+ txt "="
47 inci $ do
47 inci $ do
48 breakpoint
48 breakpoint
49 located rhs p_hsExpr
49 located rhs p_hsExpr
src/Ormolu/Printer/Meat/Declaration/Signature.hs+27−29
@@ -14,6 +14,7 @@ where
14import BasicTypes
14import BasicTypes
15import BooleanFormula
15import BooleanFormula
16import Control.Monad
16import Control.Monad
17+import Data.Bool (bool)
17import GHC
18import GHC
18import Ormolu.Printer.Combinators
19import Ormolu.Printer.Combinators
19import Ormolu.Printer.Meat.Common
20import Ormolu.Printer.Meat.Common
@@ -47,22 +48,24 @@ p_typeSig indentTail (n : ns) hswc = do
47 p_rdrName n
48 p_rdrName n
48 if null ns
49 if null ns
49 then p_typeAscription hswc
50 then p_typeAscription hswc
50− else inciIf indentTail $ do
51+ else bool id inci indentTail $ do
51− commaDel
52+ comma
53+ breakpoint
52− sep commaDel p_rdrName ns
54+ sep (comma >> breakpoint) p_rdrName ns
53 p_typeAscription hswc
55 p_typeAscription hswc
54
56
55p_typeAscription ::
57p_typeAscription ::
56 LHsSigWcType GhcPs ->
58 LHsSigWcType GhcPs ->
57 R ()
59 R ()
58−p_typeAscription HsWC {..} = inci $ do
60+p_typeAscription HsWC {..} = do
59 space
61 space
62+ inci $ do
60− txt "::"
63+ txt "::"
61− let t = hsib_body hswc_body
64+ let t = hsib_body hswc_body
62− if hasDocStrings (unLoc t)
65+ if hasDocStrings (unLoc t)
63− then newline
66+ then newline
64− else breakpoint
67+ else breakpoint
65− located t p_hsType
68+ located t p_hsType
66p_typeAscription (XHsWildCardBndrs x) = noExtCon x
69p_typeAscription (XHsWildCardBndrs x) = noExtCon x
67
70
68p_patSynSig ::
71p_patSynSig ::
@@ -71,11 +74,7 @@ p_patSynSig ::
71 R ()
74 R ()
72p_patSynSig names hsib = do
75p_patSynSig names hsib = do
73 txt "pattern"
76 txt "pattern"
74− let body =
75− p_typeSig
76− False
77− names
78− HsWC {hswc_ext = NoExtField, hswc_body = hsib}
77+ let body = p_typeSig False names HsWC {hswc_ext = NoExtField, hswc_body = hsib}
79 if length names > 1
78 if length names > 1
80 then breakpoint >> inci body
79 then breakpoint >> inci body
81 else space >> body
80 else space >> body
@@ -104,7 +103,7 @@ p_fixSig = \case
104 space
103 space
105 atom n
104 atom n
106 space
105 space
107− sitcc $ sep commaDel p_rdrName names
106+ sitcc $ sep (comma >> breakpoint) p_rdrName names
108 XFixitySig x -> noExtCon x
107 XFixitySig x -> noExtCon x
109
108
110p_inlineSig ::
109p_inlineSig ::
@@ -143,7 +142,7 @@ p_specSig name ts InlinePragma {..} = pragmaBraces $ do
143 space
142 space
144 txt "::"
143 txt "::"
145 breakpoint
144 breakpoint
146− inci $ sep commaDel (located' p_hsType . hsib_body) ts
145+ inci $ sep (comma >> breakpoint) (located' p_hsType . hsib_body) ts
147
146
148p_inlineSpec :: InlineSpec -> R ()
147p_inlineSpec :: InlineSpec -> R ()
149p_inlineSpec = \case
148p_inlineSpec = \case
@@ -187,13 +186,13 @@ p_booleanFormula = \case
187 And xs ->
186 And xs ->
188 sitcc $
187 sitcc $
189 sep
188 sep
190− commaDel
189+ (comma >> breakpoint)
191 (located' p_booleanFormula)
190 (located' p_booleanFormula)
192 xs
191 xs
193 Or xs ->
192 Or xs ->
194 sitcc $
193 sitcc $
195 sep
194 sep
196− (breakpoint >> txt "|" >> space)
195+ (breakpoint >> txt "| ")
197 (located' p_booleanFormula)
196 (located' p_booleanFormula)
198 xs
197 xs
199 Parens l -> located l (parens N . p_booleanFormula)
198 Parens l -> located l (parens N . p_booleanFormula)
@@ -207,7 +206,7 @@ p_completeSig ::
207p_completeSig cs' mty =
206p_completeSig cs' mty =
208 located cs' $ \cs ->
207 located cs' $ \cs ->
209 pragma "COMPLETE" . inci $ do
208 pragma "COMPLETE" . inci $ do
210− sep commaDel p_rdrName cs
209+ sitcc $ sep (comma >> breakpoint) p_rdrName cs
211 forM_ mty $ \ty -> do
210 forM_ mty $ \ty -> do
212 space
211 space
213 txt "::"
212 txt "::"
@@ -224,13 +223,12 @@ p_sccSig loc literal = pragma "SCC" . inci $ do
224p_standaloneKindSig :: StandaloneKindSig GhcPs -> R ()
223p_standaloneKindSig :: StandaloneKindSig GhcPs -> R ()
225p_standaloneKindSig (StandaloneKindSig NoExtField name bndrs) = do
224p_standaloneKindSig (StandaloneKindSig NoExtField name bndrs) = do
226 txt "type"
225 txt "type"
227− inci $ do
228− space
226+ space
229− p_rdrName name
227+ p_rdrName name
230− space
228+ space
231− txt "::"
229+ txt "::"
232− breakpoint
230+ breakpoint
233− case bndrs of
231+ inci $ case bndrs of
234− HsIB NoExtField sig -> located sig p_hsType
232+ HsIB NoExtField sig -> located sig p_hsType
235− XHsImplicitBndrs x -> noExtCon x
233+ XHsImplicitBndrs x -> noExtCon x
236p_standaloneKindSig (XStandaloneKindSig c) = noExtCon c
234p_standaloneKindSig (XStandaloneKindSig c) = noExtCon c
src/Ormolu/Printer/Meat/Declaration/Type.hs+3−5
@@ -28,13 +28,11 @@ p_synDecl name fixity HsQTvs {..} t = do
28 switchLayout (getLoc name : map getLoc hsq_explicit) $
28 switchLayout (getLoc name : map getLoc hsq_explicit) $
29 p_infixDefHelper
29 p_infixDefHelper
30 (case fixity of Infix -> True; _ -> False)
30 (case fixity of Infix -> True; _ -> False)
31− True
31+ inci
32 (p_rdrName name)
32 (p_rdrName name)
33 (map (located' p_hsTyVarBndr) hsq_explicit)
33 (map (located' p_hsTyVarBndr) hsq_explicit)
34 space
34 space
35− equals
35+ txt "="
36− if hasDocStrings (unLoc t)
37− then newline
38− else breakpoint
36+ breakpoint
39 inci (located t p_hsType)
37 inci (located t p_hsType)
40p_synDecl _ _ (XLHsQTyVars x) _ = noExtCon x
38p_synDecl _ _ (XLHsQTyVars x) _ = noExtCon x
src/Ormolu/Printer/Meat/Declaration/TypeFamily.hs+5−5
@@ -31,7 +31,7 @@ p_famDecl style FamilyDecl {fdTyVars = HsQTvs {..}, ..} = do
31 switchLayout (getLoc fdLName : (getLoc <$> hsq_explicit)) $
31 switchLayout (getLoc fdLName : (getLoc <$> hsq_explicit)) $
32 p_infixDefHelper
32 p_infixDefHelper
33 (isInfix fdFixity)
33 (isInfix fdFixity)
34− True
34+ inci
35 (p_rdrName fdLName)
35 (p_rdrName fdLName)
36 (located' p_hsTyVarBndr <$> hsq_explicit)
36 (located' p_hsTyVarBndr <$> hsq_explicit)
37 let resultSig = p_familyResultSigL fdResultSig
37 let resultSig = p_familyResultSigL fdResultSig
@@ -69,7 +69,7 @@ p_familyResultSigL l =
69 breakpoint
69 breakpoint
70 located k p_hsType
70 located k p_hsType
71 TyVarSig NoExtField bndr -> Just $ do
71 TyVarSig NoExtField bndr -> Just $ do
72− equals
72+ txt "="
73 breakpoint
73 breakpoint
74 located bndr p_hsTyVarBndr
74 located bndr p_hsTyVarBndr
75 XFamilyResultSig x ->
75 XFamilyResultSig x ->
@@ -92,16 +92,16 @@ p_tyFamInstEqn HsIB {hsib_body = FamEqn {..}} = do
92 Just bndrs -> do
92 Just bndrs -> do
93 p_forallBndrs ForallInvis p_hsTyVarBndr bndrs
93 p_forallBndrs ForallInvis p_hsTyVarBndr bndrs
94 breakpoint
94 breakpoint
95− inciIf (not $ null feqn_bndrs) $ do
95+ (if null feqn_bndrs then id else inci) $ do
96 let famLhsSpn = getLoc feqn_tycon : fmap (getLoc . typeArgToType) feqn_pats
96 let famLhsSpn = getLoc feqn_tycon : fmap (getLoc . typeArgToType) feqn_pats
97 switchLayout famLhsSpn $
97 switchLayout famLhsSpn $
98 p_infixDefHelper
98 p_infixDefHelper
99 (isInfix feqn_fixity)
99 (isInfix feqn_fixity)
100− True
100+ inci
101 (p_rdrName feqn_tycon)
101 (p_rdrName feqn_tycon)
102 (located' p_hsType . typeArgToType <$> feqn_pats)
102 (located' p_hsType . typeArgToType <$> feqn_pats)
103 space
103 space
104− equals
104+ txt "="
105 breakpoint
105 breakpoint
106 inci (located feqn_rhs p_hsType)
106 inci (located feqn_rhs p_hsType)
107p_tyFamInstEqn HsIB {hsib_body = XFamEqn x} = noExtCon x
107p_tyFamInstEqn HsIB {hsib_body = XFamEqn x} = noExtCon x
src/Ormolu/Printer/Meat/Declaration/Value.hs+166−181
@@ -1,5 +1,4 @@
1{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE LambdaCase #-}
2−{-# LANGUAGE MultiWayIf #-}
3{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
4{-# LANGUAGE RecordWildCards #-}
3{-# LANGUAGE RecordWildCards #-}
5{-# LANGUAGE TypeApplications #-}
4{-# LANGUAGE TypeApplications #-}
@@ -22,12 +21,12 @@ import Data.Char (isPunctuation, isSymbol)
22import Data.Data hiding (Infix, Prefix)
21import Data.Data hiding (Infix, Prefix)
23import Data.Functor ((<&>))
22import Data.Functor ((<&>))
24import Data.List (intersperse, sortOn)
23import Data.List (intersperse, sortOn)
25−import Data.List.NonEmpty (NonEmpty (..), (<|))
24+import Data.List.NonEmpty ((<|), NonEmpty (..))
26import qualified Data.List.NonEmpty as NE
25import qualified Data.List.NonEmpty as NE
27import Data.Text (Text)
26import Data.Text (Text)
28import qualified Data.Text as Text
27import qualified Data.Text as Text
29import GHC
28import GHC
30−import OccName (occNameString)
29+import OccName (mkVarOcc)
31import Ormolu.Printer.Combinators
30import Ormolu.Printer.Combinators
32import Ormolu.Printer.Internal
31import Ormolu.Printer.Internal
33import Ormolu.Printer.Meat.Common
32import Ormolu.Printer.Meat.Common
@@ -61,7 +60,7 @@ data Placement
61 -- should use it and avoid bumping one level
60 -- should use it and avoid bumping one level
62 -- of indentation
61 -- of indentation
63 Hanging
62 Hanging
64− deriving (Eq, Show)
63+ deriving (Eq)
65
64
66p_valDecl :: HsBindLR GhcPs GhcPs -> R ()
65p_valDecl :: HsBindLR GhcPs GhcPs -> R ()
67p_valDecl = \case
66p_valDecl = \case
@@ -180,24 +179,25 @@ p_match' placer render style isInfix strictness m_pats GRHSs {..} = do
180 NoSrcStrict -> return ()
179 NoSrcStrict -> return ()
181 SrcStrict -> txt "!"
180 SrcStrict -> txt "!"
182 SrcLazy -> txt "~"
181 SrcLazy -> txt "~"
183− indentBody <- case NE.nonEmpty m_pats of
182+ inci' <- case NE.nonEmpty m_pats of
184− Nothing ->
185− False <$ case style of
183+ Nothing -> id <$ case style of
186− Function name -> p_rdrName name
184+ Function name -> p_rdrName name
187− _ -> return ()
185+ _ -> return ()
188 Just ne_pats -> do
186 Just ne_pats -> do
189− let combinedSpans = case style of
187+ let combinedSpans =
190− Function name -> combineSrcSpans (getLoc name) patSpans
188+ combineSrcSpans' $
191− _ -> patSpans
192− patSpans = combineSrcSpans' (getLoc <$> ne_pats)
189+ getLoc <$> ne_pats
190+ inci' =
193− indentBody = not (isOneLineSpan combinedSpans)
191+ if isOneLineSpan combinedSpans
192+ then id
193+ else inci
194 switchLayout [combinedSpans] $ do
194 switchLayout [combinedSpans] $ do
195 let stdCase = sep breakpoint (located' p_pat) m_pats
195 let stdCase = sep breakpoint (located' p_pat) m_pats
196 case style of
196 case style of
197 Function name ->
197 Function name ->
198 p_infixDefHelper
198 p_infixDefHelper
199 isInfix
199 isInfix
200− indentBody
200+ inci'
201 (p_rdrName name)
201 (p_rdrName name)
202 (located' p_pat <$> m_pats)
202 (located' p_pat <$> m_pats)
203 PatternBind -> stdCase
203 PatternBind -> stdCase
@@ -212,32 +212,40 @@ p_match' placer render style isInfix strictness m_pats GRHSs {..} = do
212 when needsSpace space
212 when needsSpace space
213 sitcc stdCase
213 sitcc stdCase
214 LambdaCase -> stdCase
214 LambdaCase -> stdCase
215− return indentBody
215+ return inci'
216 let -- Calculate position of end of patterns. This is useful when we decide
216 let -- Calculate position of end of patterns. This is useful when we decide
217 -- about putting certain constructions in hanging positions.
217 -- about putting certain constructions in hanging positions.
218 endOfPats = case NE.nonEmpty m_pats of
218 endOfPats = case NE.nonEmpty m_pats of
219 Nothing -> case style of
219 Nothing -> case style of
220− Function name -> Just (getLoc name)
220+ Function name -> (Just . srcSpanEnd . getLoc) name
221 _ -> Nothing
221 _ -> Nothing
222− Just pats -> (Just . getLoc . NE.last) pats
222+ Just pats -> (Just . srcSpanEnd . getLoc . NE.last) pats
223 isCase = \case
223 isCase = \case
224 Case -> True
224 Case -> True
225 LambdaCase -> True
225 LambdaCase -> True
226 _ -> False
226 _ -> False
227− hasGuards = withGuards grhssGRHSs
227+ let hasGuards = withGuards grhssGRHSs
228+ unless (length grhssGRHSs > 1) $
229+ case style of
230+ Function _ | hasGuards -> return ()
231+ Function _ -> space >> txt "="
232+ PatternBind -> space >> txt "="
233+ s | isCase s && hasGuards -> return ()
234+ _ -> space >> txt "->"
228− grhssSpan =
235+ let grhssSpan =
229 combineSrcSpans' $
236 combineSrcSpans' $
230 getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
237 getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
231 patGrhssSpan =
238 patGrhssSpan =
232 maybe
239 maybe
233 grhssSpan
240 grhssSpan
234− (combineSrcSpans grhssSpan . srcLocSpan . srcSpanEnd)
241+ (combineSrcSpans grhssSpan . srcLocSpan)
235 endOfPats
242 endOfPats
236 placement =
243 placement =
237 case endOfPats of
244 case endOfPats of
238 Nothing -> blockPlacement placer grhssGRHSs
245 Nothing -> blockPlacement placer grhssGRHSs
239 Just spn ->
246 Just spn ->
247+ if isOneLineSpan
240− if onTheSameLine spn grhssSpan
248+ (mkSrcSpan spn (srcSpanStart grhssSpan))
241 then blockPlacement placer grhssGRHSs
249 then blockPlacement placer grhssGRHSs
242 else Normal
250 else Normal
243 p_body = do
251 p_body = do
@@ -253,14 +261,7 @@ p_match' placer render style isInfix strictness m_pats GRHSs {..} = do
253 txt "where"
261 txt "where"
254 unless whereIsEmpty breakpoint
262 unless whereIsEmpty breakpoint
255 inci $ located grhssLocalBinds p_hsLocalBinds
263 inci $ located grhssLocalBinds p_hsLocalBinds
256− inciIf indentBody $ do
264+ inci' $ do
257− unless (length grhssGRHSs > 1) $
258− case style of
259− Function _ | hasGuards -> return ()
260− Function _ -> space >> inci equals
261− PatternBind -> space >> inci equals
262− s | isCase s && hasGuards -> return ()
263− _ -> space >> txt "->"
264 switchLayout [patGrhssSpan] $
265 switchLayout [patGrhssSpan] $
265 placeHanging placement p_body
266 placeHanging placement p_body
266 inci p_where
267 inci p_where
@@ -284,24 +285,24 @@ p_grhs' placer render style (GRHS NoExtField guards body) =
284 xs -> do
285 xs -> do
285 txt "|"
286 txt "|"
286 space
287 space
287− sitcc (sep commaDel (sitcc . located' p_stmt) xs)
288+ sitcc (sep (comma >> breakpoint) (sitcc . located' p_stmt) xs)
288 space
289 space
289− inci $ case style of
290+ txt $ case style of
290− EqualSign -> equals
291+ EqualSign -> "="
291− RightArrow -> txt "->"
292+ RightArrow -> "->"
292 placeHanging placement p_body
293 placeHanging placement p_body
293 where
294 where
294 placement =
295 placement =
295 case endOfGuards of
296 case endOfGuards of
296 Nothing -> placer (unLoc body)
297 Nothing -> placer (unLoc body)
297 Just spn ->
298 Just spn ->
298− if onTheSameLine spn (getLoc body)
299+ if isOneLineSpan (mkSrcSpan spn (srcSpanStart (getLoc body)))
299 then placer (unLoc body)
300 then placer (unLoc body)
300 else Normal
301 else Normal
301 endOfGuards =
302 endOfGuards =
302 case NE.nonEmpty guards of
303 case NE.nonEmpty guards of
303 Nothing -> Nothing
304 Nothing -> Nothing
304− Just gs -> (Just . getLoc . NE.last) gs
305+ Just gs -> (Just . srcSpanEnd . getLoc . NE.last) gs
305 p_body = located body render
306 p_body = located body render
306p_grhs' _ _ _ (XGRHS x) = noExtCon x
307p_grhs' _ _ _ (XGRHS x) = noExtCon x
307
308
@@ -316,7 +317,7 @@ p_hsCmd = \case
316 HsHigherOrderApp -> txt "-<<"
317 HsHigherOrderApp -> txt "-<<"
317 placeHanging (exprPlacement (unLoc input)) $
318 placeHanging (exprPlacement (unLoc input)) $
318 located input p_hsExpr
319 located input p_hsExpr
319− HsCmdArrForm NoExtField form Prefix _ cmds -> banana $ do
320+ HsCmdArrForm NoExtField form Prefix _ cmds -> banana $ sitcc $ do
320 located form p_hsExpr
321 located form p_hsExpr
321 unless (null cmds) $ do
322 unless (null cmds) $ do
322 breakpoint
323 breakpoint
@@ -353,14 +354,7 @@ p_hsCmdTop = \case
353 HsCmdTop NoExtField cmd -> located cmd p_hsCmd
354 HsCmdTop NoExtField cmd -> located cmd p_hsCmd
354 XCmdTop x -> noExtCon x
355 XCmdTop x -> noExtCon x
355
356
356−-- | Render an expression preserving blank lines between such consecutive
357−-- expressions found in the original source code.
358−withSpacing ::
357+withSpacing :: Data a => (a -> R ()) -> Located a -> R ()
359− -- | Rendering function
360− (a -> R ()) ->
361− -- | Entity to render
362− Located a ->
363− R ()
364withSpacing f l = located l $ \x -> do
358withSpacing f l = located l $ \x -> do
365 case getLoc l of
359 case getLoc l of
366 UnhelpfulSpan _ -> f x
360 UnhelpfulSpan _ -> f x
@@ -369,7 +363,7 @@ withSpacing f l = located l $ \x -> do
369 -- Spacing before comments will be handled by the code
363 -- Spacing before comments will be handled by the code
370 -- that prints comments, so we just have to deal with
364 -- that prints comments, so we just have to deal with
371 -- blank lines between statements here.
365 -- blank lines between statements here.
372− Just (StatementSpan lastSpn) ->
366+ Just (OtherSpan lastSpn) ->
373 if srcSpanStartLine currentSpn > srcSpanEndLine lastSpn + 1
367 if srcSpanStartLine currentSpn > srcSpanEndLine lastSpn + 1
374 then newline
368 then newline
375 else return ()
369 else return ()
@@ -380,7 +374,7 @@ withSpacing f l = located l $ \x -> do
380 getSpanMark >>= \case
374 getSpanMark >>= \case
381 Just (HaddockSpan _ _) -> return ()
375 Just (HaddockSpan _ _) -> return ()
382 Just (CommentSpan _) -> return ()
376 Just (CommentSpan _) -> return ()
383− _ -> setSpanMark (StatementSpan currentSpn)
377+ _ -> setSpanMark (OtherSpan currentSpn)
384
378
385p_stmt :: Stmt GhcPs (LHsExpr GhcPs) -> R ()
379p_stmt :: Stmt GhcPs (LHsExpr GhcPs) -> R ()
386p_stmt = p_stmt' exprPlacement p_hsExpr
380p_stmt = p_stmt' exprPlacement p_hsExpr
@@ -471,31 +465,34 @@ gatherStmtBlock (XParStmtBlock x) = noExtCon x
471p_hsLocalBinds :: HsLocalBindsLR GhcPs GhcPs -> R ()
465p_hsLocalBinds :: HsLocalBindsLR GhcPs GhcPs -> R ()
472p_hsLocalBinds = \case
466p_hsLocalBinds = \case
473 HsValBinds NoExtField (ValBinds NoExtField bag lsigs) -> do
467 HsValBinds NoExtField (ValBinds NoExtField bag lsigs) -> do
468+ let ssStart =
469+ either
470+ (srcSpanStart . getLoc)
471+ (srcSpanStart . getLoc)
472+ items =
473+ (Left <$> bagToList bag) ++ (Right <$> lsigs)
474+ p_item (Left x) = located x p_valDecl
475+ p_item (Right x) = located x p_sigDecl
476+ -- Assigns 'False' to the last element, 'True' to the rest.
477+ markInit :: [a] -> [(Bool, a)]
478+ markInit [] = []
479+ markInit [x] = [(False, x)]
480+ markInit (x : xs) = (True, x) : markInit xs
474 -- When in a single-line layout, there is a chance that the inner
481 -- When in a single-line layout, there is a chance that the inner
475 -- elements will also contain semicolons and they will confuse the
482 -- elements will also contain semicolons and they will confuse the
476 -- parser. so we request braces around every element except the last.
483 -- parser. so we request braces around every element except the last.
477 br <- layoutToBraces <$> getLayout
484 br <- layoutToBraces <$> getLayout
478− let items =
485+ sitcc $
479− let injectLeft (L l x) = L l (Left x)
486+ sepSemi
480− injectRight (L l x) = L l (Right x)
487+ (\(m, i) -> (if m then br else id) $ p_item i)
481− in (injectLeft <$> bagToList bag) ++ (injectRight <$> lsigs)
488+ (markInit $ sortOn ssStart items)
482− positionToBracing = \case
483− SinglePos -> id
484− FirstPos -> br
485− MiddlePos -> br
486− LastPos -> id
487− p_item' (p, item) =
488− positionToBracing p $
489− withSpacing (either p_valDecl p_sigDecl) item
490− binds = sortOn (srcSpanStart . getLoc) items
491− sitcc $ sepSemi p_item' (attachRelativePos binds)
492 HsValBinds NoExtField _ -> notImplemented "HsValBinds"
489 HsValBinds NoExtField _ -> notImplemented "HsValBinds"
493 HsIPBinds NoExtField (IPBinds NoExtField xs) ->
490 HsIPBinds NoExtField (IPBinds NoExtField xs) ->
494 -- Second argument of IPBind is always Left before type-checking.
491 -- Second argument of IPBind is always Left before type-checking.
495 let p_ipBind (IPBind NoExtField (Left name) expr) = do
492 let p_ipBind (IPBind NoExtField (Left name) expr) = do
496 atom name
493 atom name
497 space
494 space
498− equals
495+ txt "="
499 breakpoint
496 breakpoint
500 useBraces $ inci $ located expr p_hsExpr
497 useBraces $ inci $ located expr p_hsExpr
501 p_ipBind (IPBind NoExtField (Right _) _) =
498 p_ipBind (IPBind NoExtField (Right _) _) =
@@ -514,12 +511,15 @@ p_hsRecField HsRecField {..} = do
514 p_rdrName hsRecFieldLbl
511 p_rdrName hsRecFieldLbl
515 unless hsRecPun $ do
512 unless hsRecPun $ do
516 space
513 space
517− equals
514+ txt "="
518− let placement =
519− if onTheSameLine (getLoc hsRecFieldLbl) (getLoc hsRecFieldArg)
520− then exprPlacement (unLoc hsRecFieldArg)
515+ let placement = exprPlacement (unLoc hsRecFieldArg)
521− else Normal
522− placeHanging placement (located hsRecFieldArg p_hsExpr)
516+ placeHanging placement $ located hsRecFieldArg p_hsExpr
517+
518+p_hsTupArg :: HsTupArg GhcPs -> R ()
519+p_hsTupArg = \case
520+ Present NoExtField x -> located x p_hsExpr
521+ Missing NoExtField -> pure ()
522+ XTupArg x -> noExtCon x
523
523
524p_hsExpr :: HsExpr GhcPs -> R ()
524p_hsExpr :: HsExpr GhcPs -> R ()
525p_hsExpr = p_hsExpr' N
525p_hsExpr = p_hsExpr' N
@@ -584,21 +584,23 @@ p_hsExpr' s = \case
584 -- do-block or case expression it is not a good idea. It seems
584 -- do-block or case expression it is not a good idea. It seems
585 -- to be safe to always bump indentation when the function
585 -- to be safe to always bump indentation when the function
586 -- expression is parenthesised.
586 -- expression is parenthesised.
587− doIndent =
587+ indent =
588 case func of
588 case func of
589− L _ (HsPar NoExtField _) -> True
589+ L _ (HsPar NoExtField _) -> inci
590− L _ (HsAppType NoExtField _ _) -> True
590+ L _ (HsAppType NoExtField _ _) -> inci
591− L _ (HsMultiIf NoExtField _) -> True
591+ L _ (HsMultiIf NoExtField _) -> inci
592+ L spn _ ->
592− L spn _ -> isOneLineSpan spn
593+ if isOneLineSpan spn
593− ub <-
594+ then inci
595+ else id
594− getLayout <&> \case
596+ ub <- getLayout <&> \case
595− SingleLine -> useBraces
597+ SingleLine -> useBraces
596− MultiLine -> id
598+ MultiLine -> id
597 ub $ do
599 ub $ do
598 located func (p_hsExpr' s)
600 located func (p_hsExpr' s)
599 breakpoint
601 breakpoint
600− inciIf doIndent $ sep breakpoint (located' p_hsExpr) initp
602+ indent $ sep breakpoint (located' p_hsExpr) initp
601− inciIf doIndent $ do
603+ indent $ do
602 unless (null initp) breakpoint
604 unless (null initp) breakpoint
603 located lastp p_hsExpr
605 located lastp p_hsExpr
604 Hanging -> do
606 Hanging -> do
@@ -613,15 +615,10 @@ p_hsExpr' s = \case
613 breakpoint
615 breakpoint
614 inci $ do
616 inci $ do
615 txt "@"
617 txt "@"
616− -- Insert a space when the type is represented as a TH splice to avoid
617− -- gluing @ and $ together.
618− case unLoc (hswc_body a) of
619− HsSpliceTy {} -> space
620− _ -> return ()
621 located (hswc_body a) p_hsType
618 located (hswc_body a) p_hsType
622 OpApp NoExtField x op y -> do
619 OpApp NoExtField x op y -> do
623 let opTree = OpBranch (exprOpTree x) op (exprOpTree y)
620 let opTree = OpBranch (exprOpTree x) op (exprOpTree y)
624− p_exprOpTree s (reassociateOpTree getOpName opTree)
621+ p_exprOpTree True s (reassociateOpTree getOpName opTree)
625 NegApp NoExtField e _ -> do
622 NegApp NoExtField e _ -> do
626 txt "-"
623 txt "-"
627 space
624 space
@@ -638,27 +635,22 @@ p_hsExpr' s = \case
638 let isRecordDot' = isRecordDot (unLoc op) (getLoc x)
635 let isRecordDot' = isRecordDot (unLoc op) (getLoc x)
639 unless (useRecordDot' && isRecordDot') breakpoint
636 unless (useRecordDot' && isRecordDot') breakpoint
640 inci (located x p_hsExpr)
637 inci (located x p_hsExpr)
641− ExplicitTuple NoExtField args boxity ->
638+ ExplicitTuple NoExtField args boxity -> do
642 let isSection = any (isMissing . unLoc) args
639 let isSection = any (isMissing . unLoc) args
643 isMissing = \case
640 isMissing = \case
644 Missing NoExtField -> True
641 Missing NoExtField -> True
645 _ -> False
642 _ -> False
646− p_arg = \case
647− Present NoExtField x -> located x p_hsExpr
648− Missing NoExtField -> pure ()
649− XTupArg x -> noExtCon x
650− p_larg = sitcc . located' p_arg
651− parens' =
643+ let parens' =
652 case boxity of
644 case boxity of
653 Boxed -> parens
645 Boxed -> parens
654 Unboxed -> parensHash
646 Unboxed -> parensHash
655− in if isSection
647+ if isSection
656− then
648+ then
657− switchLayout [] . parens' s $
649+ switchLayout [] . parens' s $
658− sep comma p_larg args
650+ sep comma (located' p_hsTupArg) args
659− else
651+ else
660− switchLayout (getLoc <$> args) . parens' s $
652+ switchLayout (getLoc <$> args) . parens' s . sitcc $
661− sep commaDel p_larg args
653+ sep (comma >> breakpoint) (sitcc . located' p_hsTupArg) args
662 ExplicitSum NoExtField tag arity e ->
654 ExplicitSum NoExtField tag arity e ->
663 p_unboxedSum N tag arity (located e p_hsExpr)
655 p_unboxedSum N tag arity (located e p_hsExpr)
664 HsCase NoExtField e mgroup ->
656 HsCase NoExtField e mgroup ->
@@ -666,9 +658,8 @@ p_hsExpr' s = \case
666 HsIf NoExtField _ if' then' else' ->
658 HsIf NoExtField _ if' then' else' ->
667 p_if exprPlacement p_hsExpr if' then' else'
659 p_if exprPlacement p_hsExpr if' then' else'
668 HsMultiIf NoExtField guards -> do
660 HsMultiIf NoExtField guards -> do
669− txt "if"
661+ txt "if "
670− breakpoint
671− inci . inci $ sep newline (located' (p_grhs RightArrow)) guards
662+ inci . inci . sitcc $ sep newline (located' (p_grhs RightArrow)) guards
672 HsLet NoExtField localBinds e ->
663 HsLet NoExtField localBinds e ->
673 p_let p_hsExpr localBinds e
664 p_let p_hsExpr localBinds e
674 HsDo NoExtField ctx es -> do
665 HsDo NoExtField ctx es -> do
@@ -680,15 +671,15 @@ p_hsExpr' s = \case
680 sepSemi
671 sepSemi
681 (ub . withSpacing (p_stmt' exprPlacement (p_hsExpr' S)))
672 (ub . withSpacing (p_stmt' exprPlacement (p_hsExpr' S)))
682 (unLoc es)
673 (unLoc es)
683− compBody = brackets N . located es $ \xs -> do
674+ compBody = brackets N $ located es $ \xs -> do
684 let p_parBody =
675 let p_parBody =
685 sep
676 sep
686− (breakpoint >> txt "|" >> space)
677+ (breakpoint >> txt "| ")
687 p_seqBody
678 p_seqBody
688 p_seqBody =
679 p_seqBody =
689 sitcc
680 sitcc
690 . sep
681 . sep
691− commaDel
682+ (comma >> breakpoint)
692 (located' (sitcc . p_stmt))
683 (located' (sitcc . p_stmt))
693 stmts = init xs
684 stmts = init xs
694 yield = last xs
685 yield = last xs
@@ -709,8 +700,8 @@ p_hsExpr' s = \case
709 ParStmtCtxt _ -> notImplemented "ParStmtCtxt"
700 ParStmtCtxt _ -> notImplemented "ParStmtCtxt"
710 TransStmtCtxt _ -> notImplemented "TransStmtCtxt"
701 TransStmtCtxt _ -> notImplemented "TransStmtCtxt"
711 ExplicitList _ _ xs ->
702 ExplicitList _ _ xs ->
712− brackets s $
703+ brackets s . sitcc $
713− sep commaDel (sitcc . located' p_hsExpr) xs
704+ sep (comma >> breakpoint) (sitcc . located' p_hsExpr) xs
714 RecordCon {..} -> do
705 RecordCon {..} -> do
715 located rcon_con_name atom
706 located rcon_con_name atom
716 breakpoint
707 breakpoint
@@ -726,8 +717,8 @@ p_hsExpr' s = \case
726 case rec_dotdot of
717 case rec_dotdot of
727 Just {} -> [txt ".."]
718 Just {} -> [txt ".."]
728 Nothing -> []
719 Nothing -> []
729− inci . braces N $
720+ inci . braces N . sitcc $
730− sep commaDel sitcc (fields <> dotdot)
721+ sep (comma >> breakpoint) sitcc (fields <> dotdot)
731 RecordUpd {..} -> do
722 RecordUpd {..} -> do
732 located rupd_expr p_hsExpr
723 located rupd_expr p_hsExpr
733 useRecordDot' <- useRecordDot
724 useRecordDot' <- useRecordDot
@@ -745,9 +736,9 @@ p_hsExpr' s = \case
745 Unambiguous _ n -> n
736 Unambiguous _ n -> n
746 XAmbiguousFieldOcc x -> noExtCon x
737 XAmbiguousFieldOcc x -> noExtCon x
747 }
738 }
748− inci . braces N $
739+ inci . braces N . sitcc $
749 sep
740 sep
750− commaDel
741+ (comma >> breakpoint)
751 (sitcc . located' (p_hsRecField . updName))
742 (sitcc . located' (p_hsRecField . updName))
752 rupd_flds
743 rupd_flds
753 ExprWithTySig NoExtField x HsWC {hswc_body = HsIB {..}} -> sitcc $ do
744 ExprWithTySig NoExtField x HsWC {hswc_body = HsIB {..}} -> sitcc $ do
@@ -760,22 +751,22 @@ p_hsExpr' s = \case
760 ExprWithTySig NoExtField _ (XHsWildCardBndrs x) -> noExtCon x
751 ExprWithTySig NoExtField _ (XHsWildCardBndrs x) -> noExtCon x
761 ArithSeq NoExtField _ x ->
752 ArithSeq NoExtField _ x ->
762 case x of
753 case x of
763− From from -> brackets s $ do
754+ From from -> brackets s . sitcc $ do
764 located from p_hsExpr
755 located from p_hsExpr
765 breakpoint
756 breakpoint
766 txt ".."
757 txt ".."
767− FromThen from next -> brackets s $ do
758+ FromThen from next -> brackets s . sitcc $ do
768− sep commaDel (located' p_hsExpr) [from, next]
759+ sitcc $ sep (comma >> breakpoint) (located' p_hsExpr) [from, next]
769 breakpoint
760 breakpoint
770 txt ".."
761 txt ".."
771− FromTo from to -> brackets s $ do
762+ FromTo from to -> brackets s . sitcc $ do
772 located from p_hsExpr
763 located from p_hsExpr
773 breakpoint
764 breakpoint
774 txt ".."
765 txt ".."
775 space
766 space
776 located to p_hsExpr
767 located to p_hsExpr
777− FromThenTo from next to -> brackets s $ do
768+ FromThenTo from next to -> brackets s . sitcc $ do
778− sep commaDel (located' p_hsExpr) [from, next]
769+ sitcc $ sep (comma >> breakpoint) (located' p_hsExpr) [from, next]
779 breakpoint
770 breakpoint
780 txt ".."
771 txt ".."
781 space
772 space
@@ -825,7 +816,7 @@ p_patSynBind PSB {..} = do
825 breakpoint
816 breakpoint
826 located psb_def p_pat
817 located psb_def p_pat
827 ImplicitBidirectional -> do
818 ImplicitBidirectional -> do
828− equals
819+ txt "="
829 breakpoint
820 breakpoint
830 located psb_def p_pat
821 located psb_def p_pat
831 ExplicitBidirectional mgroup -> do
822 ExplicitBidirectional mgroup -> do
@@ -852,8 +843,8 @@ p_patSynBind PSB {..} = do
852 inci $ do
843 inci $ do
853 switchLayout (getLoc . recordPatSynPatVar <$> xs) $ do
844 switchLayout (getLoc . recordPatSynPatVar <$> xs) $ do
854 unless (null xs) breakpoint
845 unless (null xs) breakpoint
855− braces N $
846+ braces N . sitcc $
856− sep commaDel (p_rdrName . recordPatSynPatVar) xs
847+ sep (comma >> breakpoint) (p_rdrName . recordPatSynPatVar) xs
857 rhs
848 rhs
858 InfixCon l r -> do
849 InfixCon l r -> do
859 switchLayout [getLoc l, getLoc r] $ do
850 switchLayout [getLoc l, getLoc r] $ do
@@ -907,12 +898,10 @@ p_if placer render if' then' else' = do
907 breakpoint
898 breakpoint
908 inci $ do
899 inci $ do
909 txt "then"
900 txt "then"
910− space
911 located then' $ \x ->
901 located then' $ \x ->
912 placeHanging (placer x) (render x)
902 placeHanging (placer x) (render x)
913 breakpoint
903 breakpoint
914 txt "else"
904 txt "else"
915− space
916 located else' $ \x ->
905 located else' $ \x ->
917 placeHanging (placer x) (render x)
906 placeHanging (placer x) (render x)
918
907
@@ -949,13 +938,13 @@ p_pat = \case
949 txt "!"
938 txt "!"
950 located pat p_pat
939 located pat p_pat
951 ListPat NoExtField pats ->
940 ListPat NoExtField pats ->
952− brackets S $ sep commaDel (located' p_pat) pats
941+ brackets S . sitcc $ sep (comma >> breakpoint) (located' p_pat) pats
953 TuplePat NoExtField pats boxing -> do
942 TuplePat NoExtField pats boxing -> do
954− let parens' =
943+ let f =
955 case boxing of
944 case boxing of
956 Boxed -> parens S
945 Boxed -> parens S
957 Unboxed -> parensHash S
946 Unboxed -> parensHash S
958− parens' $ sep commaDel (sitcc . located' p_pat) pats
947+ f . sitcc $ sep (comma >> breakpoint) (sitcc . located' p_pat) pats
959 SumPat NoExtField pat tag arity ->
948 SumPat NoExtField pat tag arity ->
960 p_unboxedSum S tag arity (located pat p_pat)
949 p_unboxedSum S tag arity (located pat p_pat)
961 ConPatIn pat details ->
950 ConPatIn pat details ->
@@ -971,7 +960,7 @@ p_pat = \case
971 let f = \case
960 let f = \case
972 Nothing -> txt ".."
961 Nothing -> txt ".."
973 Just x -> located x p_pat_hsRecField
962 Just x -> located x p_pat_hsRecField
974− inci . braces N . sep commaDel f $
963+ inci . braces N . sitcc . sep (comma >> breakpoint) f $
975 case dotdot of
964 case dotdot of
976 Nothing -> Just <$> fields
965 Nothing -> Just <$> fields
977 Just (L _ n) -> (Just <$> take n fields) ++ [Nothing]
966 Just (L _ n) -> (Just <$> take n fields) ++ [Nothing]
@@ -1012,7 +1001,7 @@ p_pat_hsRecField HsRecField {..} = do
1012 p_rdrName (rdrNameFieldOcc x)
1001 p_rdrName (rdrNameFieldOcc x)
1013 unless hsRecPun $ do
1002 unless hsRecPun $ do
1014 space
1003 space
1015− equals
1004+ txt "="
1016 breakpoint
1005 breakpoint
1017 inci (located hsRecFieldArg p_pat)
1006 inci (located hsRecFieldArg p_pat)
1018
1007
@@ -1021,15 +1010,17 @@ p_unboxedSum s tag arity m = do
1021 let before = tag - 1
1010 let before = tag - 1
1022 after = arity - before - 1
1011 after = arity - before - 1
1023 args = replicate before Nothing <> [Just m] <> replicate after Nothing
1012 args = replicate before Nothing <> [Just m] <> replicate after Nothing
1024− f x =
1013+ f (x, i) = do
1014+ let isFirst = i == 0
1015+ isLast = i == arity - 1
1025 case x :: Maybe (R ()) of
1016 case x :: Maybe (R ()) of
1026 Nothing ->
1017 Nothing ->
1027− space
1018+ unless (isFirst || isLast) space
1028 Just m' -> do
1019 Just m' -> do
1029− space
1020+ unless isFirst space
1030 m'
1021 m'
1031− space
1022+ unless isLast space
1032− parensHash s $ sep (txt "|") f args
1023+ parensHash s $ sep (txt "|") f (zip args [0 ..])
1033
1024
1034p_hsSplice :: HsSplice GhcPs -> R ()
1025p_hsSplice :: HsSplice GhcPs -> R ()
1035p_hsSplice = \case
1026p_hsSplice = \case
@@ -1231,10 +1222,11 @@ exprPlacement = \case
1231 HsCase NoExtField _ _ -> Hanging
1222 HsCase NoExtField _ _ -> Hanging
1232 HsDo NoExtField DoExpr _ -> Hanging
1223 HsDo NoExtField DoExpr _ -> Hanging
1233 HsDo NoExtField MDoExpr _ -> Hanging
1224 HsDo NoExtField MDoExpr _ -> Hanging
1234− OpApp NoExtField _ op y ->
1225+ -- If the rightmost expression in an operator chain is hanging, make the
1235− case (fmap getOpNameStr . getOpName . unLoc) op of
1226+ -- whole block hanging; so that we can use the common @f = foo $ do@
1227+ -- style.
1236− Just "$" -> exprPlacement (unLoc y)
1228+ OpApp NoExtField _ _ y -> exprPlacement (unLoc y)
1237− _ -> Normal
1229+ -- Same thing for function applications (usually with -XBlockArguments)
1238 HsApp NoExtField _ y -> exprPlacement (unLoc y)
1230 HsApp NoExtField _ y -> exprPlacement (unLoc y)
1239 HsProc NoExtField p _ ->
1231 HsProc NoExtField p _ ->
1240 -- Indentation breaks if pattern is longer than one line and left
1232 -- Indentation breaks if pattern is longer than one line and left
@@ -1260,16 +1252,15 @@ getOpName = \case
1260 HsVar NoExtField (L _ a) -> Just a
1252 HsVar NoExtField (L _ a) -> Just a
1261 _ -> Nothing
1253 _ -> Nothing
1262
1254
1263−getOpNameStr :: RdrName -> String
1264−getOpNameStr = occNameString . rdrNameOcc
1265−
1266p_exprOpTree ::
1255p_exprOpTree ::
1256+ -- | Can use special handling of dollar?
1257+ Bool ->
1267 -- | Bracket style to use
1258 -- | Bracket style to use
1268 BracketStyle ->
1259 BracketStyle ->
1269 OpTree (LHsExpr GhcPs) (LHsExpr GhcPs) ->
1260 OpTree (LHsExpr GhcPs) (LHsExpr GhcPs) ->
1270 R ()
1261 R ()
1271−p_exprOpTree s (OpNode x) = located x (p_hsExpr' s)
1262+p_exprOpTree _ s (OpNode x) = located x (p_hsExpr' s)
1272−p_exprOpTree s (OpBranch x op y) = do
1263+p_exprOpTree isDollarSpecial s (OpBranch x op y) = do
1273 -- If the beginning of the first argument and the second argument are on
1264 -- If the beginning of the first argument and the second argument are on
1274 -- the same line, and the second argument has a hanging form, use hanging
1265 -- the same line, and the second argument has a hanging form, use hanging
1275 -- placement.
1266 -- placement.
@@ -1291,54 +1282,44 @@ p_exprOpTree s (OpBranch x op y) = do
1291 MultiLine -> case placement of
1282 MultiLine -> case placement of
1292 Hanging -> useBraces
1283 Hanging -> useBraces
1293 Normal -> dontUseBraces
1284 Normal -> dontUseBraces
1294− opNameStr = (fmap getOpNameStr . getOpName . unLoc) op
1285+ gotDollar = case getOpName (unLoc op) of
1295− gotDollar = opNameStr == Just "$"
1286+ Just rname -> mkVarOcc "$" == rdrNameOcc rname
1296− gotColon = opNameStr == Just ":"
1287+ _ -> False
1297− gotRecordDot = isRecordDot (unLoc op) (opTreeLoc y)
1298 lhs =
1288 lhs =
1299 switchLayout [opTreeLoc x] $
1289 switchLayout [opTreeLoc x] $
1300− p_exprOpTree s x
1290+ p_exprOpTree (not gotDollar) s x
1301− p_op = located op (opWrapper . p_hsExpr)
1291+ let p_op = located op (opWrapper . p_hsExpr)
1302− p_y = switchLayout [opTreeLoc y] (p_exprOpTree N y)
1292+ p_y = switchLayout [opTreeLoc y] (p_exprOpTree True N y)
1303 isSection = case (opTreeLoc x, getLoc op) of
1293 isSection = case (opTreeLoc x, getLoc op) of
1304 (RealSrcSpan treeSpan, RealSrcSpan opSpan) ->
1294 (RealSrcSpan treeSpan, RealSrcSpan opSpan) ->
1305 srcSpanEndCol treeSpan /= srcSpanStartCol opSpan
1295 srcSpanEndCol treeSpan /= srcSpanStartCol opSpan
1306 _ -> False
1296 _ -> False
1307− isDoBlock = \case
1308− OpNode (L _ HsDo {}) -> True
1309− _ -> False
1310 useRecordDot' <- useRecordDot
1297 useRecordDot' <- useRecordDot
1311− if
1298+ let isRecordDot' = isRecordDot (unLoc op) (opTreeLoc y)
1312− | gotColon -> do
1299+ if useRecordDot' && isRecordDot'
1313− lhs
1300+ then do
1301+ lhs
1302+ when isSection space
1303+ p_op
1304+ p_y
1305+ else
1306+ if isDollarSpecial
1307+ && gotDollar
1308+ && placement
1309+ == Normal
1310+ && isOneLineSpan (opTreeLoc x)
1311+ then do
1312+ useBraces lhs
1314− space
1313+ space
1315− p_op
1314+ p_op
1316− case placement of
1315+ breakpoint
1317− Hanging -> do
1316+ inci p_y
1317+ else do
1318+ ub lhs
1319+ placeHanging placement $ do
1320+ p_op
1318 space
1321 space
1319 p_y
1322 p_y
1320− Normal -> do
1321− breakpoint
1322− inciIf (isDoBlock y) p_y
1323− | gotDollar
1324− && isOneLineSpan (opTreeLoc x)
1325− && placement == Normal -> do
1326− useBraces lhs
1327− space
1328− p_op
1329− breakpoint
1330− inci p_y
1331− | useRecordDot' && gotRecordDot -> do
1332− lhs
1333− when isSection space
1334− p_op
1335− p_y
1336− | otherwise -> do
1337− ub lhs
1338− placeHanging placement $ do
1339− p_op
1340− space
1341− p_y
1342
1323
1343-- | Return 'True' if given expression is a record-dot operator expression.
1324-- | Return 'True' if given expression is a record-dot operator expression.
1344isRecordDot ::
1325isRecordDot ::
@@ -1349,10 +1330,14 @@ isRecordDot ::
1349 Bool
1330 Bool
1350isRecordDot op (RealSrcSpan ySpan) = case op of
1331isRecordDot op (RealSrcSpan ySpan) = case op of
1351 HsVar NoExtField (L (RealSrcSpan opSpan) opName) ->
1332 HsVar NoExtField (L (RealSrcSpan opSpan) opName) ->
1352− (getOpNameStr opName == ".") && (srcSpanEndCol opSpan == srcSpanStartCol ySpan)
1333+ isDot opName && (srcSpanEndCol opSpan == srcSpanStartCol ySpan)
1353 _ -> False
1334 _ -> False
1354isRecordDot _ _ = False
1335isRecordDot _ _ = False
1355
1336
1337+-- | Check whether a given 'RdrName' is the dot operator.
1338+isDot :: RdrName -> Bool
1339+isDot name = rdrNameOcc name == mkVarOcc "."
1340+
1356-- | Get annotations for the enclosing element.
1341-- | Get annotations for the enclosing element.
1357getEnclosingAnns :: R [AnnKeywordId]
1342getEnclosingAnns :: R [AnnKeywordId]
1358getEnclosingAnns = do
1343getEnclosingAnns = do
src/Ormolu/Printer/Meat/Declaration/Value.hs-boot+4
@@ -11,7 +11,11 @@ import GHC
11import Ormolu.Printer.Combinators
11import Ormolu.Printer.Combinators
12
12
13p_valDecl :: HsBindLR GhcPs GhcPs -> R ()
13p_valDecl :: HsBindLR GhcPs GhcPs -> R ()
14+
14p_pat :: Pat GhcPs -> R ()
15p_pat :: Pat GhcPs -> R ()
16+
15p_hsExpr :: HsExpr GhcPs -> R ()
17p_hsExpr :: HsExpr GhcPs -> R ()
18+
16p_hsSplice :: HsSplice GhcPs -> R ()
19p_hsSplice :: HsSplice GhcPs -> R ()
20+
17p_stringLit :: String -> R ()
21p_stringLit :: String -> R ()
src/Ormolu/Printer/Meat/Declaration/Warning.hs+8−5
@@ -27,14 +27,17 @@ p_warnDecl (XWarnDecl x) = noExtCon x
27p_moduleWarning :: WarningTxt -> R ()
27p_moduleWarning :: WarningTxt -> R ()
28p_moduleWarning wtxt = do
28p_moduleWarning wtxt = do
29 let (pragmaText, lits) = warningText wtxt
29 let (pragmaText, lits) = warningText wtxt
30+ switchLayout (getLoc <$> lits)
31+ $ inci
30− inci $ pragma pragmaText $ inci $ p_lits lits
32+ $ pragma pragmaText (inci $ p_lits lits)
31
33
32p_topLevelWarning :: [Located RdrName] -> WarningTxt -> R ()
34p_topLevelWarning :: [Located RdrName] -> WarningTxt -> R ()
33p_topLevelWarning fnames wtxt = do
35p_topLevelWarning fnames wtxt = do
34 let (pragmaText, lits) = warningText wtxt
36 let (pragmaText, lits) = warningText wtxt
35− switchLayout (fmap getLoc fnames ++ fmap getLoc lits) $
37+ switchLayout (fmap getLoc fnames ++ fmap getLoc lits)
36− pragma pragmaText . inci $ do
38+ $ pragma pragmaText . inci
39+ $ do
37− sep commaDel p_rdrName fnames
40+ sitcc $ sep (comma >> breakpoint) p_rdrName fnames
38 breakpoint
41 breakpoint
39 p_lits lits
42 p_lits lits
40
43
@@ -46,4 +49,4 @@ warningText = \case
46p_lits :: [Located StringLiteral] -> R ()
49p_lits :: [Located StringLiteral] -> R ()
47p_lits = \case
50p_lits = \case
48 [l] -> atom l
51 [l] -> atom l
49− ls -> brackets N $ sep commaDel atom ls
52+ ls -> brackets N . sitcc $ sep (comma >> breakpoint) atom ls
src/Ormolu/Printer/Meat/ImportExport.hs+20−26
@@ -13,7 +13,6 @@ import Control.Monad
13import GHC
13import GHC
14import Ormolu.Printer.Combinators
14import Ormolu.Printer.Combinators
15import Ormolu.Printer.Meat.Common
15import Ormolu.Printer.Meat.Common
16−import Ormolu.Utils (RelativePos (..), attachRelativePos)
17
16
18p_hsmodExports :: [LIE GhcPs] -> R ()
17p_hsmodExports :: [LIE GhcPs] -> R ()
19p_hsmodExports [] = do
18p_hsmodExports [] = do
@@ -21,12 +20,9 @@ p_hsmodExports [] = do
21 breakpoint'
20 breakpoint'
22 txt ")"
21 txt ")"
23p_hsmodExports xs =
22p_hsmodExports xs =
24− parens N $ do
23+ parens N . sitcc $ do
25 layout <- getLayout
24 layout <- getLayout
26− sep
27− breakpoint
28− (\(p, l) -> sitcc (located l (p_lie layout p)))
25+ sep breakpoint (sitcc . located' (uncurry (p_lie layout))) (attachPositions xs)
29− (attachRelativePos xs)
30
26
31p_hsmodImport :: Bool -> ImportDecl GhcPs -> R ()
27p_hsmodImport :: Bool -> ImportDecl GhcPs -> R ()
32p_hsmodImport useQualifiedPost ImportDecl {..} = do
28p_hsmodImport useQualifiedPost ImportDecl {..} = do
@@ -65,17 +61,14 @@ p_hsmodImport useQualifiedPost ImportDecl {..} = do
65 Nothing -> return ()
61 Nothing -> return ()
66 Just (_, L _ xs) -> do
62 Just (_, L _ xs) -> do
67 breakpoint
63 breakpoint
68− parens N $ do
64+ parens N . sitcc $ do
69 layout <- getLayout
65 layout <- getLayout
70− sep
71− breakpoint
72− (\(p, l) -> sitcc (located l (p_lie layout p)))
66+ sep breakpoint (sitcc . located' (uncurry (p_lie layout))) (attachPositions xs)
73− (attachRelativePos xs)
74 newline
67 newline
75p_hsmodImport _ (XImportDecl x) = noExtCon x
68p_hsmodImport _ (XImportDecl x) = noExtCon x
76
69
77−p_lie :: Layout -> RelativePos -> IE GhcPs -> R ()
70+p_lie :: Layout -> (Int, Int) -> IE GhcPs -> R ()
78−p_lie encLayout relativePos = \case
71+p_lie encLayout (i, totalItems) = \case
79 IEVar NoExtField l1 -> do
72 IEVar NoExtField l1 -> do
80 located l1 p_ieWrappedName
73 located l1 p_ieWrappedName
81 p_comma
74 p_comma
@@ -93,8 +86,9 @@ p_lie encLayout relativePos = \case
93 inci $ do
86 inci $ do
94 let names :: [R ()]
87 let names :: [R ()]
95 names = located' p_ieWrappedName <$> xs
88 names = located' p_ieWrappedName <$> xs
96− parens N . sep commaDel sitcc $
89+ parens N . sitcc
90+ $ sep (comma >> breakpoint) sitcc
97− case w of
91+ $ case w of
98 NoIEWildcard -> names
92 NoIEWildcard -> names
99 IEWildcard n ->
93 IEWildcard n ->
100 let (before, after) = splitAt n names
94 let (before, after) = splitAt n names
@@ -104,11 +98,7 @@ p_lie encLayout relativePos = \case
104 located l1 p_hsmodName
98 located l1 p_hsmodName
105 p_comma
99 p_comma
106 IEGroup NoExtField n str -> do
100 IEGroup NoExtField n str -> do
107− case relativePos of
108− SinglePos -> return ()
109− FirstPos -> return ()
110− MiddlePos -> newline
111− LastPos -> newline
101+ unless (i == 0) newline
112 p_hsDocString (Asterisk n) False (noLoc str)
102 p_hsDocString (Asterisk n) False (noLoc str)
113 IEDoc NoExtField str ->
103 IEDoc NoExtField str ->
114 p_hsDocString Pipe False (noLoc str)
104 p_hsDocString Pipe False (noLoc str)
@@ -117,10 +107,14 @@ p_lie encLayout relativePos = \case
117 where
107 where
118 p_comma =
108 p_comma =
119 case encLayout of
109 case encLayout of
120− SingleLine ->
110+ SingleLine -> unless (i + 1 == totalItems) comma
121− case relativePos of
122− SinglePos -> return ()
123− FirstPos -> comma
124− MiddlePos -> comma
125− LastPos -> return ()
126 MultiLine -> comma
111 MultiLine -> comma
112+
113+-- | Attach positions to 'Located' things in a list.
114+attachPositions ::
115+ [Located a] ->
116+ [Located ((Int, Int), a)]
117+attachPositions xs =
118+ let f i (L l x) = L l ((i, n), x)
119+ n = length xs
120+ in zipWith f [0 ..] xs
src/Ormolu/Printer/Meat/Module.hs+15−12
@@ -11,7 +11,7 @@ where
11import Control.Monad
11import Control.Monad
12import qualified Data.Text as T
12import qualified Data.Text as T
13import GHC
13import GHC
14−import Ormolu.Imports (normalizeImports)
14+import Ormolu.Imports
15import Ormolu.Parser.CommentStream
15import Ormolu.Parser.CommentStream
16import Ormolu.Parser.Pragma
16import Ormolu.Parser.Pragma
17import Ormolu.Parser.Shebang
17import Ormolu.Parser.Shebang
@@ -34,12 +34,16 @@ p_hsModule ::
34 -- | Whether to use postfix qualified imports
34 -- | Whether to use postfix qualified imports
35 Bool ->
35 Bool ->
36 -- | AST to print
36 -- | AST to print
37− HsModule GhcPs ->
37+ ParsedSource ->
38 R ()
38 R ()
39−p_hsModule mstackHeader shebangs pragmas qualifiedPost HsModule {..} = do
39+p_hsModule mstackHeader shebangs pragmas qualifiedPost (L moduleSpan HsModule {..}) = do
40− let deprecSpan = maybe [] (\(L s _) -> [s]) hsmodDeprecMessage
40+ -- If span of exports in multiline, the whole thing is multiline. This is
41+ -- especially important because span of module itself always seems to have
42+ -- length zero, so it's not reliable for layout selection.
41− exportSpans = maybe [] (\(L s _) -> [s]) hsmodExports
43+ let exportSpans = maybe [] (\(L s _) -> [s]) hsmodExports
44+ deprecSpan = maybe [] (\(L s _) -> [s]) hsmodDeprecMessage
45+ spans' = exportSpans ++ deprecSpan ++ [moduleSpan]
42− switchLayout (deprecSpan <> exportSpans) $ do
46+ switchLayout spans' $ do
43 forM_ shebangs $ \(Shebang x) ->
47 forM_ shebangs $ \(Shebang x) ->
44 located x $ \shebang -> do
48 located x $ \shebang -> do
45 txt (T.pack shebang)
49 txt (T.pack shebang)
@@ -56,20 +60,19 @@ p_hsModule mstackHeader shebangs pragmas qualifiedPost HsModule {..} = do
56 located hsmodName' $ \name -> do
60 located hsmodName' $ \name -> do
57 forM_ hsmodHaddockModHeader (p_hsDocString Pipe True)
61 forM_ hsmodHaddockModHeader (p_hsDocString Pipe True)
58 p_hsmodName name
62 p_hsmodName name
59− breakpoint
60 forM_ hsmodDeprecMessage $ \w -> do
63 forM_ hsmodDeprecMessage $ \w -> do
61− located' p_moduleWarning w
62 breakpoint
64 breakpoint
65+ located' p_moduleWarning w
63 case hsmodExports of
66 case hsmodExports of
64 Nothing -> return ()
67 Nothing -> return ()
65− Just l -> do
68+ Just hsmodExports' -> do
66− located l $ \exports -> do
67− inci (p_hsmodExports exports)
68 breakpoint
69 breakpoint
70+ inci (p_hsmodExports (unLoc hsmodExports'))
71+ breakpoint
69 txt "where"
72 txt "where"
70 newline
73 newline
71 newline
74 newline
72− forM_ (normalizeImports hsmodImports) (located' (p_hsmodImport qualifiedPost))
75+ forM_ (sortImports hsmodImports) (located' (p_hsmodImport qualifiedPost))
73 newline
76 newline
74 switchLayout (getLoc <$> hsmodDecls) $ do
77 switchLayout (getLoc <$> hsmodDecls) $ do
75 p_hsDecls Free hsmodDecls
78 p_hsDecls Free hsmodDecls
src/Ormolu/Printer/Meat/Type.hs+24−35
@@ -5,7 +5,6 @@
5-- | Rendering of types.
5-- | Rendering of types.
6module Ormolu.Printer.Meat.Type
6module Ormolu.Printer.Meat.Type
7 ( p_hsType,
7 ( p_hsType,
8− p_hsTypePostDoc,
9 hasDocStrings,
8 hasDocStrings,
10 p_hsContext,
9 p_hsContext,
11 p_hsTyVarBndr,
10 p_hsTyVarBndr,
@@ -24,22 +23,14 @@ import Ormolu.Printer.Operators
24import Ormolu.Utils
23import Ormolu.Utils
25
24
26p_hsType :: HsType GhcPs -> R ()
25p_hsType :: HsType GhcPs -> R ()
27−p_hsType t = p_hsType' (hasDocStrings t) PipeStyle t
26+p_hsType t = p_hsType' (hasDocStrings t) t
28
27
29−p_hsTypePostDoc :: HsType GhcPs -> R ()
30−p_hsTypePostDoc t = p_hsType' (hasDocStrings t) CaretStyle t
31−
32−-- | How to render Haddocks associated with a type.
33−data TypeDocStyle
34− = PipeStyle
35− | CaretStyle
36−
37−p_hsType' :: Bool -> TypeDocStyle -> HsType GhcPs -> R ()
28+p_hsType' :: Bool -> HsType GhcPs -> R ()
38−p_hsType' multilineArgs docStyle = \case
29+p_hsType' multilineArgs = \case
39 HsForAllTy NoExtField visibility bndrs t -> do
30 HsForAllTy NoExtField visibility bndrs t -> do
40 p_forallBndrs visibility p_hsTyVarBndr bndrs
31 p_forallBndrs visibility p_hsTyVarBndr bndrs
41 interArgBreak
32 interArgBreak
42− p_hsTypeR (unLoc t)
33+ p_hsType' multilineArgs (unLoc t)
43 HsQualTy NoExtField qs t -> do
34 HsQualTy NoExtField qs t -> do
44 located qs p_hsContext
35 located qs p_hsContext
45 space
36 space
@@ -67,7 +58,7 @@ p_hsType' multilineArgs docStyle = \case
67 L _ (HsAppTy _ l r) -> gatherArgs l (r : knownArgs)
58 L _ (HsAppTy _ l r) -> gatherArgs l (r : knownArgs)
68 _ -> (f', knownArgs)
59 _ -> (f', knownArgs)
69 (func, args) = gatherArgs f [x]
60 (func, args) = gatherArgs f [x]
70− switchLayout (getLoc f : fmap getLoc args) . sitcc $ do
61+ switchLayout (getLoc f : fmap getLoc args) $ sitcc $ do
71 located func p_hsType
62 located func p_hsType
72 breakpoint
63 breakpoint
73 inci $
64 inci $
@@ -98,9 +89,10 @@ p_hsType' multilineArgs docStyle = \case
98 HsBoxedTuple -> parens N
89 HsBoxedTuple -> parens N
99 HsConstraintTuple -> parens N
90 HsConstraintTuple -> parens N
100 HsBoxedOrConstraintTuple -> parens N
91 HsBoxedOrConstraintTuple -> parens N
92+ in parens' . sitcc $
101− in parens' $ sep commaDel (sitcc . located' p_hsType) xs
93+ sep (comma >> breakpoint) (sitcc . located' p_hsType) xs
102 HsSumTy NoExtField xs ->
94 HsSumTy NoExtField xs ->
103− parensHash N $
95+ parensHash N . sitcc $
104 sep (txt "|" >> breakpoint) (sitcc . located' p_hsType) xs
96 sep (txt "|" >> breakpoint) (sitcc . located' p_hsType) xs
105 HsOpTy NoExtField x op y ->
97 HsOpTy NoExtField x op y ->
106 sitcc $
98 sitcc $
@@ -117,20 +109,14 @@ p_hsType' multilineArgs docStyle = \case
117 HsStarTy NoExtField _ -> txt "*"
109 HsStarTy NoExtField _ -> txt "*"
118 HsKindSig NoExtField t k -> sitcc $ do
110 HsKindSig NoExtField t k -> sitcc $ do
119 located t p_hsType
111 located t p_hsType
120− space
112+ space -- FIXME
121 txt "::"
113 txt "::"
122− breakpoint
114+ space
123 inci (located k p_hsType)
115 inci (located k p_hsType)
124 HsSpliceTy NoExtField splice -> p_hsSplice splice
116 HsSpliceTy NoExtField splice -> p_hsSplice splice
125− HsDocTy NoExtField t str ->
117+ HsDocTy NoExtField t str -> do
126− case docStyle of
127− PipeStyle -> do
128− p_hsDocString Pipe True str
118+ p_hsDocString Pipe True str
129− located t p_hsType
130− CaretStyle -> do
131− located t p_hsType
119+ located t p_hsType
132− newline
133− p_hsDocString Caret False str
134 HsBangTy NoExtField (HsSrcBang _ u s) t -> do
120 HsBangTy NoExtField (HsSrcBang _ u s) t -> do
135 case u of
121 case u of
136 SrcUnpack -> txt "{-# UNPACK #-}" >> space
122 SrcUnpack -> txt "{-# UNPACK #-}" >> space
@@ -153,14 +139,14 @@ p_hsType' multilineArgs docStyle = \case
153 case (p, xs) of
139 case (p, xs) of
154 (IsPromoted, L _ t : _) | isPromoted t -> space
140 (IsPromoted, L _ t : _) | isPromoted t -> space
155 _ -> return ()
141 _ -> return ()
156− sep commaDel (sitcc . located' p_hsType) xs
142+ sitcc $ sep (comma >> breakpoint) (sitcc . located' p_hsType) xs
157 HsExplicitTupleTy NoExtField xs -> do
143 HsExplicitTupleTy NoExtField xs -> do
158 txt "'"
144 txt "'"
159 parens N $ do
145 parens N $ do
160 case xs of
146 case xs of
161 L _ t : _ | isPromoted t -> space
147 L _ t : _ | isPromoted t -> space
162 _ -> return ()
148 _ -> return ()
163− sep commaDel (located' p_hsType) xs
149+ sep (comma >> breakpoint) (located' p_hsType) xs
164 HsTyLit NoExtField t ->
150 HsTyLit NoExtField t ->
165 case t of
151 case t of
166 HsStrTy (SourceText s) _ -> p_stringLit s
152 HsStrTy (SourceText s) _ -> p_stringLit s
@@ -170,14 +156,14 @@ p_hsType' multilineArgs docStyle = \case
170 where
156 where
171 isPromoted = \case
157 isPromoted = \case
172 HsTyVar _ IsPromoted _ -> True
158 HsTyVar _ IsPromoted _ -> True
173− HsExplicitTupleTy {} -> True
174 HsExplicitListTy {} -> True
159 HsExplicitListTy {} -> True
160+ HsExplicitTupleTy {} -> True
175 _ -> False
161 _ -> False
176 interArgBreak =
162 interArgBreak =
177 if multilineArgs
163 if multilineArgs
178 then newline
164 then newline
179 else breakpoint
165 else breakpoint
180− p_hsTypeR = p_hsType' multilineArgs docStyle
166+ p_hsTypeR = p_hsType' multilineArgs
181
167
182-- | Return 'True' if at least one argument in 'HsType' has a doc string
168-- | Return 'True' if at least one argument in 'HsType' has a doc string
183-- attached to it.
169-- attached to it.
@@ -191,7 +177,9 @@ p_hsContext :: HsContext GhcPs -> R ()
191p_hsContext = \case
177p_hsContext = \case
192 [] -> txt "()"
178 [] -> txt "()"
193 [x] -> located x p_hsType
179 [x] -> located x p_hsType
180+ xs ->
181+ parens N . sitcc $
194− xs -> parens N $ sep commaDel (sitcc . located' p_hsType) xs
182+ sep (comma >> breakpoint) (sitcc . located' p_hsType) xs
195
183
196p_hsTyVarBndr :: HsTyVarBndr GhcPs -> R ()
184p_hsTyVarBndr :: HsTyVarBndr GhcPs -> R ()
197p_hsTyVarBndr = \case
185p_hsTyVarBndr = \case
@@ -221,14 +209,15 @@ p_forallBndrs vis p tyvars =
221
209
222p_conDeclFields :: [LConDeclField GhcPs] -> R ()
210p_conDeclFields :: [LConDeclField GhcPs] -> R ()
223p_conDeclFields xs =
211p_conDeclFields xs =
212+ braces N . sitcc $
224− braces N $ sep commaDel (sitcc . located' p_conDeclField) xs
213+ sep (comma >> breakpoint) (sitcc . located' p_conDeclField) xs
225
214
226p_conDeclField :: ConDeclField GhcPs -> R ()
215p_conDeclField :: ConDeclField GhcPs -> R ()
227p_conDeclField ConDeclField {..} = do
216p_conDeclField ConDeclField {..} = do
228 mapM_ (p_hsDocString Pipe True) cd_fld_doc
217 mapM_ (p_hsDocString Pipe True) cd_fld_doc
229 sitcc $
218 sitcc $
230 sep
219 sep
231− commaDel
220+ (comma >> breakpoint)
232 (located' (p_rdrName . rdrNameFieldOcc))
221 (located' (p_rdrName . rdrNameFieldOcc))
233 cd_fld_names
222 cd_fld_names
234 space
223 space
@@ -270,6 +259,6 @@ tyVarToType = \case
270 -- <https://gitlab.haskell.org/ghc/ghc/issues/17404>. This is fine as
259 -- <https://gitlab.haskell.org/ghc/ghc/issues/17404>. This is fine as
271 -- long as 'tyVarToType' does not get applied to right-hand sides of
260 -- long as 'tyVarToType' does not get applied to right-hand sides of
272 -- declarations.
261 -- declarations.
273− HsParTy NoExtField . noLoc $
262+ HsParTy NoExtField $ noLoc $
274 HsKindSig NoExtField (noLoc (HsTyVar NoExtField NotPromoted tvar)) kind
263 HsKindSig NoExtField (noLoc (HsTyVar NoExtField NotPromoted tvar)) kind
275 XTyVarBndr x -> noExtCon x
264 XTyVarBndr x -> noExtCon x
src/Ormolu/Printer/Operators.hs+59−46
@@ -12,11 +12,10 @@ where
12
12
13import Data.Function (on)
13import Data.Function (on)
14import qualified Data.List as L
14import qualified Data.List as L
15−import Data.Map.Strict (Map)
16−import qualified Data.Map.Strict as M
17import Data.Maybe (fromMaybe, mapMaybe)
15import Data.Maybe (fromMaybe, mapMaybe)
16+import Data.Ord (Down (Down), comparing)
18import GHC
17import GHC
19−import OccName (occNameString)
18+import OccName (mkVarOcc)
20import Ormolu.Utils (unSrcSpan)
19import Ormolu.Utils (unSrcSpan)
21
20
22-- | Intermediate representation of operator trees. It has two type
21-- | Intermediate representation of operator trees. It has two type
@@ -57,7 +56,7 @@ reassociateOpTree getOpName opTree =
57reassociateOpTreeWith ::
56reassociateOpTreeWith ::
58 forall ty op.
57 forall ty op.
59 -- | Fixity map for operators
58 -- | Fixity map for operators
60− Map String Fixity ->
59+ [(RdrName, Fixity)] ->
61 -- | How to get the name of an operator
60 -- | How to get the name of an operator
62 (op -> Maybe RdrName) ->
61 (op -> Maybe RdrName) ->
63 -- | Original 'OpTree'
62 -- | Original 'OpTree'
@@ -68,13 +67,13 @@ reassociateOpTreeWith fixityMap getOpName = go
68 where
67 where
69 fixityOf :: op -> Fixity
68 fixityOf :: op -> Fixity
70 fixityOf op = fromMaybe defaultFixity $ do
69 fixityOf op = fromMaybe defaultFixity $ do
71− s <- occNameString . rdrNameOcc <$> getOpName op
70+ opName <- getOpName op
72− M.lookup s fixityMap
71+ lookup opName fixityMap
73 -- Here, left branch is already associated and the root alongside with
72 -- Here, left branch is already associated and the root alongside with
74 -- the right branch is right-associated. This function picks up one item
73 -- the right branch is right-associated. This function picks up one item
75 -- from the right and inserts it correctly to the left.
74 -- from the right and inserts it correctly to the left.
76 --
75 --
77− -- Also, we are using the 'compareFixity' function which tells if the
76+ -- Also, we are using the 'compareFixity' function which returns if the
78 -- expression should associate to right.
77 -- expression should associate to right.
79 go :: OpTree ty op -> OpTree ty op
78 go :: OpTree ty op -> OpTree ty op
80 -- base cases
79 -- base cases
@@ -94,16 +93,6 @@ reassociateOpTreeWith fixityMap getOpName = go
94 then go $ OpBranch (OpBranch l op (go $ OpBranch r op' l')) op'' r'
93 then go $ OpBranch (OpBranch l op (go $ OpBranch r op' l')) op'' r'
95 else go $ OpBranch (OpBranch (OpBranch l op r) op' l') op'' r'
94 else go $ OpBranch (OpBranch (OpBranch l op r) op' l') op'' r'
96
95
97−-- | A score assigned to an operator.
98−data Score
99− = -- | The operator was placed at the beginning of a line
100− AtBeginning Int
101− | -- | The operator was placed at the end of a line
102− AtEnd
103− | -- | The operator was placed in between arguments on a single line
104− InBetween
105− deriving (Eq, Ord)
106−
107-- | Build a map of inferred 'Fixity's from an 'OpTree'.
96-- | Build a map of inferred 'Fixity's from an 'OpTree'.
108buildFixityMap ::
97buildFixityMap ::
109 forall ty op.
98 forall ty op.
@@ -112,26 +101,23 @@ buildFixityMap ::
112 -- | Operator tree
101 -- | Operator tree
113 OpTree (Located ty) (Located op) ->
102 OpTree (Located ty) (Located op) ->
114 -- | Fixity map
103 -- | Fixity map
115− Map String Fixity
104+ [(RdrName, Fixity)]
116buildFixityMap getOpName opTree =
105buildFixityMap getOpName opTree =
117− addOverrides
118− . M.fromList
119− . concatMap (\(i, ns) -> map (\(n, _) -> (n, fixity i InfixL)) ns)
106+ concatMap (\(i, ns) -> map (\(n, _) -> (n, fixity i InfixL)) ns)
120− . zip [2 ..]
107+ . zip [0 ..]
121− . L.groupBy ((==) `on` snd)
108+ . L.groupBy (doubleWithinEps 0.00001 `on` snd)
122− . selectScores
109+ . (overrides ++)
110+ . modeScores
123 $ score opTree
111 $ score opTree
124 where
112 where
125− addOverrides :: Map String Fixity -> Map String Fixity
113+ -- Add a special case for ($), since it is pretty unlikely for someone
126− addOverrides m =
114+ -- to override it.
127− M.fromList
115+ overrides :: [(RdrName, Double)]
128− [ ("$", fixity 0 InfixR),
116+ overrides =
129− (":", fixity 1 InfixR),
117+ [ (mkRdrUnqual $ mkVarOcc "$", -1)
130− (".", fixity 100 InfixL)
118+ ]
131− ]
119+ -- Assign scores to operators based on their location in the source.
132− `M.union` m
133− fixity = Fixity NoSourceText
134− score :: OpTree (Located ty) (Located op) -> [(String, Score)]
120+ score :: OpTree (Located ty) (Located op) -> [(RdrName, Double)]
135 score (OpNode _) = []
121 score (OpNode _) = []
136 score (OpBranch l o r) = fromMaybe (score r) $ do
122 score (OpBranch l o r) = fromMaybe (score r) $ do
137 -- If we fail to get any of these, 'defaultFixity' will be used by
123 -- If we fail to get any of these, 'defaultFixity' will be used by
@@ -141,27 +127,48 @@ buildFixityMap getOpName opTree =
141 oe <- srcSpanEndLine <$> unSrcSpan (getLoc o) -- operator end
127 oe <- srcSpanEndLine <$> unSrcSpan (getLoc o) -- operator end
142 rb <- srcSpanStartLine <$> unSrcSpan (opTreeLoc r) -- right begin
128 rb <- srcSpanStartLine <$> unSrcSpan (opTreeLoc r) -- right begin
143 oc <- srcSpanStartCol <$> unSrcSpan (getLoc o) -- operator column
129 oc <- srcSpanStartCol <$> unSrcSpan (getLoc o) -- operator column
144− opName <- occNameString . rdrNameOcc <$> getOpName (unLoc o)
130+ opName <- getOpName (unLoc o)
145 let s
131 let s
146− | le < ob = AtBeginning oc
132+ | le < ob =
133+ -- if the operator is in the beginning of a line, assign
134+ -- a score relative to its column within range [0, 1).
135+ fromIntegral oc / fromIntegral (maxCol + 1)
147− | oe < rb = AtEnd
136+ | oe < rb =
137+ -- if the operator is in the end of the line, assign the
138+ -- score 1.
139+ 1
148− | otherwise = InBetween
140+ | otherwise =
141+ 2 -- otherwise, assign a high score.
149 return $ (opName, s) : score r
142 return $ (opName, s) : score r
150− selectScores :: [(String, Score)] -> [(String, Score)]
143+ -- Pick the most common score per 'RdrName'.
151− selectScores =
144+ modeScores :: [(RdrName, Double)] -> [(RdrName, Double)]
145+ modeScores =
152 L.sortOn snd
146 L.sortOn snd
153 . mapMaybe
147 . mapMaybe
154 ( \case
148 ( \case
155 [] -> Nothing
149 [] -> Nothing
156− xs@((n, _) : _) -> Just (n, selectScore $ map snd xs)
150+ xs@((n, _) : _) -> Just (n, mode $ map snd xs)
157 )
151 )
158 . L.groupBy ((==) `on` fst)
152 . L.groupBy ((==) `on` fst)
159 . L.sort
153 . L.sort
160− selectScore :: [Score] -> Score
154+ -- Return the most common number, leaning to the smaller
161− selectScore xs =
155+ -- one in case of a tie.
162− case filter (/= InBetween) xs of
156+ mode :: [Double] -> Double
163− [] -> InBetween
157+ mode =
158+ head
159+ . L.minimumBy (comparing (Down . length))
160+ . L.groupBy (doubleWithinEps 0.0001)
161+ . L.sort
162+ -- The start column of the rightmost operator.
163+ maxCol = go opTree
164+ where
165+ go (OpNode (L _ _)) = 0
166+ go (OpBranch l (L o _) r) =
164− xs' -> maximum xs'
167+ maximum
168+ [ go l,
169+ maybe 0 srcSpanStartCol (unSrcSpan o),
170+ go r
171+ ]
165
172
166----------------------------------------------------------------------------
173----------------------------------------------------------------------------
167-- Helpers
174-- Helpers
@@ -175,3 +182,9 @@ normalizeOpTree (OpBranch (OpNode l) lop r) =
175 OpBranch (OpNode l) lop (normalizeOpTree r)
182 OpBranch (OpNode l) lop (normalizeOpTree r)
176normalizeOpTree (OpBranch (OpBranch l' lop' r') lop r) =
183normalizeOpTree (OpBranch (OpBranch l' lop' r') lop r) =
177 normalizeOpTree (OpBranch l' lop' (OpBranch r' lop r))
184 normalizeOpTree (OpBranch l' lop' (OpBranch r' lop r))
185+
186+fixity :: Int -> FixityDirection -> Fixity
187+fixity = Fixity NoSourceText
188+
189+doubleWithinEps :: Double -> Double -> Double -> Bool
190+doubleWithinEps eps a b = abs (a - b) < eps
src/Ormolu/Processing/Common.hs+1−1
@@ -20,7 +20,7 @@ data OrmoluState
20
20
21-- | Marker for the beginning of the region where Ormolu should be disabled.
21-- | Marker for the beginning of the region where Ormolu should be disabled.
22startDisabling :: IsString s => s
22startDisabling :: IsString s => s
23−startDisabling = "{- ORMOLU_DISABLE_START"
23+startDisabling = "{- ORMOLU_DISABLING_START"
24
24
25-- | Marker for the end of the region where Ormolu should be disabled.
25-- | Marker for the end of the region where Ormolu should be disabled.
26endDisabling :: IsString s => s
26endDisabling :: IsString s => s
src/Ormolu/Processing/Cpp.hsdeleted−70
@@ -1,70 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−
3−-- | Support for CPP.
4−module Ormolu.Processing.Cpp
5− ( State (..),
6− processLine,
7− unmaskLine,
8− )
9−where
10−
11−import Control.Monad
12−import Data.Char (isSpace)
13−import qualified Data.List as L
14−import Data.Maybe (isJust)
15−import Data.String
16−import Data.Text (Text)
17−import qualified Data.Text as T
18−
19−-- | State of the CPP processor.
20−data State
21− = -- | Outside of CPP directives
22− Outside
23− | -- | In a conditional expression
24− InConditional
25− | -- | In a continuation (after @\\@)
26− InContinuation
27− deriving (Eq, Show)
28−
29−-- | Automatically mask the line when needed and update the 'State'.
30−processLine :: String -> State -> (String, State)
31−processLine line state
32− | for "define " = (masked, state')
33− | for "include " = (masked, state')
34− | for "undef " = (masked, state')
35− | for "ifdef " = (masked, InConditional)
36− | for "ifndef " = (masked, InConditional)
37− | for "if " = (masked, InConditional)
38− | for "else" = (masked, InConditional)
39− | for "elif" = (masked, InConditional)
40− | for "endif" = (masked, state')
41− | otherwise =
42− case state of
43− Outside -> (line, Outside)
44− InConditional -> (masked, InConditional)
45− InContinuation -> (masked, state')
46− where
47− for directive = isJust $ do
48− s <- dropWhile isSpace <$> L.stripPrefix "#" line
49− void (L.stripPrefix directive s)
50− masked = maskLine line
51− state' =
52− if "\\" `L.isSuffixOf` line
53− then InContinuation
54− else Outside
55−
56−-- | Mask the given line.
57−maskLine :: String -> String
58−maskLine x = maskPrefix ++ x
59−
60−-- | If the given line is masked, unmask it. Otherwise return the line
61−-- unchanged.
62−unmaskLine :: Text -> Text
63−unmaskLine x =
64− case T.stripPrefix maskPrefix (T.stripStart x) of
65− Nothing -> x
66− Just x' -> x'
67−
68−-- | Mask prefix for CPP.
69−maskPrefix :: IsString s => s
70−maskPrefix = "-- ORMOLU_CPP_MASK"
src/Ormolu/Processing/Postprocess.hs+3−18
@@ -1,6 +1,3 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE ViewPatterns #-}
3−
4-- | Postprocessing for the results of printing.
1-- | Postprocessing for the results of printing.
5module Ormolu.Processing.Postprocess
2module Ormolu.Processing.Postprocess
6 ( postprocess,
3 ( postprocess,
@@ -10,22 +7,10 @@ where
10import Data.Text (Text)
7import Data.Text (Text)
11import qualified Data.Text as T
8import qualified Data.Text as T
12import Ormolu.Processing.Common
9import Ormolu.Processing.Common
13−import qualified Ormolu.Processing.Cpp as Cpp
14
10
15-- | Postprocess output of the formatter.
11-- | Postprocess output of the formatter.
16−postprocess ::
12+postprocess :: Text -> Text
17− -- | Desired indentation level
18− Int ->
19− -- | Input to process
20− Text ->
21− Text
22−postprocess indent =
23− T.unlines
24− . fmap indentLine
25− . fmap Cpp.unmaskLine
26− . filter (not . magicComment)
13+postprocess = T.unlines . filter (not . magicComment) . T.lines
27− . T.lines
28 where
14 where
29− magicComment (T.stripStart -> x) =
15+ magicComment x =
30 x == startDisabling || x == endDisabling
16 x == startDisabling || x == endDisabling
31− indentLine x = T.replicate indent " " <> x
src/Ormolu/Processing/Preprocess.hs+20−41
@@ -1,6 +1,5 @@
1{-# LANGUAGE BangPatterns #-}
1{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE LambdaCase #-}
3−{-# LANGUAGE RecordWildCards #-}
4
3
5-- | Preprocessing for input source code.
4-- | Preprocessing for input source code.
6module Ormolu.Processing.Preprocess
5module Ormolu.Processing.Preprocess
@@ -11,50 +10,38 @@ where
11import Control.Monad
10import Control.Monad
12import Data.Char (isSpace)
11import Data.Char (isSpace)
13import qualified Data.List as L
12import qualified Data.List as L
14−import Data.Maybe (isJust, maybeToList)
13+import Data.Maybe (isJust)
14+import Data.Maybe (maybeToList)
15import FastString
15import FastString
16−import Ormolu.Config (RegionDeltas (..))
17import Ormolu.Parser.Shebang (isShebang)
16import Ormolu.Parser.Shebang (isShebang)
18import Ormolu.Processing.Common
17import Ormolu.Processing.Common
19−import qualified Ormolu.Processing.Cpp as Cpp
20import SrcLoc
18import SrcLoc
21
19
22-- | Transform given input possibly returning comments extracted from it.
20-- | Transform given input possibly returning comments extracted from it.
23−-- This handles LINE pragmas, CPP, shebangs, and the magic comments for
21+-- This handles LINE pragmas, shebangs, and the magic comments for
24-- enabling\/disabling of Ormolu.
22-- enabling\/disabling of Ormolu.
25preprocess ::
23preprocess ::
26 -- | File name, just to use in the spans
24 -- | File name, just to use in the spans
27 FilePath ->
25 FilePath ->
28 -- | Input to process
26 -- | Input to process
29 String ->
27 String ->
30− -- | Region deltas
28+ -- | Adjusted input with comments extracted from it
31− RegionDeltas ->
32− -- | Literal prefix, pre-processed input, literal suffix, extra comments
33− (String, String, String, [Located String])
29+ (String, [Located String])
34−preprocess path input RegionDeltas {..} =
30+preprocess path input = go 1 OrmoluEnabled id id (lines input)
35− go 1 OrmoluEnabled Cpp.Outside id id regionLines
36 where
31 where
37− (prefixLines, otherLines) = splitAt regionPrefixLength (lines input)
38− (regionLines, suffixLines) =
39− let regionLength = length otherLines - regionSuffixLength
40− in splitAt regionLength otherLines
41− go !n ormoluState cppState inputSoFar csSoFar = \case
32+ go !n ormoluState inputSoFar csSoFar = \case
42 [] ->
33 [] ->
43 let input' = unlines (inputSoFar [])
34 let input' = unlines (inputSoFar [])
44− in ( unlines prefixLines,
45− case ormoluState of
35+ in ( case ormoluState of
46 OrmoluEnabled -> input'
36 OrmoluEnabled -> input'
47 OrmoluDisabled -> input' ++ endDisabling,
37 OrmoluDisabled -> input' ++ endDisabling,
48− unlines suffixLines,
49 csSoFar []
38 csSoFar []
50 )
39 )
51 (x : xs) ->
40 (x : xs) ->
52− let (x', ormoluState', cppState', cs) =
53− processLine path n ormoluState cppState x
41+ let (x', ormoluState', cs) = processLine path n ormoluState x
54 in go
42 in go
55 (n + 1)
43 (n + 1)
56 ormoluState'
44 ormoluState'
57− cppState'
58 (inputSoFar . (x' :))
45 (inputSoFar . (x' :))
59 (csSoFar . (maybeToList cs ++))
46 (csSoFar . (maybeToList cs ++))
60 xs
47 xs
@@ -67,41 +54,34 @@ processLine ::
67 Int ->
54 Int ->
68 -- | Whether Ormolu is currently enabled
55 -- | Whether Ormolu is currently enabled
69 OrmoluState ->
56 OrmoluState ->
70− -- | CPP state
71− Cpp.State ->
72 -- | The actual line
57 -- | The actual line
73 String ->
58 String ->
74 -- | Adjusted line and possibly a comment extracted from it
59 -- | Adjusted line and possibly a comment extracted from it
75− (String, OrmoluState, Cpp.State, Maybe (Located String))
60+ (String, OrmoluState, Maybe (Located String))
76−processLine path n ormoluState Cpp.Outside line
61+processLine path n ormoluState line
77 | "{-# LINE" `L.isPrefixOf` line =
62 | "{-# LINE" `L.isPrefixOf` line =
78 let (pragma, res) = getPragma line
63 let (pragma, res) = getPragma line
79 size = length pragma
64 size = length pragma
80 ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (size + 1))
65 ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (size + 1))
81− in (res, ormoluState, Cpp.Outside, Just (L ss pragma))
66+ in (res, ormoluState, Just (L ss pragma))
82 | isOrmoluEnable line =
67 | isOrmoluEnable line =
83 case ormoluState of
68 case ormoluState of
84 OrmoluEnabled ->
69 OrmoluEnabled ->
85− (enableMarker, OrmoluEnabled, Cpp.Outside, Nothing)
70+ (enableMarker, OrmoluEnabled, Nothing)
86 OrmoluDisabled ->
71 OrmoluDisabled ->
87− (endDisabling ++ enableMarker, OrmoluEnabled, Cpp.Outside, Nothing)
72+ (endDisabling ++ enableMarker, OrmoluEnabled, Nothing)
88 | isOrmoluDisable line =
73 | isOrmoluDisable line =
89 case ormoluState of
74 case ormoluState of
90 OrmoluEnabled ->
75 OrmoluEnabled ->
91− (disableMarker ++ startDisabling, OrmoluDisabled, Cpp.Outside, Nothing)
76+ (disableMarker ++ startDisabling, OrmoluDisabled, Nothing)
92 OrmoluDisabled ->
77 OrmoluDisabled ->
93− (disableMarker, OrmoluDisabled, Cpp.Outside, Nothing)
78+ (disableMarker, OrmoluDisabled, Nothing)
94 | isShebang line =
79 | isShebang line =
95 let ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (length line))
80 let ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (length line))
96− in ("", ormoluState, Cpp.Outside, Just (L ss line))
81+ in ("", ormoluState, Just (L ss line))
97− | otherwise =
98− let (line', cppState') = Cpp.processLine line Cpp.Outside
99− in (line', ormoluState, cppState', Nothing)
82+ | otherwise = (line, ormoluState, Nothing)
100 where
83 where
101 mkSrcLoc' = mkSrcLoc (mkFastString path) n
84 mkSrcLoc' = mkSrcLoc (mkFastString path) n
102−processLine _ _ ormoluState cppState line =
103− let (line', cppState') = Cpp.processLine line cppState
104− in (line', ormoluState, cppState', Nothing)
105
85
106-- | Take a line pragma and output its replacement (where line pragma is
86-- | Take a line pragma and output its replacement (where line pragma is
107-- replaced with spaces) and the contents of the pragma itself.
87-- replaced with spaces) and the contents of the pragma itself.
@@ -142,8 +122,7 @@ magicComment ::
142 -- | Whether or not the two strings watch
122 -- | Whether or not the two strings watch
143 Bool
123 Bool
144magicComment expected s0 = isJust $ do
124magicComment expected s0 = isJust $ do
145− let trim = dropWhile isSpace
125+ s1 <- dropWhile isSpace <$> L.stripPrefix "{-" s0
146− s1 <- trim <$> L.stripPrefix "{-" (trim s0)
147− s2 <- trim <$> L.stripPrefix expected s1
126+ s2 <- dropWhile isSpace <$> L.stripPrefix expected s1
148 s3 <- L.stripPrefix "-}" s2
127 s3 <- L.stripPrefix "-}" s2
149 guard (all isSpace s3)
128 guard (all isSpace s3)
src/Ormolu/Utils.hs+10−63
@@ -1,29 +1,24 @@
1{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE ViewPatterns #-}
4
3
5-- | Random utilities used by the code.
4-- | Random utilities used by the code.
6module Ormolu.Utils
5module Ormolu.Utils
7− ( RelativePos (..),
8− attachRelativePos,
9− combineSrcSpans',
6+ ( combineSrcSpans',
7+ isModule,
10 notImplemented,
8 notImplemented,
11 showOutputable,
9 showOutputable,
12 splitDocString,
10 splitDocString,
13 typeArgToType,
11 typeArgToType,
14 unSrcSpan,
12 unSrcSpan,
15− incSpanLine,
16 separatedByBlank,
13 separatedByBlank,
17 separatedByBlankNE,
14 separatedByBlankNE,
18− onTheSameLine,
19− removeIndentation,
20 )
15 )
21where
16where
22
17
23−import Data.Char (isSpace)
18+import Data.Data (Data, showConstr, toConstr)
24import Data.List (dropWhileEnd)
19import Data.List (dropWhileEnd)
25−import Data.List.NonEmpty (NonEmpty (..))
26import qualified Data.List.NonEmpty as NE
20import qualified Data.List.NonEmpty as NE
21+import Data.List.NonEmpty (NonEmpty (..))
27import Data.Maybe (fromMaybe)
22import Data.Maybe (fromMaybe)
28import Data.Text (Text)
23import Data.Text (Text)
29import qualified Data.Text as T
24import qualified Data.Text as T
@@ -31,29 +26,14 @@ import GHC
31import GHC.DynFlags (baseDynFlags)
26import GHC.DynFlags (baseDynFlags)
32import qualified Outputable as GHC
27import qualified Outputable as GHC
33
28
34−-- | Relative positions in a list.
35−data RelativePos
36− = SinglePos
37− | FirstPos
38− | MiddlePos
39− | LastPos
40− deriving (Eq, Show)
41−
42−-- | Attach 'RelativePos'es to elements of a given list.
43−attachRelativePos :: [a] -> [(RelativePos, a)]
44−attachRelativePos = \case
45− [] -> []
46− [x] -> [(SinglePos, x)]
47− (x : xs) -> (FirstPos, x) : markLast xs
48− where
49− markLast [] = []
50− markLast [x] = [(LastPos, x)]
51− markLast (x : xs) = (MiddlePos, x) : markLast xs
52−
53-- | Combine all source spans from the given list.
29-- | Combine all source spans from the given list.
54combineSrcSpans' :: NonEmpty SrcSpan -> SrcSpan
30combineSrcSpans' :: NonEmpty SrcSpan -> SrcSpan
55combineSrcSpans' (x :| xs) = foldr combineSrcSpans x xs
31combineSrcSpans' (x :| xs) = foldr combineSrcSpans x xs
56
32
33+-- | Return 'True' if given element of AST is module.
34+isModule :: Data a => a -> Bool
35+isModule x = showConstr (toConstr x) == "HsModule"
36+
57-- | Placeholder for things that are not yet implemented.
37-- | Placeholder for things that are not yet implemented.
58notImplemented :: String -> a
38notImplemented :: String -> a
59notImplemented msg = error $ "not implemented yet: " ++ msg
39notImplemented msg = error $ "not implemented yet: " ++ msg
@@ -99,32 +79,15 @@ splitDocString docStr =
99 then dropSpace <$> xs
79 then dropSpace <$> xs
100 else xs
80 else xs
101
81
102−-- | Get 'LHsType' out of 'LHsTypeArg'.
103typeArgToType :: LHsTypeArg p -> LHsType p
82typeArgToType :: LHsTypeArg p -> LHsType p
104typeArgToType = \case
83typeArgToType = \case
105 HsValArg tm -> tm
84 HsValArg tm -> tm
106 HsTypeArg _ ty -> ty
85 HsTypeArg _ ty -> ty
107 HsArgPar _ -> notImplemented "HsArgPar"
86 HsArgPar _ -> notImplemented "HsArgPar"
108
87
109−-- | Get 'RealSrcSpan' out of 'SrcSpan' if the span is “helpful”.
110unSrcSpan :: SrcSpan -> Maybe RealSrcSpan
88unSrcSpan :: SrcSpan -> Maybe RealSrcSpan
111−unSrcSpan = \case
112− RealSrcSpan r -> Just r
89+unSrcSpan (RealSrcSpan r) = Just r
113− UnhelpfulSpan _ -> Nothing
90+unSrcSpan (UnhelpfulSpan _) = Nothing
114−
115−-- | Increment line number in a 'SrcSpan'.
116−incSpanLine :: Int -> SrcSpan -> SrcSpan
117−incSpanLine i = \case
118− RealSrcSpan s ->
119− let start = realSrcSpanStart s
120− end = realSrcSpanEnd s
121− incLine x =
122− let file = srcLocFile x
123− line = srcLocLine x
124− col = srcLocCol x
125− in mkRealSrcLoc file (line + i) col
126− in RealSrcSpan (mkRealSrcSpan (incLine start) (incLine end))
127− UnhelpfulSpan x -> UnhelpfulSpan x
128
91
129-- | Do two declarations have a blank between them?
92-- | Do two declarations have a blank between them?
130separatedByBlank :: (a -> SrcSpan) -> a -> a -> Bool
93separatedByBlank :: (a -> SrcSpan) -> a -> a -> Bool
@@ -137,19 +100,3 @@ separatedByBlank loc a b =
137-- | Do two declaration groups have a blank between them?
100-- | Do two declaration groups have a blank between them?
138separatedByBlankNE :: (a -> SrcSpan) -> NonEmpty a -> NonEmpty a -> Bool
101separatedByBlankNE :: (a -> SrcSpan) -> NonEmpty a -> NonEmpty a -> Bool
139separatedByBlankNE loc a b = separatedByBlank loc (NE.last a) (NE.head b)
102separatedByBlankNE loc a b = separatedByBlank loc (NE.last a) (NE.head b)
140−
141−-- | Return 'True' if one span ends on the same line the second one starts.
142−onTheSameLine :: SrcSpan -> SrcSpan -> Bool
143−onTheSameLine a b =
144− isOneLineSpan (mkSrcSpan (srcSpanEnd a) (srcSpanStart b))
145−
146−-- | Remove indentation from a given 'String'. Return the input with
147−-- indentation removed and the detected indentation level.
148−removeIndentation :: String -> (String, Int)
149−removeIndentation (lines -> xs) = (unlines (drop n <$> xs), n)
150− where
151− n = minimum (getIndent <$> xs)
152− getIndent y =
153− if all isSpace y
154− then 0
155− else length (takeWhile isSpace y)
tests/Ormolu/PrinterSpec.hs+7−4
@@ -1,6 +1,9 @@
1{-# LANGUAGE TemplateHaskell #-}
1{-# LANGUAGE TemplateHaskell #-}
2
2
3−module Ormolu.PrinterSpec (spec) where
3+module Ormolu.PrinterSpec
4+ ( spec,
5+ )
6+where
4
7
5import Control.Exception
8import Control.Exception
6import Control.Monad
9import Control.Monad
@@ -62,7 +65,7 @@ deriveOutput path =
62-- | A version of 'shouldBe' that is specialized to comparing 'Text' values.
65-- | A version of 'shouldBe' that is specialized to comparing 'Text' values.
63-- It also prints multi-line snippets in a more readable form.
66-- It also prints multi-line snippets in a more readable form.
64shouldMatch :: Bool -> Text -> Text -> Expectation
67shouldMatch :: Bool -> Text -> Text -> Expectation
65−shouldMatch idempotenceTest actual expected =
68+shouldMatch idempotencyTest actual expected =
66 when (actual /= expected) . expectationFailure $
69 when (actual /= expected) . expectationFailure $
67 unlines
70 unlines
68 [ ">>>>>>>>>>>>>>>>>>>>>> expected (" ++ pass ++ "):",
71 [ ">>>>>>>>>>>>>>>>>>>>>> expected (" ++ pass ++ "):",
@@ -72,8 +75,8 @@ shouldMatch idempotenceTest actual expected =
72 ]
75 ]
73 where
76 where
74 pass =
77 pass =
75− if idempotenceTest
78+ if idempotencyTest
76− then "idempotence pass"
79+ then "idempotency pass"
77 else "first pass"
80 else "first pass"
78
81
79examplesDir :: Path Rel Dir
82examplesDir :: Path Rel Dir