on 3abadae help sign in
.buildkite/pipeline.ymldeleted−18
since splitsnapshots
unifiedsplit
@@ -1,18 +0,0 @@
1−steps:
2− - label: Build and test with GHC 8.6.5
3− command: |
4− nix-build --keep-going --no-out-link --argstr ormoluCompiler ghc865
5− timeout: 100
6− - label: Build and test with GHC 8.8.4
7− command: |
8− nix-build --keep-going --no-out-link --argstr ormoluCompiler ghc884
9− timeout: 100
10− - label: Build and test with GHC 8.10.1
11− command: |
12− nix-build --keep-going --no-out-link --argstr ormoluCompiler ghc8101
13− timeout: 100
14− - wait
15− - label: Check formatting
16− command: |
17− ./format.sh
18− git diff --exit-code --color=always
.circleci/config.ymlnew file+49
@@ -0,0 +1,49 @@
1+version: 2
2+
3+jobs:
4+ build:
5+ docker:
6+ - image: nixos/nix:2.1.3
7+ steps:
8+ - checkout
9+ - run:
10+ name: Add ca-certificates
11+ command: |
12+ apk --no-progress update
13+ apk --no-progress add ca-certificates
14+ - run:
15+ name: Setup Cachix
16+ command: |
17+ nix-env -iA cachix -f https://cachix.org/api/v1/install
18+ USER=dummy cachix use tweag
19+ - run:
20+ name: Build environment
21+ command: |
22+ nix-shell --pure --run :
23+ - run:
24+ name: Push Cachix
25+ command: |
26+ if [ -n "$CACHIX_SIGNING_KEY" ];
27+ then nix-store -qR --include-outputs $(nix-instantiate default.nix) | cachix push tweag;
28+ fi
29+ - run:
30+ name: Build the package (includes running the tests)
31+ command: nix-build --keep-going
32+ - run:
33+ name: Check formatting
34+ command: |
35+ ./format.sh
36+ nix-shell -p "(import ./nix/nixpkgs/default.nix).git" --command "git diff --exit-code --color=always"
37+ - run:
38+ name: Generate Haddocks
39+ command: nix-build --attr ormolu.doc
40+ - store_artifacts:
41+ path: result-doc/share/doc
42+ destination: haddock
43+
44+workflows:
45+ version: 2
46+ build:
47+ jobs:
48+ - build:
49+ context: org-global
.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
.gitignore−1
@@ -26,5 +26,4 @@ cabal.sandbox.config
26dist-*/
26dist-*/
27dist/
27dist/
28stack.yaml
28stack.yaml
29−stack.yaml.lock
30result*
29result*
CHANGELOG.md−231
@@ -1,234 +1,3 @@
1−## Unreleased
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
101− 74](https://github.com/tweag/ormolu/issues/74).
102−
103−* Grouping of TH splices is now preserved. [Issue
104− 507](https://github.com/tweag/ormolu/issues/507).
105−
106−* Comments on pragmas are now preserved. [Issue
107− 216](https://github.com/tweag/ormolu/issues/216).
108−
109−* Ormolu can now be enabled and disabled via special comments. [Issue
110− 435](https://github.com/tweag/ormolu/issues/435).
111−
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
123−
124−* When given several files to format, Ormolu does not stop on the first
125− failure, but tries to format all the files. [Issue
126− 502](https://github.com/tweag/ormolu/issues/502).
127−
128−* Made rendering of pattern matches involving operators consistent with
129− other cases of rendering of operators. [Issue
130− 500](https://github.com/tweag/ormolu/issues/500).
131−
132−* More compact rendering of type family injectivity constraints. [Issue
133− 482](https://github.com/tweag/ormolu/issues/482).
134−
135−* Improved rendering of the keyword `where` in class, data, and type family
136− declarations. When headers of these declarations are multi-line `where` is
137− now put on its own line. [Issue
138− 509](https://github.com/tweag/ormolu/issues/509).
139−
140−* Fixed the bug pertaining to rendering of arrow notation with multiline
141− expressions. [Issue 513](https://github.com/tweag/ormolu/issues/513).
142−
143−* Made rendering of data type definitions, value-level applications, and
144− application of types use the same style. Moreover, existential now doesn't
145− cause the data constructor be unconditionally rendered in multiline
146− layout. [Issue 427](https://github.com/tweag/ormolu/issues/427).
147−
148−* Records with a single data constructor are now formatted more compactly.
149− [Issue 425](https://github.com/tweag/ormolu/issues/425).
150−
151−* Switched to `ghc-lib-parser-8.10.1`.
152−
153−* Implemented support for the new language extensions `ImportQualifiedPost`
154− and `StandaloneKindSignatures`.
155−
156−## Ormolu 0.0.3.1
157−
158−* Fixed rendering of record updates with the record dot preprocessor syntax
159− [Issue 498](https://github.com/tweag/ormolu/issues/498).
160−
161−## Ormolu 0.0.3.0
162−
163−* Fixed an issue related to unnecessary use of curly braces. [Issue
164− 473](https://github.com/tweag/ormolu/issues/473).
165−
166−* Fixed the issue with formatting multi-way if when it happens to be a
167− function applied to arguments [Issue
168− 488](https://github.com/tweag/ormolu/issues/488). This changed the way
169− multi-line if is formatted in general.
170−
171−* Added support for record dot pre-processor when used via the plugin.
172− [Issue 486](https://github.com/tweag/ormolu/issues/486).
173−
174−* Stopped hanging record constructors and improved placing
175− potentially-hanging consturctions in the presence of comments. [Issue
176− 447](https://github.com/tweag/ormolu/issues/447).
177−
178−* Fixed indentation in presence of type applications. [Issue
179− 493](https://github.com/tweag/ormolu/issues/493).
180−
181−* Class and instance declarations now do not have a blank line after
182− `where`. Grouping of methods from the original input is also preserved
183− with some normalizations. [Issue
184− 431](https://github.com/tweag/ormolu/issues/431).
185−
186−## Ormolu 0.0.2.0
187−
188−* Switched to `ghc-lib-parser` instead of depending on the `ghc` package
189− directly. This should allow us to use newest features of GHC while not
190− necessarily depending on the newest version of the compiler. In addition
191− to that Ormolu is now GHCJS-compatible.
192−
193−* Now unrecognized GHC options passed with `--ghc-opt` cause Ormolu to fail
194− (exit code 7).
195−
196−* Fixed formatting of result type in closed type families. See [issue
197− 420](https://github.com/tweag/ormolu/issues/420).
198−
199−* Fixed a minor inconsistency between formatting of normal and foreign type
200− signatures. See [issue 408](https://github.com/tweag/ormolu/issues/408).
201−
202−* Fixed a bug when comment before module header with Haddock was moved
203− inside the export list. See [issue
204− 430](https://github.com/tweag/ormolu/issues/430).
205−
206−* Empty `forall`s are now correctly preserved. See [issue
207− 429](https://github.com/tweag/ormolu/issues/429).
208−
209−* Fixed [issue 446](https://github.com/tweag/ormolu/issues/446), which
210− involved braces and operators.
211−
212−* When there are comments between preceding Haddock (pipe-style) and its
213− corresponding declaration they are preserved like this in the output
214− instead of being shifted. To be clear, this is not a very good idea to
215− have comments in that position because the Haddock will end up not being
216− associated with the declarations. Issues
217− [440](https://github.com/tweag/ormolu/issues/440) and
218− [448](https://github.com/tweag/ormolu/issues/448).
219−
220−* Implemented correct handling of shebangs. [Issue
221− 377](https://github.com/tweag/ormolu/issues/377).
222−
223−* Implemented correct handling of stack headers. [Issue
224− 393](https://github.com/tweag/ormolu/issues/393).
225−
226−* Sorting language pragmas cannot not change meaning of the input program
227− anymore. [Issue 404](https://github.com/tweag/ormolu/issues/404).
228−
229−* Fixed formatting of applications where function is a complex expression.
230− [Issue 444](https://github.com/tweag/ormolu/issues/444).
231−
232## Ormolu 0.0.1.0
1## Ormolu 0.0.1.0
233
2
234* Initial release.
3* Initial release.
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+14−62
@@ -4,7 +4,7 @@
4[![Hackage](https://img.shields.io/hackage/v/ormolu.svg?style=flat)](https://hackage.haskell.org/package/ormolu)
4[![Hackage](https://img.shields.io/hackage/v/ormolu.svg?style=flat)](https://hackage.haskell.org/package/ormolu)
5[![Stackage Nightly](http://stackage.org/package/ormolu/badge/nightly)](http://stackage.org/nightly/package/ormolu)
5[![Stackage Nightly](http://stackage.org/package/ormolu/badge/nightly)](http://stackage.org/nightly/package/ormolu)
6[![Stackage LTS](http://stackage.org/package/ormolu/badge/lts)](http://stackage.org/lts/package/ormolu)
6[![Stackage LTS](http://stackage.org/package/ormolu/badge/lts)](http://stackage.org/lts/package/ormolu)
7−[![Build status](https://badge.buildkite.com/8e3b0951f3652b77e1c422b361904136a539b0522029156354.svg?branch=master)](https://buildkite.com/tweag-1/ormolu)
7+[![CircleCI](https://circleci.com/gh/tweag/ormolu/tree/master.svg?style=svg&circle-token=cfd37a39265561eb44e608f97cf953cb2a394c03)](https://circleci.com/gh/tweag/ormolu/tree/master)
8
8
9Ormolu is a formatter for Haskell source code. The project was created with
9Ormolu is a formatter for Haskell source code. The project was created with
10the following goals in mind:
10the following goals in mind:
@@ -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,44 +91,19 @@ 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
102−
103−Ormolu understands two magic comments:
104−
105−```haskell
106−{- ORMOLU_DISABLE -}
107−```
108−
109−and
110−
111−```haskell
112−{- ORMOLU_ENABLE -}
113−```
114−
115−This allows us to disable formatting selectively for code between these
116−markers or disable it for the entire file. To achieve the latter, just put
117−`{- ORMOLU_DISABLE -}` at the very top. Note that the source code should
118−still be parseable even without the “excluded” part. Because of that the
119−magic comments cannot be placed arbitrary, but should rather enclose
120−independent top-level definitions.
121−
122## Current limitations
94## Current limitations
123
95
124−* CPP support is experimental. CPP is virtually impossible to handle
96+* 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
97* Input modules should be parsable by Haddock, which is a bit stricter
130 criterion than just being valid Haskell modules.
98 criterion than just being valid Haskell modules.
131* Various minor idempotence issues, most of them are related to comments.
99* Various minor idempotence issues, most of them are related to comments.
132
100
101+## Editor integration
102+
103+We know of the following editor integrations:
104+
105+* [For Emacs][emacs-package]
106+
133## Running on Hackage
107## Running on Hackage
134
108
135It's possible to try Ormolu on arbitrary packages from Hackage. For that
109It's possible to try Ormolu on arbitrary packages from Hackage. For that
@@ -144,38 +118,16 @@ also contain formatted `.hs` files for inspection and original inputs with
144`.hs-original` extension (those are with CPP dropped, exactly what is fed
118`.hs-original` extension (those are with CPP dropped, exactly what is fed
145into Ormolu).
119into Ormolu).
146
120
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
121## Contributing
164
122
165−See [CONTRIBUTING.md][contributing].
123+See [CONTRIBUTING.md](./CONTRIBUTING.md).
166
124
167## License
125## License
168
126
169−See [LICENSE.md][license].
127+See [LICENSE.md](./LICENSE.md).
170
128
171Copyright © 2018–present Tweag I/O
129Copyright © 2018–present Tweag I/O
172
130
173−[design-cpp]: https://github.com/tweag/ormolu/blob/master/DESIGN.md#cpp
131+[design]: ./DESIGN.md#cpp
174−[contributing]: https://github.com/tweag/ormolu/blob/master/CONTRIBUTING.md
175−[license]: https://github.com/tweag/ormolu/blob/master/LICENSE.md
176[haskell-src-exts]: https://hackage.haskell.org/package/haskell-src-exts
132[haskell-src-exts]: https://hackage.haskell.org/package/haskell-src-exts
177[emacs-package]: https://github.com/vyorkin/ormolu.el
133[emacs-package]: https://github.com/vyorkin/ormolu.el
178−[vs-code-plugin]: https://marketplace.visualstudio.com/items?itemName=sjurmillidahl.ormolu-vscode
179−[vim-ormolu]: https://github.com/sdiehl/vim-ormolu
180−[neoformat]: https://github.com/sbdchd/neoformat
181−[aur]: https://aur.archlinux.org/packages/ormolu
app/Main.hs+95−133
@@ -1,17 +1,12 @@
1−{-# LANGUAGE CPP #-}
1+{-# LANGUAGE CPP #-}
2−{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE LambdaCase #-}
3{-# LANGUAGE RecordWildCards #-}
3{-# LANGUAGE RecordWildCards #-}
4{-# LANGUAGE TemplateHaskell #-}
4{-# LANGUAGE TemplateHaskell #-}
5−{-# LANGUAGE TypeApplications #-}
6
5
7module Main (main) where
6module Main (main) where
8
7
9−import Control.Exception (SomeException, displayException, try)
10import Control.Monad
8import Control.Monad
11−import Data.Bool (bool)
12−import Data.Either (lefts)
13import Data.List (intercalate, sort)
9import Data.List (intercalate, sort)
14−import qualified Data.Text.IO as TIO
15import Data.Version (showVersion)
10import Data.Version (showVersion)
16import Development.GitRev
11import Development.GitRev
17import Options.Applicative
12import Options.Applicative
@@ -21,8 +16,10 @@ import Ormolu.Utils (showOutputable)
21import Paths_ormolu (version)
16import Paths_ormolu (version)
22import System.Exit (ExitCode (..), exitWith)
17import System.Exit (ExitCode (..), exitWith)
23import System.IO (hPutStrLn, stderr)
18import System.IO (hPutStrLn, stderr)
19+import qualified Data.Text.IO as TIO
24
20
25-- | Entry point of the program.
21-- | Entry point of the program.
22+
26main :: IO ()
23main :: IO ()
27main = withPrettyOrmoluExceptions $ do
24main = withPrettyOrmoluExceptions $ do
28 Opts {..} <- execParser optsParserInfo
25 Opts {..} <- execParser optsParserInfo
@@ -30,50 +27,35 @@ main = withPrettyOrmoluExceptions $ do
30 case optInputFiles of
27 case optInputFiles of
31 [] -> formatOne' Nothing
28 [] -> formatOne' Nothing
32 ["-"] -> formatOne' Nothing
29 ["-"] -> formatOne' Nothing
33− [x] -> formatOne' (Just x)
30+ xs -> mapM_ (formatOne' . Just) xs
34− xs -> do
35− -- It is possible to get IOException, error's and 'OrmoluException's
36− -- from 'formatOne', so we just catch everything.
37− errs <-
38− lefts <$> mapM (try @SomeException . formatOne' . Just) (sort xs)
39− unless (null errs) $ do
40− mapM_ (hPutStrLn stderr . displayException) errs
41− exitWith (ExitFailure 102)
42
31
43-- | Format a single input.
32-- | Format a single input.
33+
44−formatOne ::
34+formatOne
45− -- | Mode of operation
35+ :: Mode -- ^ Mode of operation
46− Mode ->
47− -- | Configuration
36+ -> Config -- ^ Configuration
48− Config RegionIndices ->
49− -- | File to format or stdin as 'Nothing'
37+ -> Maybe FilePath -- ^ File to format or stdin as 'Nothing'
50− Maybe FilePath ->
51− IO ()
38+ -> IO ()
52formatOne mode config = \case
39formatOne mode config = \case
53 Nothing -> do
40 Nothing -> do
54 r <- ormoluStdin config
41 r <- ormoluStdin config
55 case mode of
42 case mode of
56 Stdout -> TIO.putStr r
43 Stdout -> TIO.putStr r
57− _ -> do
44+ _ -> do
58− hPutStrLn
45+ hPutStrLn stderr
59− stderr
60 "This feature is not supported when input comes from stdin."
46 "This feature is not supported when input comes from stdin."
61− -- 101 is different from all the other exit codes we already use.
47+ -- 101 is different from all the other exit codes we already use.
62 exitWith (ExitFailure 101)
48 exitWith (ExitFailure 101)
63 Just inputFile -> do
49 Just inputFile -> do
64− originalInput <- TIO.readFile inputFile
65− formattedInput <- ormoluFile config inputFile
50+ r <- ormoluFile config inputFile
66 case mode of
51 case mode of
67 Stdout ->
52 Stdout ->
68− TIO.putStr formattedInput
53+ TIO.putStr r
69− InPlace -> do
54+ 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
55+ TIO.writeFile inputFile r
75 Check -> do
56 Check -> do
76− when (formattedInput /= originalInput) $
57+ r' <- TIO.readFile inputFile
58+ when (r /= r') $
77 -- 100 is different to all the other exit code that are emitted
59 -- 100 is different to all the other exit code that are emitted
78 -- either from an 'OrmoluException' or from 'error' and
60 -- either from an 'OrmoluException' or from 'error' and
79 -- 'notImplemented'.
61 -- 'notImplemented'.
@@ -83,121 +65,101 @@ formatOne mode config = \case
83-- Command line options parsing.
65-- Command line options parsing.
84
66
85data Opts = Opts
67data Opts = Opts
68+ { optMode :: !Mode
86− { -- | Mode of operation
69+ -- ^ Mode of operation
87− optMode :: !Mode,
70+ , optConfig :: !Config
88− -- | Ormolu 'Config'
71+ -- ^ Ormolu 'Config'
89− optConfig :: !(Config RegionIndices),
72+ , optInputFiles :: ![FilePath]
90− -- | Haskell source files to format or stdin (when the list is empty)
73+ -- ^ Haskell source files to format or stdin (when the list is empty)
91− optInputFiles :: ![FilePath]
92 }
74 }
93
75
94-- | Mode of operation.
76-- | Mode of operation.
77+
95data Mode
78data Mode
96− = -- | Output formatted source code to stdout
79+ = Stdout -- ^ Output formatted source code to stdout
97− Stdout
98− | -- | Overwrite original file
80+ | InPlace -- ^ Overwrite original file
99− InPlace
100− | -- | Exit with non-zero status code if
81+ | Check -- ^ Exit with non-zero status code if
101− -- source is not already formatted
82+ -- source is not already formatted
102− Check
103 deriving (Eq, Show)
83 deriving (Eq, Show)
104
84
105optsParserInfo :: ParserInfo Opts
85optsParserInfo :: ParserInfo Opts
106−optsParserInfo =
107− info (helper <*> ver <*> exts <*> optsParser) . mconcat $
86+optsParserInfo = info (helper <*> ver <*> exts <*> optsParser) . mconcat $
108− [ fullDesc,
87+ [ fullDesc
109− progDesc "",
88+ , progDesc ""
110− header ""
89+ , header ""
111− ]
90+ ]
112 where
91 where
113 ver :: Parser (a -> a)
92 ver :: Parser (a -> a)
114− ver =
115− infoOption verStr . mconcat $
93+ ver = infoOption verStr . mconcat $
116− [ long "version",
94+ [ long "version"
117− short 'v',
95+ , short 'v'
118− help "Print version of the program"
96+ , help "Print version of the program"
119− ]
97+ ]
120− verStr =
121− intercalate
98+ verStr = intercalate "\n"
122− "\n"
123− [ unwords
99+ [ unwords
124− [ "ormolu",
100+ [ "ormolu"
125− showVersion version,
101+ , showVersion version
126− $gitBranch,
102+ , $gitBranch
127− $gitHash
103+ , $gitHash
128− ],
129− "using ghc-lib-parser " ++ VERSION_ghc_lib_parser
130 ]
104 ]
105+ , "using ghc " ++ VERSION_ghc
106+ ]
131 exts :: Parser (a -> a)
107 exts :: Parser (a -> a)
132− exts =
133− infoOption displayExts . mconcat $
108+ exts = infoOption displayExts . mconcat $
134− [ long "manual-exts",
109+ [ long "manual-exts"
135− help "Display extensions that need to be enabled manually"
110+ , help "Display extensions that need to be enabled manually"
136− ]
111+ ]
137 displayExts = unlines $ sort (showOutputable <$> manualExts)
112 displayExts = unlines $ sort (showOutputable <$> manualExts)
138
113
139optsParser :: Parser Opts
114optsParser :: Parser Opts
140−optsParser =
115+optsParser = Opts
141− Opts
142− <$> ( (fmap (bool Stdout InPlace) . switch . mconcat)
143− [ short 'i',
144− help "A shortcut for --mode inplace"
145− ]
146− <|> (option parseMode . mconcat)
116+ <$> (option parseMode . mconcat)
147− [ long "mode",
117+ [ long "mode"
148− short 'm',
118+ , short 'm'
149− metavar "MODE",
119+ , metavar "MODE"
150− value Stdout,
120+ , value Stdout
151− help "Mode of operation: 'stdout' (default), 'inplace', or 'check'"
121+ , help "Mode of operation: 'stdout' (default), 'inplace', or 'check'"
152− ]
122+ ]
153− )
154− <*> configParser
123+ <*> configParser
155− <*> (many . strArgument . mconcat)
124+ <*> (many . strArgument . mconcat)
156− [ metavar "FILE",
125+ [ metavar "FILE"
157− help "Haskell source files to format or stdin (default)"
126+ , help "Haskell source files to format or stdin (default)"
158− ]
127+ ]
159
128
160−configParser :: Parser (Config RegionIndices)
129+configParser :: Parser Config
161−configParser =
130+configParser = Config
162− Config
163− <$> (fmap (fmap DynOption) . many . strOption . mconcat)
131+ <$> (fmap (fmap DynOption) . many . strOption . mconcat)
164− [ long "ghc-opt",
132+ [ long "ghc-opt"
165− short 'o',
133+ , short 'o'
166− metavar "OPT",
134+ , metavar "OPT"
167− help "GHC options to enable (e.g. language extensions)"
135+ , help "GHC options to enable (e.g. language extensions)"
168− ]
136+ ]
169− <*> (switch . mconcat)
137+ <*> (switch . mconcat)
170− [ long "unsafe",
138+ [ long "unsafe"
171− short 'u',
139+ , short 'u'
172− help "Do formatting faster but without automatic detection of defects"
140+ , help "Do formatting faster but without automatic detection of defects"
173− ]
141+ ]
174− <*> (switch . mconcat)
142+ <*> (switch . mconcat)
175− [ long "debug",
143+ [ long "debug"
176− short 'd',
144+ , short 'd'
177− help "Output information useful for debugging"
145+ , help "Output information useful for debugging"
178− ]
146+ ]
147+ <*> (switch . mconcat)
148+ [ long "tolerate-cpp"
149+ , short 'p'
150+ , help "Do not fail if CPP pragma is present"
151+ ]
179− <*> (switch . mconcat)
152+ <*> (switch . mconcat)
180− [ long "check-idempotence",
153+ [ long "check-idempotency"
181− short 'c',
154+ , short 'c'
182− help "Fail if formatting is not idempotent"
155+ , help "Fail if formatting is not idempotent"
183− ]
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− ]
156+ ]
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
157
197----------------------------------------------------------------------------
158----------------------------------------------------------------------------
198-- Helpers
159-- Helpers
199
160
200-- | Parse 'Mode'.
161-- | Parse 'Mode'.
162+
201parseMode :: ReadM Mode
163parseMode :: ReadM Mode
202parseMode = eitherReader $ \case
164parseMode = eitherReader $ \case
203 "stdout" -> Right Stdout
165 "stdout" -> Right Stdout
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/class/associated-data1-out.hs+1
@@ -4,6 +4,7 @@ class Foo a where data FooBar a
4
4
5-- | Something.
5-- | Something.
6class Bar a where
6class Bar a where
7+
7 -- | Bar bar
8 -- | Bar bar
8 data BarBar a
9 data BarBar a
9
10
data/examples/declaration/class/associated-data2-out.hs+1
@@ -4,6 +4,7 @@ module Main where
4
4
5-- | Something more.
5-- | Something more.
6class Baz a where
6class Baz a where
7+
7 -- | Baz bar
8 -- | Baz bar
8 data
9 data
9 BazBar
10 BazBar
data/examples/declaration/class/associated-type-defaults-out.hs+2
@@ -4,6 +4,7 @@ class Foo a where type FooBar a = Int
4
4
5-- | Something.
5-- | Something.
6class Bar a where
6class Bar a where
7+
7 -- Define bar
8 -- Define bar
8 type
9 type
9 BarBar a =
10 BarBar a =
@@ -17,6 +18,7 @@ class Bar a where
17 a
18 a
18
19
19class Baz a where
20class Baz a where
21+
20 type
22 type
21 BazBar
23 BazBar
22 a
24 a
data/examples/declaration/class/associated-types1-out.hs+1
@@ -4,6 +4,7 @@ class Foo a where type FooBar a
4
4
5-- | Something.
5-- | Something.
6class Bar a where
6class Bar a where
7+
7 -- | Bar bar
8 -- | Bar bar
8 type BarBar a
9 type BarBar a
9
10
data/examples/declaration/class/associated-types2-out.hs+1
@@ -4,6 +4,7 @@ module Main where
4
4
5-- | Something more.
5-- | Something more.
6class Baz a where
6class Baz a where
7+
7 -- | Baz bar
8 -- | Baz bar
8 type
9 type
9 BazBar
10 BazBar
data/examples/declaration/class/default-implementations-comments-out.hs+1
@@ -2,6 +2,7 @@ module Main where
2
2
3-- | Baz
3-- | Baz
4class Baz a where
4class Baz a where
5+
5 foobar :: a -> a
6 foobar :: a -> a
6 foobar a =
7 foobar a =
7 barbaz (bazbar a)
8 barbaz (bazbar a)
data/examples/declaration/class/default-signatures-out.hs+2
@@ -4,11 +4,13 @@ module Main where
4
4
5-- | Something else.
5-- | Something else.
6class Bar a where
6class Bar a where
7+
7 -- | Bar
8 -- | Bar
8 bar ::
9 bar ::
9 String ->
10 String ->
10 String ->
11 String ->
11 a
12 a
13+
12 -- Pointless comment
14 -- Pointless comment
13 default bar ::
15 default bar ::
14 ( Read a,
16 ( Read a,
data/examples/declaration/class/default-signatures-simple-out.hs+2
@@ -2,7 +2,9 @@ module Main where
2
2
3-- | Something.
3-- | Something.
4class Foo a where
4class Foo a where
5+
5 -- | Foo
6 -- | Foo
6 foo :: a -> String
7 foo :: a -> String
8+
7 default foo :: Show a => a -> String
9 default foo :: Show a => a -> String
8 foo = show
10 foo = show
data/examples/declaration/class/dependency-super-classes-out.hs+4−2
@@ -4,7 +4,9 @@ module Main where
4
4
5-- | Something.
5-- | Something.
6class (MonadReader r s, MonadWriter w m) => MonadState s m | m -> s where
6class (MonadReader r s, MonadWriter w m) => MonadState s m | m -> s where
7+
7 get :: m s
8 get :: m s
9+
8 put :: s -> m ()
10 put :: s -> m ()
9
11
10-- | 'MonadParsec'
12-- | 'MonadParsec'
@@ -13,8 +15,8 @@ class
13 MonadPlus m -- Potential for failure
15 MonadPlus m -- Potential for failure
14 ) =>
16 ) =>
15 MonadParsec e s m
17 MonadParsec e s m
16− | m -> e s
17− where
18+ | m -> e s where
19+
18 -- | 'getState' returns state
20 -- | 'getState' returns state
19 getState ::
21 getState ::
20 m s
22 m s
data/examples/declaration/class/functional-dependencies-out.hs+1−2
@@ -14,6 +14,5 @@ class
14 b c -> a d, -- Bar
14 b c -> a d, -- Bar
15 a c -> b d, -- Baz
15 a c -> b d, -- Baz
16 a c d -> b,
16 a c d -> b,
17− a b d -> a b c d
17+ a b d -> a b c d where
18− where
19 baz :: a -> b
18 baz :: a -> b
data/examples/declaration/class/multi-parameters2-out.hs+3−2
@@ -10,10 +10,11 @@ class
10 c -- Baz bar
10 c -- Baz bar
11 d -- Baz baz
11 d -- Baz baz
12 e -- Rest
12 e -- Rest
13− f
13+ f where
14− where
14+
15 barbaz ::
15 barbaz ::
16 a -> f
16 a -> f
17+
17 bazbar ::
18 bazbar ::
18 e ->
19 e ->
19 f
20 f
data/examples/declaration/class/newlines-after-where-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−class Num a where
2− (+) :: a -> a -> a
3−
4−class Num a where
5− (+) :: a -> a -> a
data/examples/declaration/class/newlines-after-where.hsdeleted−7
@@ -1,7 +0,0 @@
1−class Num a where
2− (+) :: a -> a -> a
3−
4−class Num a where
5−
6−
7− (+) :: a -> a -> a
data/examples/declaration/class/newlines-and-default-decls-out.hsdeleted−11
@@ -1,11 +0,0 @@
1−class Foo a where
2− foo :: a
3− default foo :: ()
4− foo = ()
5− bar :: a
6− default bar :: ()
7− bar = ()
8−
9− qux :: a
10− default qux :: ()
11− qux = ()
data/examples/declaration/class/newlines-and-default-decls.hsdeleted−13
@@ -1,13 +0,0 @@
1−class Foo a where
2− foo :: a
3− default foo :: ()
4− foo = ()
5− bar :: a
6− default bar :: ()
7− bar = ()
8−
9− qux :: a
10−
11− default qux :: ()
12−
13− qux = ()
data/examples/declaration/class/newlines-and-haddocks-out.hsdeleted−23
@@ -1,23 +0,0 @@
1−class Foo a where
2− -- | Haddock
3− foo :: a
4−
5− -- | Another Haddock
6− bar :: a
7−
8− baz :: a
9− -- ^ Post-Haddock
10−
11− raz :: a
12− -- ^ Another Post-Haddock
13−
14− -- | One more Haddock
15− qux :: a
16−
17− -- Comment before a Haddock
18−
19− -- | And one more Haddock
20− xyz :: a
21−
22− -- | Haddock followed by a blank line
23− abc :: a
data/examples/declaration/class/newlines-and-haddocks.hsdeleted−19
@@ -1,19 +0,0 @@
1−class Foo a where
2− -- | Haddock
3− foo :: a
4− -- | Another Haddock
5− bar :: a
6− baz :: a
7− -- ^ Post-Haddock
8− raz :: a
9− -- ^ Another Post-Haddock
10−
11− -- | One more Haddock
12− qux :: a
13− -- Comment before a Haddock
14− -- | And one more Haddock
15− xyz :: a
16−
17− -- | Haddock followed by a blank line
18−
19− abc :: a
data/examples/declaration/class/newlines-between-methods-out.hsdeleted−17
@@ -1,17 +0,0 @@
1−class Num a where
2− (+) :: a -> a -> a
3− (-) :: a -> a -> a
4− (*) :: a -> a -> a
5−
6− -- Comment before definition
7− negate :: a -> a
8−
9− -- Comment after definition
10−
11− -- Separator
12−
13− abs :: a -> a
14− signum :: a -> a
15−
16− -- Comment between unrelated definitions
17− fromInteger :: Integer -> a
data/examples/declaration/class/newlines-between-methods.hsdeleted−15
@@ -1,15 +0,0 @@
1−class Num a where
2− (+) :: a -> a -> a
3− (-) :: a -> a -> a
4− (*) :: a -> a -> a
5−
6− -- Comment before definition
7− negate :: a -> a
8− -- Comment after definition
9−
10− -- Separator
11−
12− abs :: a -> a
13− signum :: a -> a
14− -- Comment between unrelated definitions
15− fromInteger :: Integer -> a
data/examples/declaration/class/single-parameters-out.hs+2
@@ -21,6 +21,8 @@ class Baz a where
21 a
21 a
22
22
23class BarBaz a where
23class BarBaz a where
24+
24 barbaz ::
25 barbaz ::
25 a -> b
26 a -> b
27+
26 bazbar :: b -> a
28 bazbar :: b -> a
data/examples/declaration/class/type-operators3-out.hsdeleted−10
@@ -1,10 +0,0 @@
1−{-# LANGUAGE PolyKinds #-}
2−{-# LANGUAGE TypeFamilies #-}
3−{-# LANGUAGE TypeOperators #-}
4−{-# LANGUAGE NoStarIsType #-}
5−
6−class PNum x where
7− type (a :: x) * (b :: x)
8−
9−instance PNum Nat where
10− type a * b = ()
data/examples/declaration/class/type-operators3.hsdeleted−7
@@ -1,7 +0,0 @@
1−{-# LANGUAGE TypeFamilies, TypeOperators, NoStarIsType, PolyKinds #-}
2−
3−class PNum x where
4− type (a :: x) * (b :: x)
5−
6−instance PNum Nat where
7− type a * b = ()
data/examples/declaration/data/existential-multiline-out.hs−12
@@ -3,15 +3,3 @@
3data Foo
3data Foo
4 = forall a. MkFoo a (a -> Bool)
4 = forall a. MkFoo a (a -> Bool)
5 | forall a. Eq a => MkBar a
5 | forall a. Eq a => MkBar a
6−
7−data Bar
8− = forall x y.
9− Bar x y x y
10−
11−data Baz
12− = forall x y.
13− Baz
14− x
15− y
16− x
17− y
data/examples/declaration/data/existential-multiline.hs−7
@@ -3,10 +3,3 @@
3data Foo
3data Foo
4 = forall a. MkFoo a (a -> Bool)
4 = forall a. MkFoo a (a -> Bool)
5 | forall a. Eq a => MkBar a
5 | forall a. Eq a => MkBar a
6−
7−data Bar = forall x y.
8− Bar x y x y
9−
10−data Baz = forall x y.
11− Baz x y x
12− y
data/examples/declaration/data/existential-out.hs−2
@@ -1,5 +1,3 @@
1{-# LANGUAGE ExistentialQuantification #-}
1{-# LANGUAGE ExistentialQuantification #-}
2
2
3data Foo = forall a. MkFoo a (a -> Bool)
3data Foo = forall a. MkFoo a (a -> Bool)
4−
5−data Bar = forall a b. a + b => Bar a b
data/examples/declaration/data/existential.hs−2
@@ -1,5 +1,3 @@
1{-# LANGUAGE ExistentialQuantification #-}
1{-# LANGUAGE ExistentialQuantification #-}
2
2
3data Foo = forall a. MkFoo a (a -> Bool)
3data Foo = forall a. MkFoo a (a -> Bool)
4−
5−data Bar = forall a b. a + b => Bar a b
data/examples/declaration/data/field-layout/gadt-out.hs+1−2
@@ -6,6 +6,5 @@ data Foo a b where
6 Foo :: Foo Int Int
6 Foo :: Foo Int Int
7 -- | Something else
7 -- | Something else
8 Bar ::
8 Bar ::
9− Foo
10− Char
9+ Foo Char
11 Char
10 Char
data/examples/declaration/data/field-layout/record-out.hs+9−9
@@ -1,12 +1,12 @@
1module Main where
1module Main where
2
2
3-- | Foo.
3-- | Foo.
4−data Foo = Foo
4+data Foo
5+ = Foo
5− { -- | Something
6+ { -- | Something
6− foo :: Foo Int Int,
7+ foo :: Foo Int Int,
7− -- | Something else
8+ -- | Something else
8− bar ::
9+ bar ::
9− Bar
10− Char
10+ Bar Char
11− Char
11+ Char
12− }
12+ }
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/gadt/multiline-where-out.hsdeleted−7
@@ -1,7 +0,0 @@
1−data
2− Foo
3− a
4− b
5− c
6− where
7− Foo :: a -> b -> c -> Foo a b c
data/examples/declaration/data/gadt/multiline-where.hsdeleted−6
@@ -1,6 +0,0 @@
1−data
2− Foo
3− a
4− b
5− c where
6− Foo :: a -> b -> c -> Foo a b c
data/examples/declaration/data/gadt/strictness-out.hs+1−2
@@ -1,3 +1,2 @@
1data Foo a where
1data Foo a where
2− Foo1 :: !Int -> {-# UNPACK #-} !Bool -> Foo Int
2+ Foo :: !Int -> {-# UNPACK #-} !Bool -> Foo Int
3− Foo2 :: {-# UNPACK #-} Maybe Int && Bool -> Foo Int
data/examples/declaration/data/gadt/strictness.hs+1−2
@@ -1,3 +1,2 @@
1data Foo a where
1data Foo a where
2− Foo1 :: !Int -> {-# UNPACK #-} !Bool -> Foo Int
2+ Foo :: !Int -> {-# UNPACK #-} !Bool -> Foo Int
3− Foo2 :: {-# UNPACK #-} Maybe Int && Bool -> Foo Int
data/examples/declaration/data/kind-annotations-out.hs−8
@@ -1,11 +1,3 @@
1data Something (n :: Nat) = Something
1data Something (n :: Nat) = Something
2
2
3data Format (k :: *) (k' :: *) (k'' :: *)
3data Format (k :: *) (k' :: *) (k'' :: *)
4−
5−type Parens1 = Proxy '(a :: A, b :: (B :: *))
6−
7−type Parens2 = Proxy '((a :: A), (b :: B))
8−
9−type family Foo a where
10− Foo '(a :: Int, b :: Bool) = Int
11− Foo '((a :: Int), (b :: Bool)) = Int
data/examples/declaration/data/kind-annotations.hs−7
@@ -1,10 +1,3 @@
1data Something (n :: Nat) = Something
1data Something (n :: Nat) = Something
2
2
3data Format (k :: *) (k' :: *) (k'' :: *)
3data Format (k :: *) (k' :: *) (k'' :: *)
4−
5−type Parens1 = Proxy '(a :: A, b :: (B :: *))
6−type Parens2 = Proxy '((a :: A), (b :: B))
7−
8−type family Foo a where
9− Foo '(a :: Int, b :: Bool) = Int
10− Foo '((a :: Int), (b :: Bool)) = 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/operators-out.hsdeleted−12
@@ -1,12 +0,0 @@
1−data ErrorMessage' s
2− = -- | Show the text as is.
3− Text s
4− | -- | Pretty print the type.
5− -- @ShowType :: k -> ErrorMessage@
6− forall t. ShowType t
7− | -- | Put two pieces of error message next
8− -- to each other.
9− ErrorMessage' s :<>: ErrorMessage' s
10− | -- | Stack two pieces of error message on top
11− -- of each other.
12− ErrorMessage' s :$$: ErrorMessage' s
data/examples/declaration/data/operators.hsdeleted−12
@@ -1,12 +0,0 @@
1−data ErrorMessage' s
2− = -- | Show the text as is.
3− Text s
4− | -- | Pretty print the type.
5− -- @ShowType :: k -> ErrorMessage@
6− forall t. ShowType t
7− | -- | Put two pieces of error message next
8− -- to each other.
9− ErrorMessage' s :<>: ErrorMessage' s
10− | -- | Stack two pieces of error message on top
11− -- of each other.
12− ErrorMessage' s :$$: ErrorMessage' s
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/record-multi-const-out.hsdeleted−17
@@ -1,17 +0,0 @@
1−module Main where
2−
3−-- | Something.
4−data Foo
5− = Foo
6− { -- | X
7− fooX :: Int,
8− -- | Y
9− fooY :: Int
10− }
11− | Bar
12− { -- | X
13− barX :: Int,
14− -- | Y
15− barY :: Int
16− }
17− deriving (Eq, Show)
data/examples/declaration/data/record-multi-const.hsdeleted−13
@@ -1,13 +0,0 @@
1−module Main where
2−
3−-- | Something.
4−
5−data Foo = Foo
6− { fooX :: Int -- ^ X
7− , fooY :: Int -- ^ Y
8− } |
9− Bar
10− { barX :: Int -- ^ X
11− , barY :: Int -- ^ Y
12− }
13− deriving (Eq, Show)
data/examples/declaration/data/record-out.hs+20−19
@@ -1,23 +1,24 @@
1module Main where
1module Main where
2
2
3-- | Something.
3-- | Something.
4−data Foo = Foo
4+data Foo
5+ = Foo
5− { -- | X
6+ { -- | X
6− fooX :: Int,
7+ fooX :: Int,
7− -- | Y
8+ -- | Y
8− fooY :: Int,
9+ fooY :: Int,
9− -- | BarBaz
10+ -- | BarBaz
10− fooBar, fooBaz :: NonEmpty (Identity Bool),
11+ fooBar, fooBaz :: NonEmpty (Identity Bool),
11− -- | GagGog
12+ -- | GagGog
12− fooGag,
13+ fooGag,
13− fooGog ::
14+ fooGog ::
14− NonEmpty
15+ NonEmpty
15− ( Indentity
16+ ( Indentity
16− Bool
17+ Bool
17− ),
18+ ),
18− -- | Huh!
19+ -- | Huh!
19− fooFoo,
20+ fooFoo,
20− barBar ::
21+ barBar ::
21− Int
22+ Int
22− }
23+ }
23 deriving (Eq, Show)
24 deriving (Eq, Show)
data/examples/declaration/data/simple-broken-out.hs+2−1
@@ -1,7 +1,8 @@
1module Main where
1module Main where
2
2
3-- | Here we go.
3-- | Here we go.
4+data Foo
4−data Foo = Foo {unFoo :: Int}
5+ = Foo {unFoo :: Int}
5 deriving (Eq)
6 deriving (Eq)
6
7
7-- | And once again.
8-- | And once again.
data/examples/declaration/data/strictness-out.hs+1−3
@@ -1,6 +1,4 @@
1module Main where
1module Main where
2
2
3-- | Something.
3-- | Something.
4−data Foo
5− = Foo1 !Int {-# UNPACK #-} !Bool {-# NOUNPACK #-} !String
4+data Foo = Foo !Int {-# UNPACK #-} !Bool {-# NOUNPACK #-} !String
6− | Foo2 {a :: {-# UNPACK #-} Maybe Int && Bool}
data/examples/declaration/data/strictness.hs+1−3
@@ -2,6 +2,4 @@ module Main where
2
2
3-- | Something.
3-- | Something.
4
4
5−data Foo
6− = Foo1 !Int {-# UNPACK #-} !Bool {-# NOUNPACK #-} !String
5+data Foo = Foo !Int {-# UNPACK #-} !Bool {-# NOUNPACK #-} !String
7− | Foo2 { a :: {-# UNPACK #-} Maybe Int && Bool }
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/foreign/foreign-export-out.hs+1−2
@@ -2,8 +2,7 @@ foreign export ccall foo :: Int -> IO Int
2
2
3-- | 'foreignTomFun' is a very important thing
3-- | 'foreignTomFun' is a very important thing
4foreign export ccall "tomography"
4foreign export ccall "tomography"
5− foreignTomFun ::
6− StablePtr Storage {- Storage is bad -} -> TomForegin
5+ foreignTomFun :: StablePtr Storage {- Storage is bad -} -> TomForegin
7
6
8foreign export {- We can't use capi here -} ccall "dynamic"
7foreign export {- We can't use capi here -} ccall "dynamic"
9 export_nullaryMeth :: (IO HRESULT) -> IO (Ptr ())
8 export_nullaryMeth :: (IO HRESULT) -> IO (Ptr ())
data/examples/declaration/instance/associated-data-out.hs+2
@@ -11,7 +11,9 @@ instance Foo Double where
11 Double
11 Double
12
12
13instance Foo [a] where
13instance Foo [a] where
14+
14 data Bar [a]
15 data Bar [a]
15 = ListBar [Bar a]
16 = ListBar [Bar a]
17+
16 data Baz [a]
18 data Baz [a]
17 = ListBaz
19 = ListBaz
data/examples/declaration/instance/associated-data.hs−1
@@ -13,7 +13,6 @@ instance Foo Double where
13
13
14instance Foo [a]
14instance Foo [a]
15 where
15 where
16−
17 data Bar [a] =
16 data Bar [a] =
18 ListBar [Bar a]
17 ListBar [Bar a]
19 data Baz [a] =
18 data Baz [a] =
data/examples/declaration/instance/associated-types-out.hs+1
@@ -3,6 +3,7 @@
3instance Foo Int where type Bar Int = Double
3instance Foo Int where type Bar Int = Double
4
4
5instance Foo Double where
5instance Foo Double where
6+
6 type
7 type
7 Bar
8 Bar
8 Double =
9 Double =
data/examples/declaration/instance/associated-types.hs−2
@@ -9,7 +9,5 @@ instance Foo Double
9 Double
9 Double
10 =
10 =
11 [Double]
11 [Double]
12−
13−
14 type instance Baz Double
12 type instance Baz Double
15 = [Double]
13 = [Double]
data/examples/declaration/instance/data-family-instances-gadt-out.hs+2−4
@@ -3,11 +3,9 @@
3
3
4data instance Bar Int a where
4data instance Bar Int a where
5 SameBar ::
5 SameBar ::
6− Bar
6+ Bar Int
7− Int
8 Int
7 Int
9 CloseBar :: Bar Int Double
8 CloseBar :: Bar Int Double
10 OtherBar ::
9 OtherBar ::
11− Bar
10+ Bar Int
12− Int
13 a
11 a
data/examples/declaration/instance/data-family-instances-newtype-out.hs+4−3
@@ -1,6 +1,7 @@
1{-# LANGUAGE GADTSyntax #-}
1{-# LANGUAGE GADTSyntax #-}
2{-# LANGUAGE TypeFamilies #-}
2{-# LANGUAGE TypeFamilies #-}
3
3
4−newtype instance Foo [Double] = DoubleListFoo
4+newtype instance Foo [Double]
5+ = DoubleListFoo
5− { unDoubleListFoo :: Double
6+ { unDoubleListFoo :: Double
6− }
7+ }
data/examples/declaration/instance/instance-sigs-multiple-out.hs+2
@@ -1,10 +1,12 @@
1{-# LANGUAGE InstanceSigs #-}
1{-# LANGUAGE InstanceSigs #-}
2
2
3instance Applicative [] where
3instance Applicative [] where
4+
4 pure ::
5 pure ::
5 a ->
6 a ->
6 [a]
7 [a]
7 pure a = [a]
8 pure a = [a]
9+
8 (<*>) ::
10 (<*>) ::
9 [a] -> [a] -> [a]
11 [a] -> [a] -> [a]
10 (<*>) _ _ = []
12 (<*>) _ _ = []
data/examples/declaration/instance/multi-parameter-out.hs+2
@@ -1,5 +1,7 @@
1instance MonadReader a ((->) a) where ask = id
1instance MonadReader a ((->) a) where ask = id
2
2
3instance MonadState s (State s) where
3instance MonadState s (State s) where
4+
4 get = State.get
5 get = State.get
6+
5 put = State.put
7 put = State.put
data/examples/declaration/instance/newlines-after-where-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−instance Num X where
2− (+) = undefined
3−
4−instance Num Y where
5− (+) = undefined
data/examples/declaration/instance/newlines-after-where.hsdeleted−7
@@ -1,7 +0,0 @@
1−instance Num X where
2− (+) = undefined
3−
4−instance Num Y where
5−
6−
7− (+) = undefined
data/examples/declaration/instance/newlines-between-methods-out.hsdeleted−18
@@ -1,18 +0,0 @@
1−instance Num a => Num (Diff a) where
2− D u dudx + D v dvdx = D (u + v) (dudx + dvdx)
3− D u dudx - D v dvdx = D (u - v) (dudx - dvdx)
4− D u dudx * D v dvdx = D (u * v) (u * dvdx + v * dudx)
5−
6− -- Comment before definition
7− negate (D u dudx) = D (- u) (- dudx)
8− negate (Z u dudx) = undefined
9−
10− -- Comment after definition
11−
12− -- Separator
13−
14− abs (D u _) = D (abs u) (signum u)
15− signum (D u _) = D (signum u) 0
16−
17− -- Comment between unrelated definitions
18− fromInteger n = D (fromInteger n) 0
data/examples/declaration/instance/newlines-between-methods.hsdeleted−16
@@ -1,16 +0,0 @@
1−instance Num a => Num (Diff a) where
2− D u dudx + D v dvdx = D (u + v) (dudx + dvdx)
3− D u dudx - D v dvdx = D (u - v) (dudx - dvdx)
4− D u dudx * D v dvdx = D (u * v) (u * dvdx + v * dudx)
5−
6− -- Comment before definition
7− negate (D u dudx) = D (-u) (-dudx)
8− negate (Z u dudx) = undefined
9− -- Comment after definition
10−
11− -- Separator
12−
13− abs (D u _) = D (abs u) (signum u)
14− signum (D u _) = D (signum u) 0
15− -- Comment between unrelated definitions
16− fromInteger n = D (fromInteger n) 0
data/examples/declaration/instance/single-parameter-out.hs+2
@@ -1,7 +1,9 @@
1instance Monoid Int where (<>) x y = x + y
1instance Monoid Int where (<>) x y = x + y
2
2
3instance Enum Int where
3instance Enum Int where
4+
4 fromEnum x = x
5 fromEnum x = x
6+
5 toEnum =
7 toEnum =
6 \x ->
8 \x ->
7 x
9 x
data/examples/declaration/rewrite-rule/forall-1-out.hsdeleted−23
@@ -1,23 +0,0 @@
1−{-# RULES "rd_tyvs" forall a. forall (x :: a). id x = x #-}
2−
3−{-# RULES "rd_tyvs'" forall f a. forall (x :: f a). id x = x #-}
4−
5−{-# RULES "rd_tyvs''" forall (a :: *). forall (x :: a). id x = x #-}
6−
7−{-# RULES
8−"rd_tyvs_multiline1" forall (a :: *). forall (x :: a).
9− id x =
10− x
11− #-}
12−
13−{-# RULES
14−"rd_tyvs_multiline2" forall
15− ( a ::
16− *
17− ). forall
18− ( x ::
19− a
20− ).
21− id x =
22− x
23− #-}
data/examples/declaration/rewrite-rule/forall-1.hsdeleted−17
@@ -1,17 +0,0 @@
1−{-# RULES "rd_tyvs" forall a. forall (x :: a). id x = x #-}
2−
3−{-# RULES "rd_tyvs'" forall f a. forall (x :: f a). id x = x #-}
4−
5−{-# RULES "rd_tyvs''" forall (a :: *). forall (x :: a). id x = x #-}
6−
7−{-# RULES "rd_tyvs_multiline1"
8− forall (a :: *).
9− forall (x :: a).
10− id x = x #-}
11−
12−{-# RULES "rd_tyvs_multiline2"
13− forall (a ::
14− *).
15− forall (x ::
16− a).
17− id x = x #-}
data/examples/declaration/rewrite-rule/forall-0-out.hs → data/examples/declaration/rewrite-rule/forall-out.hsrenamed

The content is the same.

data/examples/declaration/rewrite-rule/forall-0.hs → data/examples/declaration/rewrite-rule/forall.hsrenamed

The content is the same.

data/examples/declaration/signature/minimal/minimal-out.hs+2
@@ -1,4 +1,5 @@
1class Foo a where
1class Foo a where
2+
2 {-# MINIMAL (==) | ((/=), foo) #-}
3 {-# MINIMAL (==) | ((/=), foo) #-}
3
4
4 {-# MINIMAL
5 {-# MINIMAL
@@ -11,4 +12,5 @@ class Foo a where
11 #-}
12 #-}
12
13
13 (==) :: a -> a -> Bool
14 (==) :: a -> a -> Bool
15+
14 (/=) :: a -> a -> Bool
16 (/=) :: a -> a -> Bool
data/examples/declaration/signature/specialize/specialize-instance-out.hs+4
@@ -3,12 +3,16 @@ data Foo a = Foo a
3data VT v m r = VT v m r
3data VT v m r = VT v m r
4
4
5instance (Eq a) => Eq (Foo a) where
5instance (Eq a) => Eq (Foo a) where
6+
6 {-# SPECIALIZE instance Eq (Foo [(Int, Bar)]) #-}
7 {-# SPECIALIZE instance Eq (Foo [(Int, Bar)]) #-}
8+
7 (==) (Foo a) (Foo b) = (==) a b
9 (==) (Foo a) (Foo b) = (==) a b
8
10
9instance (Num r, V.Vector v r, Factored m r) => Num (VT v m r) where
11instance (Num r, V.Vector v r, Factored m r) => Num (VT v m r) where
12+
10 {-# SPECIALIZE instance
13 {-# SPECIALIZE instance
11 ( Factored m Int => Num (VT U.Vector m Int)
14 ( Factored m Int => Num (VT U.Vector m Int)
12 )
15 )
13 #-}
16 #-}
17+
14 VT x + VT y = VT $ V.zipWith (+) x y
18 VT x + VT y = VT $ V.zipWith (+) x y
data/examples/declaration/signature/standalone-kind-out.hsdeleted−13
@@ -1,13 +0,0 @@
1−{-# LANGUAGE StandaloneKindSignatures #-}
2−
3−type T ::
4− (k -> Type) ->
5− k ->
6− Type
7−data T m a = MkT (m a) (T Maybe (m a))
8−
9−type C1 :: Type -> Constraint
10−class C1 a
11−
12−type F :: Type -> Type
13−type family F
data/examples/declaration/signature/standalone-kind.hsdeleted−13
@@ -1,13 +0,0 @@
1−{-# LANGUAGE StandaloneKindSignatures #-}
2−
3−type T :: (k -> Type)
4− -> k
5− -> Type
6−
7−data T m a = MkT (m a) (T Maybe (m a))
8−
9−type C1 :: Type -> Constraint
10−class C1 a
11−
12−type F :: Type -> Type
13−type family F
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/long-multiline-applications-out.hs−1
@@ -1,6 +1,5 @@
1functionName ::
1functionName ::
2 (C1, C2, C3, C4, C5) =>
2 (C1, C2, C3, C4, C5) =>
3− forall a b c.
4 a ->
3 a ->
5 b ->
4 b ->
6 ( LongDataTypeName
5 ( LongDataTypeName
data/examples/declaration/signature/type/long-multiline-applications.hs+1−2
@@ -1,7 +1,6 @@
1functionName
1functionName
2 :: (C1, C2, C3, C4, C5)
2 :: (C1, C2, C3, C4, C5)
3− => forall a b c
4− . a
3+ => a
5 -> b
4 -> b
6 -> ( LongDataTypeName
5 -> ( LongDataTypeName
7 AnotherLongDataTypeName
6 AnotherLongDataTypeName
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/splice/grouped-splices-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−$(deriveJSON fieldLabelMod ''A)
2−$(deriveJSON fieldLabelMod ''B)
3−$(deriveJSON fieldLabelMod ''C)
data/examples/declaration/splice/grouped-splices.hsdeleted−3
@@ -1,3 +0,0 @@
1−$(deriveJSON fieldLabelMod ''A)
2−$(deriveJSON fieldLabelMod ''B)
3−$(deriveJSON fieldLabelMod ''C)
data/examples/declaration/splice/splice-decl.hs+1
@@ -15,3 +15,4 @@ foo bar
15-- TemplateHaskell allows Q () at the top level
15-- TemplateHaskell allows Q () at the top level
16do
16do
17 pure []
17 pure []
18+
data/examples/declaration/type-families/closed-type-family/multi-line-out.hs+5−6
@@ -1,7 +1,7 @@
1type family
1type family
2 Id a =
2 Id a =
3− result | result -> a
3+ result
4− where
4+ | result -> a where
5 Id a =
5 Id a =
6 a
6 a
7
7
@@ -10,15 +10,14 @@ type family
10 (a :: k)
10 (a :: k)
11 b
11 b
12 c =
12 c =
13− foo | foo -> k b
13+ foo
14− where
14+ | foo -> k b where
15 G a b c =
15 G a b c =
16 (a, b)
16 (a, b)
17
17
18type family
18type family
19 F a ::
19 F a ::
20− * -> *
21− where
20+ * -> * where
22 F Int = Double
21 F Int = Double
23 F Bool =
22 F Bool =
24 Char
23 Char
data/examples/declaration/type-families/closed-type-family/with-equal-sign-out.hsdeleted−2
@@ -1,2 +0,0 @@
1−type family TF a b = result where
2− TF a b = Int
data/examples/declaration/type-families/closed-type-family/with-equal-sign.hsdeleted−2
@@ -1,2 +0,0 @@
1−type family TF a b = result where
2− TF a b = Int
data/examples/declaration/type-families/closed-type-family/with-forall-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−type family G a b where
2− forall x y. G [x] (Proxy y) = Double
3− forall z. z `G` z = Bool
data/examples/declaration/type-families/closed-type-family/with-forall.hsdeleted−3
@@ -1,3 +0,0 @@
1−type family G a b where
2− forall x y. G [x] (Proxy y) = Double
3− forall z. z `G` z = Bool
data/examples/declaration/type-families/type-family/operator-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−type family a ! b
2−
3−type family a . b
data/examples/declaration/type-families/type-family/operator.hsdeleted−2
@@ -1,2 +0,0 @@
1−type family a ! b
2−type family a . b
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/type/type-applications-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−{-# LANGUAGE TypeApplications #-}
2−
3−type P = K @Bool @(Bool :: *) 'True 'False
data/examples/declaration/type/type-applications.hsdeleted−3
@@ -1,3 +0,0 @@
1−{-# LANGUAGE TypeApplications #-}
2−
3−type P = K @Bool @(Bool :: *) 'True 'False
data/examples/declaration/type/visible-forall-out.hsdeleted−2
@@ -1,2 +0,0 @@
1−-- source: https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0081-forall-arrow.rst
2−data T :: forall k -> k -> Type
data/examples/declaration/type/visible-forall.hsdeleted−2
@@ -1,2 +0,0 @@
1−-- source: https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0081-forall-arrow.rst
2−data T :: forall k -> k -> Type
data/examples/declaration/value/function/application-1-out.hsdeleted−19
@@ -1,19 +0,0 @@
1−main =
2− do
3− x
4− y
5− z
6−
7−main =
8− case foo of
9− x -> a
10− foo
11− a
12− b
13−
14−main =
15− do
16− if x then y else z
17− foo
18− a
19− b
data/examples/declaration/value/function/application-1.hsdeleted−14
@@ -1,14 +0,0 @@
1−main =
2− do
3− x
4− y
5− z
6−
7−main =
8− case foo of
9− x -> a
10− foo a b
11−
12−main = do
13− if x then y else z
14− foo a b
data/examples/declaration/value/function/application-0-out.hs → data/examples/declaration/value/function/application-out.hsrenamed

The content is the same.

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

The content is the same.

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/expression-applications-out.hsnew file+9
@@ -0,0 +1,9 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo x y = x -< y
4+
5+bar f x =
6+ f x -< -- Hello
7+ x -- World
8+
9+baz x y = x -<< y
data/examples/declaration/value/function/arrow/expression-applications.hsnew file+9
@@ -0,0 +1,9 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo x y = x -< y
4+
5+bar f x
6+ = f x -- Hello
7+ -< x -- World
8+
9+baz x y = x -<< y
data/examples/declaration/value/function/arrow/expression-forms-out.hsnew file+14
@@ -0,0 +1,14 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo f g x y = (| test (f -< x) (g -< y) |)
4+
5+bar f g x y =
6+ (|
7+ test
8+ ( f -<
9+ x
10+ )
11+ ( g -<
12+ y
13+ )
14+ |)
data/examples/declaration/value/function/arrow/expression-forms.hsnew file+11
@@ -0,0 +1,11 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo f g x y = (| test (f -< x) (g -< y) |)
4+
5+bar f g x y = (|
6+ test
7+ (f
8+ -< x)
9+ (g
10+ -< y)
11+ |)
data/examples/declaration/value/function/arrow/multiline-case-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−{-# LANGUAGE Arrows #-}
2−
3−f = proc x -> do
4− x <-
5− case x of X -> x
6− -<
7− y
8− a -< b
data/examples/declaration/value/function/arrow/multiline-case.hsdeleted−7
@@ -1,7 +0,0 @@
1−{-# LANGUAGE Arrows #-}
2−
3−f = proc x -> do
4− x
5− <- case x of X -> x
6− -< y
7− a -< b
data/examples/declaration/value/function/arrow/proc-applications-out.hs+5−6
@@ -9,11 +9,10 @@ bar f x =
9 w
9 w
10 )
10 )
11 ->
11 ->
12− f -- The value
12+ f -< -- The value
13− -<
14− ( x, -- Foo
13+ ( x, -- Foo
15− w, -- Bar
14+ w, -- Bar
16− z -- Baz
15+ z -- Baz
17− )
16+ )
18
17
19baz x = proc a -> a -<< x
18baz x = proc a -> a -<< x
data/examples/declaration/value/function/arrow/proc-do-complex-out.hs+14−18
@@ -19,11 +19,10 @@ foo
19 )
19 )
20 ( b,
20 ( b,
21 d
21 d
22+ ) -<
23+ ( b + 1, -- Funnel into arrow
24+ d * b
22 )
25 )
23− -<
24− ( b + 1, -- Funnel into arrow
25− d * b
26− )
27 if x `mod` y == 0 -- Basic condition
26 if x `mod` y == 0 -- Basic condition
28 then case e of -- Only left case is relevant
27 then case e of -- Only left case is relevant
29 Left
28 Left
@@ -33,20 +32,18 @@ foo
33 let v =
32 let v =
34 u -- Actually never used
33 u -- Actually never used
35 ^ 2
34 ^ 2
36− in ( returnA
35+ in ( returnA -<
37− -<
38− -- Just do the calculation
36+ -- Just do the calculation
39− (x + y * z)
37+ (x + y * z)
40 )
38 )
41 else do
39 else do
42 let u = x -- Let bindings bind expressions, not commands
40 let u = x -- Let bindings bind expressions, not commands
43− -- Could pattern match directly on x
41+ -- Could pattern match directly on x
44 i <- case u of
42 i <- case u of
45 0 -> (g . h -< u)
43 0 -> (g . h -< u)
46 n ->
44 n ->
47− ( ( h . g
45+ ( ( h . g -<
48− -<
49− y -- First actual use of y
46+ y -- First actual use of y
50 )
47 )
51 )
48 )
52 returnA -< ()
49 returnA -< ()
@@ -54,9 +51,8 @@ foo
54 if i > 0
51 if i > 0
55 then ma -< ()
52 then ma -< ()
56 else returnA -< ()
53 else returnA -< ()
57− returnA
54+ returnA -<
58− -<
59− ( i
55+ ( i
60− + x
56+ + x
61− * y -- Just do the calculation
57+ * y -- Just do the calculation
62− )
58+ )
data/examples/declaration/value/function/arrow/proc-do-simple1-out.hs+2−3
@@ -13,6 +13,5 @@ barbaz f g = proc (a, b) -> do
13
13
14bazbar f = proc a -> do
14bazbar f = proc a -> do
15 a <-
15 a <-
16− f
16+ f -<
17− -<
18− a
17+ a
data/examples/declaration/value/function/arrow/proc-do-simple2-out.hs+7−9
@@ -11,12 +11,10 @@ bazbaz f g h = proc (a, b, c) -> do
11 z <-
11 z <-
12 h
12 h
13 x
13 x
14− y
14+ y -<
15− -<
16− ( a,
15+ ( a,
17− b,
16+ b,
18− c
17+ c
19− )
18+ )
20− returnA
19+ returnA -<
21− -<
22− (x, y, z)
20+ (x, y, z)
data/examples/declaration/value/function/arrow/proc-forms1-out.hs+6−8
@@ -7,15 +7,13 @@ foo1 f g h x =
7 (|
7 (|
8 test
8 test
9 ( h f
9 ( h f
10− . h g
10+ . h g -<
11− -<
12− y x
11+ y x
13− . y z
12+ . y z
14 )
13 )
15 ( h g
14 ( h g
16− . h f
15+ . h f -<
17− -<
18− y z
16+ y z
19− . y x
17+ . y x
20 )
18 )
21 |)
19 |)
data/examples/declaration/value/function/arrow/proc-forms2-out.hs+6−10
@@ -4,19 +4,15 @@ bar0 f g h x =
4 proc (y, z) ->
4 proc (y, z) ->
5 (| test (h f . (h g) -< (y x) . y z) ((h g) . h f -< y z . (y x)) |)
5 (| test (h f . (h g) -< (y x) . y z) ((h g) . h f -< y z . (y x)) |)
6
6
7−bar1 f g x y = proc _ -> (f -< x) &&& (g -< y)
7+bar1 f g x y = proc _ -> f -< x &&& g -< y
8
8
9bar2 f g h x =
9bar2 f g h x =
10 proc (y, z) ->
10 proc (y, z) ->
11− (h f . (h g) -< (y x) . y z) ||| ((h g) . h f -< y z . (y x))
11+ h f . (h g) -< (y x) . y z ||| (h g) . h f -< y z . (y x)
12
12
13bar3 f g h x =
13bar3 f g h x =
14 proc (y, z) ->
14 proc (y, z) ->
15− ( (h f . h g)
15+ (h f . h g) -<
16− -<
17− (y x) . y z
16+ (y x) . y z
18− ) |||
19− ( (h g . h f)
17+ ||| (h g . h f) -<
20− -<
21− y z . (y x)
18+ y z . (y x)
22− )
data/examples/declaration/value/function/arrow/proc-forms2.hs+6−6
@@ -4,16 +4,16 @@ bar0 f g h x =
4 proc (y, z) ->
4 proc (y, z) ->
5 (| test (h f.(h g) -< (y x).y z)((h g) . h f-<y z . (y x)) |)
5 (| test (h f.(h g) -< (y x).y z)((h g) . h f-<y z . (y x)) |)
6
6
7−bar1 f g x y = proc _ -> (f -< x)&&&(g -< y)
7+bar1 f g x y = proc _ -> f -< x&&&g -< y
8
8
9bar2 f g h x =
9bar2 f g h x =
10 proc (y, z) ->
10 proc (y, z) ->
11− (h f.(h g) -< (y x).y z) ||| ((h g) . h f-<y z . (y x))
11+ h f.(h g) -< (y x).y z ||| (h g) . h f-<y z . (y x)
12
12
13bar3 f g h x =
13bar3 f g h x =
14 proc (y, z) ->
14 proc (y, z) ->
15− ((h f.h g)
15+ (h f.h g)
16− -< (y x).y z)
16+ -< (y x).y z
17 |||
17 |||
18− ((h g . h f)
18+ (h g . h f)
19− -<y z . (y x))
19+ -<y z . (y x)
data/examples/declaration/value/function/arrow/proc-ifs-out.hs+4−6
@@ -6,10 +6,8 @@ bar f g = proc a ->
6 if f a
6 if f a
7 then
7 then
8 f
8 f
9− . g
9+ . g -<
10− -<
11− a
10+ a
12 else
11 else
13− g
12+ g -<
14− -<
15− b
13+ b
data/examples/declaration/value/function/arrow/proc-parentheses-out.hs+4−5
@@ -6,14 +6,13 @@ bar f g = proc a ->
6 ( ( (f)
6 ( ( (f)
7 ( g
7 ( g
8 )
8 )
9− )
9+ ) -<
10− -<
11− ( ( ( ( ( ( g
10+ ( ( ( ( ( ( g
12− a
11+ a
13− )
14 )
12 )
15 )
13 )
16 )
14 )
17 )
15 )
18 )
16 )
17+ )
19 )
18 )
data/examples/declaration/value/function/arrow/recursive-procs-out.hs+10−14
@@ -3,21 +3,17 @@
3foo f g = proc (x, y) -> do
3foo f g = proc (x, y) -> do
4 rec a <- f y -< x
4 rec a <- f y -< x
5 b <-
5 b <-
6− g x
6+ g x -<
7− -<
8− y
7+ y
9− bar
8+ bar -<
10− -<
11− ( a,
9+ ( a,
12− b
10+ b
13− )
11+ )
14 rec p <-
12 rec p <-
15 f
13 f
16− p
14+ p -<
17− -<
18− a
15+ a
19 rec q <-
16 rec q <-
20 g
17 g
21− q
18+ q -<
22− -<
23− b
19+ b
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/block-arguments-out.hs−5
@@ -27,8 +27,3 @@ f8 = foo \x ->
27 y
27 y
28
28
29f9 = foo do { bar } baz
29f9 = foo do { bar } baz
30−
31−f10 = foo
32− do a
33− do b
34− do c
data/examples/declaration/value/function/block-arguments.hs−5
@@ -23,8 +23,3 @@ f8 = foo \x ->
23 y
23 y
24
24
25f9 = foo do { bar } baz
25f9 = foo do { bar } baz
26−
27−f10 = foo
28− do { a }
29− do { b }
30− do c
data/examples/declaration/value/function/do/blocks-out.hs−1
@@ -15,5 +15,4 @@ readInClause = do
15 <|> do
15 <|> do
16 optional g_Semi
16 optional g_Semi
17 void allspacing
17 void allspacing
18−
19 return things
18 return things
data/examples/declaration/value/function/do/comment-alignment-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−main = do
2− case blah of
3− Nothing -> return ()
4− Just xs -> do
5− forM_ xs foo
6− bar
7− -- and here it goes
8− unless bobla $
9− quux
data/examples/declaration/value/function/do/comment-alignment.hsdeleted−9
@@ -1,9 +0,0 @@
1−main = do
2− case blah of
3− Nothing -> return ()
4− Just xs -> do
5− forM_ xs foo
6− bar
7− -- and here it goes
8− unless bobla $
9− quux
data/examples/declaration/value/function/do/comment-spacing-out.hsdeleted−7
@@ -1,7 +0,0 @@
1−foo = do
2− bar
3− -- foo
4− baz
5−
6− -- foo
7− quux
data/examples/declaration/value/function/do/comment-spacing.hsdeleted−7
@@ -1,7 +0,0 @@
1−foo = do
2− bar
3− -- foo
4− baz
5−
6− -- foo
7− quux
data/examples/declaration/value/function/do/recursive-do-rec-out.hs−5
@@ -2,18 +2,13 @@
2
2
3foo = do
3foo = do
4 rec a <- b + 5
4 rec a <- b + 5
5−
6 let d = c
5 let d = c
7−
8 b <- a * 5
6 b <- a * 5
9−
10 something
7 something
11−
12 c <- a + b
8 c <- a + b
13 print c
9 print c
14 rec something $ do
10 rec something $ do
15 x <- a
11 x <- a
16 print x
12 print x
17−
18 y <- c
13 y <- c
19 print y
14 print y
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−7
@@ -13,10 +13,6 @@ 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−
20−x =
21− case l of { A -> B } $
22− case q of r -> s
data/examples/declaration/value/function/infix/dollar-chains.hs−4
@@ -16,7 +16,3 @@ foo =
16 bar
16 bar
17 $ baz
17 $ baz
18 $ quux
18 $ quux
19−
20−x =
21− case l of { A -> B } $
22− case q of r -> s
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/let-single-line-out.hs+1
@@ -5,6 +5,7 @@ foo x = let x = z where { z = 2 }; a = 3 in x
5foo x = let g :: Int -> Int; g = id in ()
5foo x = let g :: Int -> Int; g = id in ()
6
6
7let a = b; c = do { foo; bar }; d = baz in b
7let a = b; c = do { foo; bar }; d = baz in b
8+
8let a = case True of { True -> foo; False -> bar }; b = foo a in b
9let a = case True of { True -> foo; False -> bar }; b = foo a in b
9
10
10foo x = let ?g = id; ?f = g in x
11foo x = let ?g = id; ?f = g in x
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+4−10
@@ -4,13 +4,7 @@ foo x = if | x == 5 -> 5
4
4
5bar x y =
5bar x y =
6 if
6 if
7− | x > y -> x
7+ | x > y -> x
8− | x < y ->
8+ | x < y ->
9− y
9+ y
10− | otherwise -> x
11−
12−baz =
13− if
14− | p -> f
15− | otherwise -> g
10+ | otherwise -> x
16− x
data/examples/declaration/value/function/multi-way-if.hs−5
@@ -7,8 +7,3 @@ bar x y = if
7 | x < y
7 | x < y
8 -> y
8 -> y
9 | otherwise -> x
9 | otherwise -> x
10−
11−baz =
12− if | p -> f
13− | otherwise -> g
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-0-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−a =
2− b & c .~ d
3− & e
4− %~ f
5− g
data/examples/declaration/value/function/operators-0.hsdeleted−4
@@ -1,4 +0,0 @@
1−a =
2− b & c .~ d
3− & e %~ f
4− g
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/overindentation-out.hs+9−11
@@ -1,11 +1,9 @@
1−reallyincrediblyLongName =
1+reallyincrediblyLongName = f
2− f
3− a
2+ a
4− A
3+ A
5− { reallyincrediblyLongName =
4+ { reallyincrediblyLongName = f
6− f
7− a
5+ a
8− A
6+ A
9− { reallyincrediblyLongName
7+ { reallyincrediblyLongName
10− }
8+ }
11− }
9+ }
data/examples/declaration/value/function/pattern/famous-cardano-pattern-out.hs+8−8
@@ -1,8 +1,8 @@
1−( getNodeSettingsR
1+( getNodeSettingsR :<|>
2− :<|> getNodeInfoR
2+ getNodeInfoR :<|>
3− :<|> getNextUpdateR
3+ getNextUpdateR :<|>
4− :<|> restartNodeR
4+ restartNodeR
5− )
5+ ) :<|>
6− :<|> ( getUtxoR
6+ ( getUtxoR :<|>
7− :<|> getConfirmedProposalsR
7+ getConfirmedProposalsR
8− ) = client nodeV1Api
8+ ) = client nodeV1Api
data/examples/declaration/value/function/pattern/multiline-case-pattern-out.hs+2−2
@@ -10,6 +10,6 @@ f xs = case xs of
10 ] -> a + b
10 ] -> a + b
11
11
12g xs = case xs of
12g xs = case xs of
13− ( a
13+ ( a :
14− : bs
14+ bs
15 ) -> a + b
15 ) -> a + b
data/examples/declaration/value/function/pattern/view-pattern-out.hs+3
@@ -13,3 +13,6 @@ multiline
13 bar
13 bar
14 baz
14 baz
15 ) = True
15 ) = True
16+
17+-- https://github.com/tweag/ormolu/issues/343
18+foo = (f -> 4)
data/examples/declaration/value/function/pattern/view-pattern.hs+3
@@ -10,3 +10,6 @@ g ((f, _), f -> 4) = True
10multiline (t -> Foo
10multiline (t -> Foo
11 bar
11 bar
12 baz) = True
12 baz) = True
13+
14+-- https://github.com/tweag/ormolu/issues/343
15+foo = (f -> 4)
data/examples/declaration/value/function/record-constructors-out.hsnew file+27
@@ -0,0 +1,27 @@
1+foo = Foo {a = 3}
2+
3+bar = Bar
4+ { abc = foo,
5+ def = Foo {a = 10}
6+ }
7+
8+baz = Baz {}
9+
10+sym = Foo {(+) = 3}
11+
12+aLongVariableName =
13+ ALongRecordName
14+ { short = baz,
15+ aLongRecordFieldName = YetAnotherLongRecordName
16+ { yetAnotherLongRecordFieldName = "a long string"
17+ },
18+ aLongRecordFieldName2 = Just YetAnotherLongRecordName
19+ { yetAnotherLongRecordFieldName = "a long string",
20+ yetAnotherLongRecordFieldName =
21+ Just
22+ "a long string"
23+ },
24+ aLongRecordFieldName3 = do
25+ foo
26+ bar
27+ }
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/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+6−7
@@ -3,12 +3,11 @@
3
3
4foo x y = Foo {x, y}
4foo x y = Foo {x, y}
5
5
6−bar x y z =
6+bar x y z = Bar
7− Bar
8− { x,
7+ { x,
9− y,
8+ y,
10− z,
9+ z,
11− ..
10+ ..
12− }
11+ }
13
12
14baz = Baz {..}
13baz = Baz {..}
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/constructors-out.hsdeleted−31
@@ -1,31 +0,0 @@
1−foo = Foo {a = 3}
2−
3−bar =
4− Bar
5− { abc = foo,
6− def = Foo {a = 10}
7− }
8−
9−baz = Baz {}
10−
11−sym = Foo {(+) = 3}
12−
13−aLongVariableName =
14− ALongRecordName
15− { short = baz,
16− aLongRecordFieldName =
17− YetAnotherLongRecordName
18− { yetAnotherLongRecordFieldName = "a long string"
19− },
20− aLongRecordFieldName2 =
21− Just
22− YetAnotherLongRecordName
23− { yetAnotherLongRecordFieldName = "a long string",
24− yetAnotherLongRecordFieldName =
25− Just
26− "a long string"
27− },
28− aLongRecordFieldName3 = do
29− foo
30− bar
31− }
data/examples/declaration/value/function/record/dot-out.hsdeleted−15
@@ -1,15 +0,0 @@
1−{-# OPTIONS_GHC -fplugin=RecordDotPreprocessor #-}
2−
3−data Foo = Foo {bar :: Int}
4−
5−mfoo = fmap (.bar) $ Nothing
6−
7−bar = (Foo 1).bar
8−
9−fooplus f n = f{foo = f.bar + n}
10−
11−fooplus' f n = f {foo = f.bar + n}
12−
13−fooplus'' f n = f {foo = f.bar + n}
14−
15−fooplus''' f n = f {foo = f.bar + n}
data/examples/declaration/value/function/record/dot.hsdeleted−14
@@ -1,14 +0,0 @@
1−{-# OPTIONS_GHC -fplugin=RecordDotPreprocessor #-}
2−data Foo = Foo { bar :: Int }
3−
4−mfoo = fmap (.bar) $ Nothing
5−
6−bar = ( Foo 1).bar
7−
8−fooplus f n = f{foo = f.bar + n}
9−
10−fooplus' f n = f { foo = f.bar + n}
11−
12−fooplus'' f n = f {foo = f.bar + n}
13−
14−fooplus''' f n = f{ foo = f.bar + n}
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/record/inter-comments-out.hsdeleted−13
@@ -1,13 +0,0 @@
1−x =
2− Just
3− -- comment
4− A
5− { x
6− }
7−
8−x =
9− Just
10− -- comment
11− a
12− { x
13− }
data/examples/declaration/value/function/record/inter-comments.hsdeleted−11
@@ -1,11 +0,0 @@
1−x = Just
2− -- comment
3− A
4− { x
5− }
6−
7−x = Just
8− -- comment
9− a
10− { x
11− }
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/declaration/value/function/type-applications-out.hs−6
@@ -8,9 +8,3 @@ baz =
8 f @Int @String
8 f @Int @String
9 a
9 a
10 b
10 b
11−
12−goo =
13− hash
14− @(HASH TPraosStandardCrypto)
15− @ByteString
16− "And the lamb lies down on Broadway"
data/examples/declaration/value/function/type-applications.hs−5
@@ -6,8 +6,3 @@ bar = f @(Maybe Int) a b
6
6
7baz = f @Int @String
7baz = f @Int @String
8 a b
8 a b
9−
10−goo = hash
11− @(HASH TPraosStandardCrypto)
12− @ByteString
13− "And the lamb lies down on Broadway"
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.hsdeleted−5
@@ -1,5 +0,0 @@
1−{-# LANGUAGE ImportQualifiedPost #-}
2−
3−import Data.Text qualified (a, b, c)
4−import Data.Text qualified hiding (a, b, c)
5−import Data.Text qualified as T
data/examples/import/qualified-post.hsdeleted−5
@@ -1,5 +0,0 @@
1−{-# LANGUAGE ImportQualifiedPost #-}
2−
3−import qualified Data.Text as T
4−import qualified Data.Text (a, c, b)
5−import Data.Text qualified hiding (c, b, a)
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, (.))
3+import Prelude hiding ((.), id)
4import qualified Prelude
4import qualified Prelude
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.hsdeleted−8
@@ -1,8 +0,0 @@
1−{-
2− Here we go.
3−-}
4−
5−-- | This is the module's Haddock.
6−module Main (main) where
7−
8−main = return ()
data/examples/module-header/preceding-comment-with-haddock.hsdeleted−8
@@ -1,8 +0,0 @@
1−{-
2− Here we go.
3−-}
4−
5−-- | This is the module's Haddock.
6−module Main (main) where
7−
8−main = return ()
data/examples/module-header/shebang-out.hs−1
@@ -1,5 +1,4 @@
1#! /usr/bin/env runhaskell
1#! /usr/bin/env runhaskell
2−
3import Prelude
2import Prelude
4
3
5main :: IO ()
4main :: IO ()
data/examples/module-header/shebang-with-pragmas-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−#!/usr/bin/env stack
2−
3−{-# LANGUAGE OverloadedStrings #-}
4−
5−main = pure ()
data/examples/module-header/shebang-with-pragmas.hsdeleted−5
@@ -1,5 +0,0 @@
1−#!/usr/bin/env stack
2−
3−{-# LANGUAGE OverloadedStrings #-}
4−
5−main = pure ()
data/examples/module-header/shebang.hs−1
@@ -1,5 +1,4 @@
1#! /usr/bin/env runhaskell
1#! /usr/bin/env runhaskell
2−
3import Prelude
2import Prelude
4
3
5main :: IO ()
4main :: IO ()
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.hsdeleted−7
@@ -1,7 +0,0 @@
1−-- stack runhaskell
2−
3−{-# LANGUAGE OverloadedStrings #-}
4−
5−main = return ()
6−
7−-- stack runhaskell
data/examples/module-header/stack-header-0.hsdeleted−4
@@ -1,4 +0,0 @@
1−-- stack runhaskell
2−{-# LANGUAGE OverloadedStrings #-}
3−main = return ()
4−-- stack runhaskell
data/examples/module-header/stack-header-1-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−#!/usr/bin/env stack
2−-- stack runhaskell
3−
4−{-# LANGUAGE OverloadedStrings #-}
5−
6−main = return ()
7−
8−-- stack runhaskell
data/examples/module-header/stack-header-1.hsdeleted−5
@@ -1,5 +0,0 @@
1−#!/usr/bin/env stack
2−-- stack runhaskell
3−{-# LANGUAGE OverloadedStrings #-}
4−main = return ()
5−-- stack runhaskell
data/examples/module-header/stack-header-2-out.hsdeleted−12
@@ -1,12 +0,0 @@
1−#!/usr/bin/env stack
2−{- stack
3− script
4− --resolver lts-6.25
5− --package turtle
6− --package "stm async"
7− --package http-client,http-conduit
8−-}
9−
10−{-# LANGUAGE OverloadedStrings #-}
11−
12−main = return ()
data/examples/module-header/stack-header-2.hsdeleted−12
@@ -1,12 +0,0 @@
1−#!/usr/bin/env stack
2−{- stack
3− script
4− --resolver lts-6.25
5− --package turtle
6− --package "stm async"
7− --package http-client,http-conduit
8−-}
9−
10−{-# LANGUAGE OverloadedStrings #-}
11−
12−main = return ()
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-after-preceding-haddock-out.hsdeleted−12
@@ -1,12 +0,0 @@
1−module Main where
2−
3−-- | A
4−
5−-- B
6−
7−type D = E
8−
9−-- | This is 'f'
10−
11−-- * Comment
12−f :: a -> b
data/examples/other/comment-after-preceding-haddock.hsdeleted−12
@@ -1,12 +0,0 @@
1−module Main where
2−
3−-- | A
4−
5−-- B
6−
7−type D = E
8−
9−-- | This is 'f'
10−
11−-- * Comment
12−f :: a -> b
data/examples/other/comment-alignment-out.hs+1
@@ -1,4 +1,5 @@
1class Foo a where
1class Foo a where
2+
2 -- | Foo.
3 -- | Foo.
3 foo ::
4 foo ::
4 Int ->
5 Int ->
data/examples/other/comment-before-hanging-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−x = Just
2− -- comment
3− do
4− foo
5− bar
data/examples/other/comment-before-hanging.hsdeleted−5
@@ -1,5 +0,0 @@
1−x = Just
2− -- comment
3− do
4− foo
5− bar
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/disabling/single-definition-out.hsdeleted−10
@@ -1,10 +0,0 @@
1−module Foo (foo, bar) where
2−
3−{- ORMOLU_DISABLE -}
4−foo :: Int -> Int
5−foo = (+5)
6−{- ORMOLU_ENABLE -}
7−
8−bar :: Bool -> Bool
9−bar True = True
10−bar False = True
data/examples/other/disabling/single-definition.hsdeleted−10
@@ -1,10 +0,0 @@
1−module Foo (foo,bar) where
2−
3−{- ORMOLU_DISABLE -}
4−foo :: Int -> Int
5−foo = (+5)
6−{- ORMOLU_ENABLE -}
7−
8−bar :: Bool -> Bool
9−bar True = True
10−bar False = True
data/examples/other/disabling/whole-file-out.hsdeleted−10
@@ -1,10 +0,0 @@
1−{- ORMOLU_DISABLE -}
2−
3−module Foo (foo,bar) where
4−
5−foo :: Int -> Int
6−foo = (+5)
7−
8−bar :: Bool -> Bool
9−bar True = True
10−bar False = True
data/examples/other/disabling/whole-file.hsdeleted−10
@@ -1,10 +0,0 @@
1−{- ORMOLU_DISABLE -}
2−
3−module Foo (foo,bar) where
4−
5−foo :: Int -> Int
6−foo = (+5)
7−
8−bar :: Bool -> Bool
9−bar True = True
10−bar False = True
data/examples/other/empty-forall-out.hsdeleted−18
@@ -1,18 +0,0 @@
1−-- Empty foralls are handled correctly in different situations.
2−
3−data D = forall. D Int
4−
5−data G where
6− G :: forall. Int -> G
7−
8−f :: forall. a -> a
9−f x = x
10−
11−type family T x where
12− forall. T x = x
13−
14−{-# RULES
15−"r"
16− r a =
17− ()
18− #-}
data/examples/other/empty-forall.hsdeleted−17
@@ -1,17 +0,0 @@
1−-- Empty foralls are handled correctly in different situations.
2−
3−data D = forall. D Int
4−
5−data G where
6− G :: forall. Int -> G
7−
8−f :: forall. a -> a
9−f x = x
10−
11−type family T x where
12− forall. T x = x
13−
14−{-# RULES
15− "r"
16− forall. r a = ()
17−#-}
data/examples/other/haddock-sections-out.hsdeleted−7
@@ -1,7 +0,0 @@
1−-- $weird #anchor#
2−--
3−-- Section 1
4−
5−-- $normal
6−--
7−-- Section 2
data/examples/other/haddock-sections.hsdeleted−7
@@ -1,7 +0,0 @@
1−-- $weird #anchor#
2−--
3−-- Section 1
4−
5−-- $normal
6−--
7−-- Section 2
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/multiline-forall-out.hsdeleted−58
@@ -1,58 +0,0 @@
1−{-# LANGUAGE GADTs #-}
2−{-# LANGUAGE PolyKinds #-}
3−{-# LANGUAGE RankNTypes #-}
4−{-# LANGUAGE TypeFamilies #-}
5−
6−-- Multiline foralls are consistent across all declarations
7−
8−data D
9− = forall
10− ( f ::
11− * -> * -> *
12− )
13− (x :: *)
14− (y :: *).
15− D (f x y)
16−
17−data G where
18− G ::
19− forall
20− ( f ::
21− * -> * -> *
22− )
23− (x :: *)
24− (y :: *).
25− f x y ->
26− G
27−
28−f ::
29− forall
30− ( f ::
31− * -> * -> *
32− )
33− (x :: *)
34− (y :: *).
35− f x y ->
36− ()
37−f = const ()
38−
39−type family T f x y where
40− forall
41− ( f ::
42− * -> * -> *
43− )
44− (x :: *)
45− (y :: *).
46− T f x y =
47− f x y
48−
49−{-# RULES
50−"r" forall
51− ( f ::
52− * -> * -> *
53− )
54− (x :: *)
55− (y :: *).
56− r (a :: f x y) =
57− ()
58− #-}
data/examples/other/multiline-forall.hsdeleted−46
@@ -1,46 +0,0 @@
1−{-# LANGUAGE RankNTypes, PolyKinds, GADTs, TypeFamilies #-}
2−
3−-- Multiline foralls are consistent across all declarations
4−
5−data D =
6− forall
7− (f ::
8− * -> * -> *)
9− (x :: *)
10− (y :: *)
11− . D (f x y)
12−
13−data G where
14− G :: forall
15− (f ::
16− * -> * -> *)
17− (x :: *)
18− (y :: *)
19− . f x y -> G
20−
21−f :: forall
22− (f ::
23− * -> * -> *)
24− (x :: *)
25− (y :: *)
26− . f x y -> ()
27−f = const ()
28−
29−type family T f x y where
30− forall
31− (f ::
32− * -> * -> *)
33− (x :: *)
34− (y :: *)
35− . T f x y = f x y
36−
37−{-# RULES
38− "r"
39− forall
40− (f ::
41− * -> * -> *)
42− (x :: *)
43− (y :: *)
44− . r (a :: f x y) =
45− ()
46− #-}
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.hsdeleted−8
@@ -1,8 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−-- TODO This extension is probably too dangerous, remove it.
3−{-# LANGUAGE RecordWildCards #-}
4−-- Avoid warning produced by TH.
5−{-# OPTIONS_GHC -fno-warn-overlapping-patterns #-}
6−
7−-- | Header comment.
8−module Foo () where
data/examples/other/pragma-comments.hsdeleted−11
@@ -1,11 +0,0 @@
1−-- | Header comment.
2−
3−{-# LANGUAGE OverloadedStrings #-}
4−
5−-- Avoid warning produced by TH.
6−{-# OPTIONS_GHC -fno-warn-overlapping-patterns #-}
7−
8−-- TODO This extension is probably too dangerous, remove it.
9−{-# LANGUAGE RecordWildCards #-}
10−
11−module Foo () 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
data/examples/other/pragma-sorting-out.hsdeleted−11
@@ -1,11 +0,0 @@
1−{-# LANGUAGE NondecreasingIndentation #-}
2−{-# LANGUAGE ScopedTypeVariables #-}
3−{-# LANGUAGE TypeFamilies #-}
4−-- This gap is necessary for stylish Haskell not to re-arrange
5−-- NoMonoLocalBinds before TypeFamilies
6−{-# LANGUAGE NoMonoLocalBinds #-}
7−
8−module Foo
9− ( bar,
10− )
11−where
data/examples/other/pragma-sorting.hsdeleted−10
@@ -1,10 +0,0 @@
1−{-# LANGUAGE ScopedTypeVariables #-}
2−{-# LANGUAGE TypeFamilies #-}
3−{-# LANGUAGE NondecreasingIndentation #-}
4−-- This gap is necessary for stylish Haskell not to re-arrange
5−-- NoMonoLocalBinds before TypeFamilies
6−{-# LANGUAGE NoMonoLocalBinds #-}
7−
8−module Foo (
9− bar
10− ) where
default.nix+44−108
@@ -1,9 +1,7 @@
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
4−}:
5
2
6let
3let
4+ ormoluCompiler = "ghc865";
7 source = pkgs.lib.sourceByRegex ./. [
5 source = pkgs.lib.sourceByRegex ./. [
8 "^.*\.md$"
6 "^.*\.md$"
9 "^app.*$"
7 "^app.*$"
@@ -16,71 +14,51 @@ let
16 overrides = ormoluOverlay;
14 overrides = ormoluOverlay;
17 };
15 };
18 ormoluOverlay = self: super: {
16 ormoluOverlay = self: super: {
19− "ormolu" = super.callCabal2nixWithOptions "ormolu" source "-fdev" { };
17+ "ormolu" = super.callCabal2nix "ormolu" source { };
20 };
18 };
21 ormolize = import ./nix/ormolize {
19 ormolize = import ./nix/ormolize {
22 inherit pkgs;
20 inherit pkgs;
23 inherit haskellPackages;
21 inherit haskellPackages;
24 };
22 };
25− expectedFailures = [
23+ # NOTE We have to exclude some directories for some packages because
26− "Agda"
24+ # Ormolu needs files to be parsable by Haddock which is not always the
25+ # case. For example some tests and examples do not parse.
26+ excludedHackageDirs = {
27− "aws"
27+ "aws" = ["Examples"];
28− "distributed-process"
28+ "distributed-process" = ["benchmarks"];
29− "esqueleto"
29+ "esqueleto" = ["test"];
30− "fay"
30+ "fay" = ["examples"];
31− "hlint"
32− "idris"
33− "intero"
34− "leksah"
35− "pandoc"
36− "pipes"
37− "postgrest"
31+ "postgrest" = ["test"];
38− "purescript"
32+ };
39− "tensorflow"
40− ] ++ (if ormoluCompiler == "ghc8101" then [] else ["lens"]);
41 ormolizedPackages = doCheck:
33 ormolizedPackages = doCheck:
42 pkgs.lib.mapAttrs (name: p: ormolize {
34 pkgs.lib.mapAttrs (name: p: ormolize {
43 package = p;
35 package = p;
44 inherit doCheck;
36 inherit doCheck;
45− expectedFailures =
37+ excludedDirs =
46− if pkgs.lib.lists.any (x: x == name) expectedFailures
38+ if builtins.hasAttr name excludedHackageDirs
47− then ./expected-failures + "/${name}.txt"
39+ then excludedHackageDirs.${name}
48− else null;
40+ else [];
49 }) haskellPackages;
41 }) haskellPackages;
50in {
42in {
51 ormolu = haskellPackages.ormolu;
43 ormolu = haskellPackages.ormolu;
52− # We put the derivations in another attribute set to avoid building them
53− # when nix-build is run.
54− dev = {
55− ormoluShell =
56− haskellPackages.shellFor {
44+ ormoluShell = haskellPackages.shellFor {
57− packages = ps: [
45+ packages = ps: [
58− ps.ormolu
46+ ps.ormolu
59− ];
47+ ];
60− buildInputs = [
48+ buildInputs = [
61− haskellPackages.cabal-install
49+ haskellPackages.cabal-install
62− haskellPackages.ghcid
50+ haskellPackages.ghcid
63− ];
64− };
65− withOrmolu = haskellPackages.shellFor {
66− packages = ps: [];
67− buildInputs = [
68− haskellPackages.cabal-install
69− haskellPackages.ormolu
70− ];
71− };
51+ ];
72 };
52 };
73 inherit ormoluOverlay ormoluCompiler;
53 inherit ormoluOverlay ormoluCompiler;
74 hackage = ormolizedPackages false;
54 hackage = ormolizedPackages false;
75 hackageTests = with pkgs.lib; pkgs.recurseIntoAttrs (
55 hackageTests = with pkgs.lib; pkgs.recurseIntoAttrs (
76 let ps = [
56 let ps = [
77− "Agda"
78 "QuickCheck"
57 "QuickCheck"
79 "ShellCheck"
58 "ShellCheck"
80 "aeson"
59 "aeson"
81 "attoparsec"
60 "attoparsec"
82 "aws"
61 "aws"
83− "brick"
84 "capability"
62 "capability"
85 "cassava"
63 "cassava"
86 "conduit"
64 "conduit"
@@ -92,78 +70,36 @@ in {
92 "hakyll"
70 "hakyll"
93 "haxl"
71 "haxl"
94 "hedgehog"
72 "hedgehog"
95− "hledger"
96 "hlint"
73 "hlint"
97− "http-client"
98− "idris"
99− "intero"
100− "leksah"
101− "lens"
102 "megaparsec"
74 "megaparsec"
103− "optics"
104 "ormolu"
75 "ormolu"
105− "pandoc"
106− "parsec3"
107− "pipes"
108 "postgrest"
76 "postgrest"
109− "purescript"
110 "servant"
77 "servant"
111 "servant-server"
78 "servant-server"
112− "stack"
113 "tensorflow"
79 "tensorflow"
114 "text_1_2_4_0"
80 "text_1_2_4_0"
115 "tls"
81 "tls"
116 "yesod-core"
82 "yesod-core"
83+
84+ # Comment idempotence issue
85+
86+ # "Agda"
87+ # "brick"
88+ # "hledger"
89+ # "http-client"
90+ # "idris"
91+ # "intero"
92+ # "leksah"
93+ # "pandoc"
94+ # "pipes"
95+ # "stack"
96+
97+ # Missing language extension
98+
99+ # "lens" #fixed in master
100+ # "purescript"
101+
117 ];
102 ];
118 in listToAttrs (map (p: nameValuePair p (ormolizedPackages true).${p}) ps)
103 in listToAttrs (map (p: nameValuePair p (ormolizedPackages true).${p}) ps)
119 );
104 );
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}
105}
expected-failures/Agda.txtdeleted−11
@@ -1,11 +0,0 @@
1−Formatting is not idempotent:
2− dist/build/Agda/Syntax/Parser/Lexer.hs<rendered>:1602:17
3− before: " = (check_ac"
4− after: " =\n "
5−Please, consider reporting the bug.
6−
7−Formatting is not idempotent:
8− src/full/Agda/Syntax/Translation/InternalToAbstract.hs<rendered>:769:4
9− before: " nes\n\n "
10− after: " nes\n\n -- Andreas"
11−Please, consider reporting the bug.
expected-failures/aws.txtdeleted−9
@@ -1,9 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− Examples/PutBucketNearLine.hs:5:1-6
3− parse error on input `import'
4−
5−The GHC parser (in Haddock mode) failed:
6− Examples/Sqs.hs:(88,3)-(90,4)
7− parse error on input `{- | Let's make sure the queue was actually deleted and that the same number of queues exist at when
8− | the program ends as when it started.
9− -}'
expected-failures/distributed-process.txtdeleted−7
@@ -1,7 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− benchmarks/Channels.hs:2:1-6
3− parse error on input `import'
4−
5−The GHC parser (in Haddock mode) failed:
6− benchmarks/Spawns.hs:5:1-6
7− parse error on input `import'
expected-failures/esqueleto.txtdeleted−7
@@ -1,7 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− src/Database/Esqueleto/Internal/Internal.hs:379:1
3− lexical error in string/character literal at character 's'
4−
5−The GHC parser (in Haddock mode) failed:
6− test/PostgreSQL/Test.hs:562:9-41
7− parse error on input `-- | Check the result is not null'
expected-failures/fay.txtdeleted−18
@@ -1,18 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− examples/Separated.hs:12:1-6
3− parse error on input `module'
4−
5−The GHC parser (in Haddock mode) failed:
6− examples/calc.hs:(4,1)-(6,2)
7− parse error on input `-- $ fay -p --html-wrapper --html-js-lib jquery.min.js examples/calc.hs
8−-- You also need to download jquery.min.js.
9−--'
10−
11−The GHC parser (in Haddock mode) failed:
12− examples/canvaswater.hs:(6,1)-(7,17)
13− parse error on input `-- | A demonstration of Fay using the canvas element to display a
14−-- simple effect.'
15−
16−The GHC parser (in Haddock mode) failed:
17− examples/data.hs:9:1-6
18− parse error on input `module'
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.txtdeleted−7
@@ -1,7 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− src/Idris/Parser.hs:1052:1
3− parse error on input `@'
4−
5−The GHC parser (in Haddock mode) failed:
6− src/Idris/Parser/Expr.hs:75:1
7− parse error on input `@'
expected-failures/intero.txtdeleted−5
@@ -1,5 +0,0 @@
1−Formatting is not idempotent:
2− src/InteractiveUI.hs<rendered>:3748:33
3− before: "text \"Try\" <+> doWha"
4− after: "text \"Try\"\n "
5−Please, consider reporting the bug.
expected-failures/leksah.txtdeleted−5
@@ -1,5 +0,0 @@
1−Formatting is not idempotent:
2− src/IDE/Pane/Modules.hs<rendered>:1184:7
3− before: "cr\n -- show"
4− after: "cr\n in -- show"
5−Please, consider reporting the bug.
expected-failures/lens.txtdeleted−3
@@ -1,3 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− src/Control/Exception/Lens.hs:180:13-37
3− parse error on input `AllocationLimitExceeded__'
expected-failures/pandoc.txtdeleted−9
@@ -1,9 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− benchmark/weigh-pandoc.hs:14:1-6
3− parse error on input `import'
4−
5−Formatting is not idempotent:
6− src/Text/Pandoc/Readers/Vimwiki.hs<rendered>:613:19
7− before: ".softbreak <$ endlin"
8− after: ".softbreak\n <$ en"
9−Please, consider reporting the bug.
expected-failures/pipes.txtdeleted−3
@@ -1,3 +0,0 @@
1−AST of input and AST of formatted code differ.
2− at src/Pipes/Core.hs:(128,1)-(151,2)
3−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.txtdeleted−18
@@ -1,18 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− src/Language/PureScript/AST/Declarations.hs:479:1-17
3− Invalid type signature: pattern ValueDecl :: ...
4−Perhaps you meant to use PatternSynonyms?
5−
6−The GHC parser (in Haddock mode) failed:
7− src/Language/PureScript/AST/SourcePos.hs:99:1-22
8− Invalid type signature: pattern NullSourceSpan :: ...
9−Perhaps you meant to use PatternSynonyms?
10−
11−The GHC parser (in Haddock mode) failed:
12− src/Language/PureScript/Constants.hs:42:1-15
13− Invalid type signature: pattern Discard :: ...
14−Perhaps you meant to use PatternSynonyms?
15−
16−The GHC parser (in Haddock mode) failed:
17− src/Language/PureScript/Crash.hs:16:1-6
18− parse error on input `import'
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+3−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 -p "(import ./default.nix {}).ormolu" -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,5 @@ 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")
13−ormolu -m inplace $(find src -type f \( -name "*.hs" -o -name "*.hs-boot" \))
10+ormolu --mode inplace $(find src -type f \( -name "*.hs" -o -name "*.hs-boot" \))
14−ormolu -m inplace $(find tests -type f -name "*.hs")
11+ormolu --mode 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 = "3f4144c30a6351dd79b177328ec4dea03e2ce45f";
4− sha256 = "1gzfrpjnr1bz9zljsyg3a4zrhk8r927sz761mrgcg56dwinkhpjk";
3+ sha256 = "1qg5n60n3fr6cypihnrjw451fadps5pysj5p0vvfb320mpfvlbjb";
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+13−29
@@ -2,48 +2,32 @@
2, haskellPackages
2, haskellPackages
3}:
3}:
4{ package
4{ package
5−, expectedFailures ? null
6, doCheck ? false
5, doCheck ? false
6+, excludedDirs ? []
7}:
7}:
8 pkgs.stdenv.mkDerivation rec {
8 pkgs.stdenv.mkDerivation rec {
9 name = package.name + "-ormolized";
9 name = package.name + "-ormolized";
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
16 ];
17 ];
17 LANG = "en_US.UTF-8";
18 LANG = "en_US.UTF-8";
19+ excludedDirsRendered =
20+ if excludedDirs == []
21+ then ""
22+ else pkgs.lib.concatMapStringsSep " " (x: "-not -path './" + x + "/*'") excludedDirs;
18 buildPhase = ''
23 buildPhase = ''
19− hs_files=$(find . -name '*.hs')
24+ find . -name '*.hs' ${excludedDirsRendered} -exec bash ${./ormolize.sh} {} \; 2> log.txt
20− for hs_file in $hs_files; do
25+ cat log.txt
21−
22− # drop includes
23− sed -i '/^#include/d' "$hs_file"
24−
25− # deal with CPP
26− cpphs "$hs_file" --noline -DARCH_X86 > "''${hs_file}-nocpp" 2> /dev/null
27−
28− # annoyingly, cpphs cannot modify files in place
29− mv "''${hs_file}-nocpp" "$hs_file"
30−
31− # preserve the original
32− cp "$hs_file" "''${hs_file}-original"
33− done
34−
35− (ormolu --check-idempotence --mode inplace $hs_files || true) 2> log.txt
36 '';
26 '';
37 inherit doCheck;
27 inherit doCheck;
38− checkPhase =
28+ checkPhase = ''
39− if expectedFailures == null
40− then ''
41− echo "No failures expected"
42− if [[ -s log.txt ]]; then exit 1; fi
29+ if [[ -s log.txt ]]; then exit 1; fi
43− ''
44− else ''
45− diff --ignore-blank-lines --color=always ${expectedFailures} log.txt
46− '';
30+ '';
47 installPhase = ''
31 installPhase = ''
48 mkdir "$out"
32 mkdir "$out"
49 find . -name '*.hs-original' -exec cp --parents {} $out \;
33 find . -name '*.hs-original' -exec cp --parents {} $out \;
nix/ormolize/ormolize.shnew file+17
@@ -0,0 +1,17 @@
1+set -euo pipefail
2+
3+# drop includes
4+sed -i '/^#include/d' "$1"
5+
6+# deal with CPP in a fairly straightforward way
7+cpphs "$1" --noline > "$1-nocpp" 2> /dev/null
8+
9+# annoyingly, cpphs cannot modify files in place
10+mv "$1-nocpp" "$1"
11+
12+# preserve the original
13+cp "$1" "$1-original"
14+
15+# run ormolu
16+ormolu --tolerate-cpp --check-idempotency --mode inplace "$1" ||
17+ ormolu --tolerate-cpp --unsafe --mode inplace "$1"
ormolu.cabal+155−174
@@ -1,184 +1,165 @@
1+name: ormolu
2+version: 0.0.1.0
1−cabal-version: 1.18
3+cabal-version: 1.18
2−name: ormolu
4+tested-with: GHC==8.6.5
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 == 8.6.5
72+ , ghc-boot-th == 8.6.5
73+ , ghc-paths >= 0.1 && < 0.2
74+ , mtl >= 2.0 && < 3.0
75+ , syb >= 0.7 && < 0.8
76+ , text >= 0.2 && < 1.3
68− exposed-modules:
77+ exposed-modules: Ormolu
69− Ormolu
70− Ormolu.Config
78+ , Ormolu.Config
71− Ormolu.Diff
79+ , Ormolu.Diff
72− Ormolu.Exception
80+ , Ormolu.Exception
73− Ormolu.Imports
81+ , Ormolu.Imports
74− Ormolu.Parser
82+ , Ormolu.Parser
75− Ormolu.Parser.Anns
83+ , Ormolu.Parser.Anns
76− Ormolu.Parser.CommentStream
84+ , Ormolu.Parser.CommentStream
77− Ormolu.Parser.Pragma
85+ , Ormolu.Parser.Pragma
78− Ormolu.Parser.Result
86+ , Ormolu.Parser.Result
79− Ormolu.Parser.Shebang
80− Ormolu.Printer
87+ , Ormolu.Printer
81− Ormolu.Printer.Combinators
88+ , Ormolu.Printer.Combinators
82− Ormolu.Printer.Comments
89+ , Ormolu.Printer.Comments
83− Ormolu.Printer.Internal
90+ , Ormolu.Printer.Internal
84− Ormolu.Printer.Meat.Common
91+ , Ormolu.Printer.Meat.Common
85− Ormolu.Printer.Meat.Declaration
92+ , Ormolu.Printer.Meat.Declaration
86− Ormolu.Printer.Meat.Declaration.Annotation
93+ , Ormolu.Printer.Meat.Declaration.Annotation
87− Ormolu.Printer.Meat.Declaration.Class
94+ , Ormolu.Printer.Meat.Declaration.Class
88− Ormolu.Printer.Meat.Declaration.Data
95+ , Ormolu.Printer.Meat.Declaration.Data
89− Ormolu.Printer.Meat.Declaration.Default
96+ , Ormolu.Printer.Meat.Declaration.Default
90− Ormolu.Printer.Meat.Declaration.Foreign
97+ , Ormolu.Printer.Meat.Declaration.Foreign
91− Ormolu.Printer.Meat.Declaration.Instance
98+ , Ormolu.Printer.Meat.Declaration.Instance
92− Ormolu.Printer.Meat.Declaration.RoleAnnotation
99+ , Ormolu.Printer.Meat.Declaration.RoleAnnotation
93− Ormolu.Printer.Meat.Declaration.Rule
100+ , Ormolu.Printer.Meat.Declaration.Rule
94− Ormolu.Printer.Meat.Declaration.Signature
101+ , Ormolu.Printer.Meat.Declaration.Signature
95− Ormolu.Printer.Meat.Declaration.Splice
102+ , Ormolu.Printer.Meat.Declaration.Splice
96− Ormolu.Printer.Meat.Declaration.Type
103+ , Ormolu.Printer.Meat.Declaration.Type
97− Ormolu.Printer.Meat.Declaration.TypeFamily
104+ , Ormolu.Printer.Meat.Declaration.TypeFamily
98− Ormolu.Printer.Meat.Declaration.Value
105+ , Ormolu.Printer.Meat.Declaration.Value
99− Ormolu.Printer.Meat.Declaration.Warning
106+ , Ormolu.Printer.Meat.Declaration.Warning
100− Ormolu.Printer.Meat.ImportExport
107+ , Ormolu.Printer.Meat.ImportExport
101− Ormolu.Printer.Meat.Module
108+ , Ormolu.Printer.Meat.Module
102− Ormolu.Printer.Meat.Pragma
109+ , Ormolu.Printer.Meat.Pragma
103− Ormolu.Printer.Meat.Type
110+ , Ormolu.Printer.Meat.Type
104− Ormolu.Printer.Operators
111+ , Ormolu.Printer.Operators
105− Ormolu.Printer.SpanStream
112+ , Ormolu.Printer.SpanStream
106− Ormolu.Processing.Common
107− Ormolu.Processing.Cpp
108− Ormolu.Processing.Postprocess
109− Ormolu.Processing.Preprocess
110− Ormolu.Utils
113+ , Ormolu.Utils
111−
112− hs-source-dirs: src
113− other-modules:
114− GHC
115− 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)
114+ if flag(dev)
130− ghc-options:
115+ ghc-options: -Wall -Werror -Wcompat
131− -Wall -Werror -Wcompat -Wincomplete-record-updates
116+ -Wincomplete-record-updates
117+ -Wincomplete-uni-patterns
132− -Wincomplete-uni-patterns -Wnoncanonical-monad-instances
118+ -Wnoncanonical-monad-instances
133− -Wno-missing-home-modules
119+ -Wnoncanonical-monadfail-instances
134−
135− else
120+ else
136− ghc-options: -O2 -Wall
121+ 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
122+ 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
123
160test-suite tests
124test-suite tests
161− type: exitcode-stdio-1.0
162− main-is: Spec.hs
125+ main-is: Spec.hs
163− build-tools: hspec-discover >=2.0 && <3.0
164− hs-source-dirs: tests
126+ hs-source-dirs: tests
127+ type: exitcode-stdio-1.0
128+ build-depends: base >= 4.12 && < 5.0
129+ , containers >= 0.5 && < 0.7
130+ , filepath >= 1.2 && < 1.5
131+ , hspec >= 2.0 && < 3.0
132+ , ormolu
133+ , path >= 0.6 && < 0.7
134+ , path-io >= 1.4.2 && < 2.0
135+ , text >= 0.2 && < 1.3
136+ build-tools: hspec-discover >= 2.0 && < 3.0
165− other-modules:
137+ other-modules:
166− Ormolu.Parser.PragmaSpec
138+ Ormolu.Parser.PragmaSpec
167− Ormolu.PrinterSpec
139+ , Ormolu.PrinterSpec
168
140
141+ if flag(dev)
142+ ghc-options: -Wall -Werror
143+ else
144+ ghc-options: -O2 -Wall
169− default-language: Haskell2010
145+ 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
146
147+executable ormolu
148+ main-is: Main.hs
149+ hs-source-dirs: app
150+ build-depends: base >= 4.12 && < 5.0
151+ , ghc == 8.6.5
152+ , gitrev >= 1.3 && < 1.4
153+ , optparse-applicative >= 0.14 && < 0.15
154+ , ormolu
155+ , text >= 0.2 && < 1.3
156+ other-modules: Paths_ormolu
180− if flag(dev)
157+ if flag(dev)
181− ghc-options: -Wall -Werror
158+ ghc-options: -Wall -Werror -Wcompat
182−
159+ -Wincomplete-record-updates
160+ -Wincomplete-uni-patterns
161+ -Wnoncanonical-monad-instances
162+ -Wnoncanonical-monadfail-instances
183− else
163+ else
184− ghc-options: -O2 -Wall
164+ ghc-options: -O2 -Wall
165+ 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.hsdeleted−12
@@ -1,12 +0,0 @@
1−module GHC
2− ( module X,
3− )
4−where
5−
6−import ApiAnnotation as X
7−import BasicTypes as X
8−import GHC.Hs as X
9−import GHC.Hs.Instances as X ()
10−import Module as X
11−import RdrName as X
12−import SrcLoc as X
src/GHC/DynFlags.hsdeleted−49
@@ -1,49 +0,0 @@
1−{-# OPTIONS_GHC -Wno-missing-fields #-}
2−
3−-- Modified from ghc-lib-api-ext.
4−
5−module GHC.DynFlags
6− ( baseDynFlags,
7− )
8−where
9−
10−import Config
11−import DynFlags
12−import Fingerprint
13−import GHC.Platform
14−import ToolSettings
15−
16−fakeSettings :: Settings
17−fakeSettings =
18− Settings
19− { sGhcNameVersion =
20− GhcNameVersion
21− { ghcNameVersion_programName = "ghc",
22− ghcNameVersion_projectVersion = cProjectVersion
23− },
24− sFileSettings = FileSettings {},
25− sTargetPlatform =
26− Platform
27− { platformWordSize = PW8,
28− platformMini =
29− PlatformMini
30− { platformMini_arch = ArchUnknown,
31− platformMini_os = OSUnknown
32− },
33− platformUnregisterised = True
34− },
35− sPlatformMisc = PlatformMisc {},
36− sPlatformConstants =
37− PlatformConstants {pc_DYNAMIC_BY_DEFAULT = False, pc_WORD_SIZE = 8},
38− sToolSettings =
39− ToolSettings
40− { toolSettings_opt_P_fingerprint = fingerprint0,
41− toolSettings_pgm_F = ""
42− }
43− }
44−
45−fakeLlvmConfig :: LlvmConfig
46−fakeLlvmConfig = LlvmConfig [] []
47−
48−baseDynFlags :: DynFlags
49−baseDynFlags = defaultDynFlags fakeSettings fakeLlvmConfig
src/Ormolu.hs+19−19
@@ -1,4 +1,5 @@
1{-# LANGUAGE BangPatterns #-}
1{-# LANGUAGE BangPatterns #-}
2+{-# LANGUAGE RecordWildCards #-}
2
3
3-- | A formatter for Haskell source code.
4-- | A formatter for Haskell source code.
4module Ormolu
5module Ormolu
@@ -6,7 +7,6 @@ module Ormolu
6 ormoluFile,
7 ormoluFile,
7 ormoluStdin,
8 ormoluStdin,
8 Config (..),
9 Config (..),
9− RegionIndices (..),
10 defaultConfig,
10 defaultConfig,
11 DynOption (..),
11 DynOption (..),
12 OrmoluException (..),
12 OrmoluException (..),
@@ -29,6 +29,7 @@ import Ormolu.Parser.Result
29import Ormolu.Printer
29import Ormolu.Printer
30import Ormolu.Utils (showOutputable)
30import Ormolu.Utils (showOutputable)
31import qualified SrcLoc as GHC
31import qualified SrcLoc as GHC
32+import System.IO (hGetContents, stdin)
32
33
33-- | Format a 'String', return formatted version as 'Text'.
34-- | Format a 'String', return formatted version as 'Text'.
34--
35--
@@ -43,27 +44,26 @@ import qualified SrcLoc as GHC
43ormolu ::
44ormolu ::
44 MonadIO m =>
45 MonadIO m =>
45 -- | Ormolu configuration
46 -- | Ormolu configuration
46− Config RegionIndices ->
47+ Config ->
47 -- | Location of source file
48 -- | Location of source file
48 FilePath ->
49 FilePath ->
49 -- | Input to format
50 -- | Input to format
50 String ->
51 String ->
51 m Text
52 m Text
52−ormolu cfgWithIndices path str = do
53+ormolu cfg path str = do
53− let totalLines = length (lines str)
54− cfg = regionIndicesToDeltas totalLines <$> cfgWithIndices
55− (warnings, result0) <-
54+ (ws, result0) <-
56 parseModule' cfg OrmoluParsingFailed path str
55 parseModule' cfg OrmoluParsingFailed path str
57 when (cfgDebug cfg) $ do
56 when (cfgDebug cfg) $ do
58 traceM "warnings:\n"
57 traceM "warnings:\n"
59− traceM (concatMap showWarn warnings)
58+ traceM (concatMap showWarn ws)
60 traceM (prettyPrintParseResult result0)
59 traceM (prettyPrintParseResult result0)
61− -- We're forcing 'txt' here because otherwise errors (such as messages
60+ -- NOTE We're forcing 'txt' here because otherwise errors (such as
62− -- about not-yet-supported functionality) will be thrown later when we try
61+ -- messages about not-yet-supported functionality) will be thrown later
63− -- to parse the rendered code back, inside of GHC monad wrapper which will
62+ -- when we try to parse the rendered code back, inside of GHC monad
64− -- lead to error messages presenting the exceptions as GHC bugs.
63+ -- wrapper which will lead to error messages presenting the exceptions as
64+ -- GHC bugs.
65 let !txt = printModule result0
65 let !txt = printModule result0
66− when (not (cfgUnsafe cfg) || cfgCheckIdempotence cfg) $ do
66+ when (not (cfgUnsafe cfg) || cfgCheckIdempotency cfg) $ do
67 let pathRendered = path ++ "<rendered>"
67 let pathRendered = path ++ "<rendered>"
68 -- Parse the result of pretty-printing again and make sure that AST
68 -- Parse the result of pretty-printing again and make sure that AST
69 -- is the same as AST of original snippet module span positions.
69 -- is the same as AST of original snippet module span positions.
@@ -79,7 +79,7 @@ ormolu cfgWithIndices path str = do
79 Different ss -> liftIO $ throwIO (OrmoluASTDiffers path ss)
79 Different ss -> liftIO $ throwIO (OrmoluASTDiffers path ss)
80 -- Try re-formatting the formatted result to check if we get exactly
80 -- Try re-formatting the formatted result to check if we get exactly
81 -- the same output.
81 -- the same output.
82− when (cfgCheckIdempotence cfg) $
82+ when (cfgCheckIdempotency cfg) $
83 let txt2 = printModule result1
83 let txt2 = printModule result1
84 in case diffText txt txt2 pathRendered of
84 in case diffText txt txt2 pathRendered of
85 Nothing -> return ()
85 Nothing -> return ()
@@ -96,7 +96,7 @@ ormolu cfgWithIndices path str = do
96ormoluFile ::
96ormoluFile ::
97 MonadIO m =>
97 MonadIO m =>
98 -- | Ormolu configuration
98 -- | Ormolu configuration
99− Config RegionIndices ->
99+ Config ->
100 -- | Location of source file
100 -- | Location of source file
101 FilePath ->
101 FilePath ->
102 -- | Resulting rendition
102 -- | Resulting rendition
@@ -111,11 +111,11 @@ ormoluFile cfg path =
111ormoluStdin ::
111ormoluStdin ::
112 MonadIO m =>
112 MonadIO m =>
113 -- | Ormolu configuration
113 -- | Ormolu configuration
114− Config RegionIndices ->
114+ Config ->
115 -- | Resulting rendition
115 -- | Resulting rendition
116 m Text
116 m Text
117ormoluStdin cfg =
117ormoluStdin cfg =
118− liftIO getContents >>= ormolu cfg "<stdin>"
118+ liftIO (hGetContents stdin) >>= ormolu cfg "<stdin>"
119
119
120----------------------------------------------------------------------------
120----------------------------------------------------------------------------
121-- Helpers
121-- Helpers
@@ -124,7 +124,7 @@ ormoluStdin cfg =
124parseModule' ::
124parseModule' ::
125 MonadIO m =>
125 MonadIO m =>
126 -- | Ormolu configuration
126 -- | Ormolu configuration
127− Config RegionDeltas ->
127+ Config ->
128 -- | How to obtain 'OrmoluException' to throw when parsing fails
128 -- | How to obtain 'OrmoluException' to throw when parsing fails
129 (GHC.SrcSpan -> String -> OrmoluException) ->
129 (GHC.SrcSpan -> String -> OrmoluException) ->
130 -- | File name to use in errors
130 -- | File name to use in errors
@@ -133,10 +133,10 @@ parseModule' ::
133 String ->
133 String ->
134 m ([GHC.Warn], ParseResult)
134 m ([GHC.Warn], ParseResult)
135parseModule' cfg mkException path str = do
135parseModule' cfg mkException path str = do
136− (warnings, r) <- parseModule cfg path str
136+ (ws, r) <- parseModule cfg path str
137 case r of
137 case r of
138 Left (spn, err) -> liftIO $ throwIO (mkException spn err)
138 Left (spn, err) -> liftIO $ throwIO (mkException spn err)
139− Right x -> return (warnings, x)
139+ Right x -> return (ws, x)
140
140
141-- | Pretty-print a 'GHC.Warn'.
141-- | Pretty-print a 'GHC.Warn'.
142showWarn :: GHC.Warn -> String
142showWarn :: GHC.Warn -> String
src/Ormolu/Config.hs+29−65
@@ -1,13 +1,11 @@
1−{-# LANGUAGE DeriveFunctor #-}
1+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2+{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE RecordWildCards #-}
3{-# LANGUAGE RecordWildCards #-}
3
4
4-- | Configuration options used by the tool.
5-- | Configuration options used by the tool.
5module Ormolu.Config
6module Ormolu.Config
6 ( Config (..),
7 ( Config (..),
7− RegionIndices (..),
8− RegionDeltas (..),
9 defaultConfig,
8 defaultConfig,
10− regionIndicesToDeltas,
11 DynOption (..),
9 DynOption (..),
12 dynOptionToLocatedStr,
10 dynOptionToLocatedStr,
13 )
11 )
@@ -16,72 +14,38 @@ where
16import qualified SrcLoc as GHC
14import qualified SrcLoc as GHC
17
15
18-- | Ormolu configuration.
16-- | Ormolu configuration.
19−data Config region = Config
17+data Config
18+ = Config
20− { -- | Dynamic options to pass to GHC parser
19+ { -- | Dynamic options to pass to GHC parser
21− cfgDynOptions :: ![DynOption],
20+ cfgDynOptions :: ![DynOption],
22− -- | Do formatting faster but without automatic detection of defects
21+ -- | Do formatting faster but without automatic detection of defects
23− cfgUnsafe :: !Bool,
22+ cfgUnsafe :: !Bool,
24− -- | Output information useful for debugging
23+ -- | Output information useful for debugging
25− cfgDebug :: !Bool,
24+ cfgDebug :: !Bool,
25+ -- | Do not fail if CPP pragma is present (still doesn't handle CPP but
26+ -- useful for formatting of files that enable the extension without
27+ -- actually containing CPP macros)
28+ cfgTolerateCpp :: !Bool,
26− -- | Checks if re-formatting the result is idempotent
29+ -- | Checks if re-formatting the result is idempotent.
27− cfgCheckIdempotence :: !Bool,
30+ 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− }
31+ }
40 deriving (Eq, Show)
32 deriving (Eq, Show)
41
33
42−-- | Region selection as the length of the literal prefix and the literal
34+-- | Default 'Config'.
43−-- suffix.
35+defaultConfig :: Config
44−data RegionDeltas = RegionDeltas
36+defaultConfig = Config
45− { -- | Prefix length in number of lines
37+ { cfgDynOptions = [],
46− regionPrefixLength :: !Int,
38+ cfgUnsafe = False,
47− -- | Suffix length in number of lines
39+ cfgDebug = False,
48− regionSuffixLength :: !Int
40+ cfgTolerateCpp = False,
41+ cfgCheckIdempotency = False
49 }
42 }
50− deriving (Eq, Show)
51−
52−-- | Default @'Config' 'RegionIndices'@.
53−defaultConfig :: Config RegionIndices
54−defaultConfig =
55− Config
56− { cfgDynOptions = [],
57− cfgUnsafe = False,
58− cfgDebug = False,
59− cfgCheckIdempotence = False,
60− cfgRegion =
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− }
80
43
81-- | A wrapper for dynamic options.
44-- | A wrapper for dynamic options.
82−newtype DynOption = DynOption
45+newtype DynOption
46+ = DynOption
83− { unDynOption :: String
47+ { unDynOption :: String
84− }
48+ }
85 deriving (Eq, Ord, Show)
49 deriving (Eq, Ord, Show)
86
50
87-- | Convert 'DynOption' to @'GHC.Located' 'String'@.
51-- | Convert 'DynOption' to @'GHC.Located' 'String'@.
src/Ormolu/Diff.hs+18−25
@@ -1,4 +1,6 @@
1+{-# LANGUAGE DeriveDataTypeable #-}
1{-# LANGUAGE RankNTypes #-}
2{-# LANGUAGE RankNTypes #-}
3+{-# LANGUAGE RecordWildCards #-}
2
4
3-- | Diffing GHC ASTs modulo span positions.
5-- | Diffing GHC ASTs modulo span positions.
4module Ormolu.Diff
6module Ormolu.Diff
@@ -8,16 +10,17 @@ module Ormolu.Diff
8 )
10 )
9where
11where
10
12
13+import BasicTypes (SourceText)
11import Data.ByteString (ByteString)
14import Data.ByteString (ByteString)
12import Data.Generics
15import Data.Generics
13import Data.Text (Text)
16import Data.Text (Text)
14import qualified Data.Text as T
17import qualified Data.Text as T
15import qualified FastString as GHC
18import qualified FastString as GHC
16import GHC
19import GHC
17−import Ormolu.Imports (normalizeImports)
20+import Ormolu.Imports (sortImports)
18−import Ormolu.Parser.CommentStream
19import Ormolu.Parser.Result
21import Ormolu.Parser.Result
20import Ormolu.Utils
22import Ormolu.Utils
23+import qualified SrcLoc as GHC
21
24
22-- | Result of comparing two 'ParseResult's.
25-- | Result of comparing two 'ParseResult's.
23data Diff
26data Diff
@@ -39,16 +42,14 @@ diffParseResult :: ParseResult -> ParseResult -> Diff
39diffParseResult
42diffParseResult
40 ParseResult
43 ParseResult
41 { prCommentStream = cstream0,
44 { prCommentStream = cstream0,
42− prParsedSource = hs0
45+ prParsedSource = ps0
43 }
46 }
44 ParseResult
47 ParseResult
45 { prCommentStream = cstream1,
48 { prCommentStream = cstream1,
46− prParsedSource = hs1
49+ prParsedSource = ps1
47 } =
50 } =
48 matchIgnoringSrcSpans cstream0 cstream1
51 matchIgnoringSrcSpans cstream0 cstream1
49− <> matchIgnoringSrcSpans
52+ <> matchIgnoringSrcSpans ps0 ps1
50− hs0 {hsmodImports = normalizeImports (hsmodImports hs0)}
51− hs1 {hsmodImports = normalizeImports (hsmodImports hs1)}
52
53
53-- | Compare two values for equality disregarding differences in 'SrcSpan's
54-- | Compare two values for equality disregarding differences in 'SrcSpan's
54-- and the ordering of import lists.
55-- and the ordering of import lists.
@@ -57,7 +58,7 @@ matchIgnoringSrcSpans = genericQuery
57 where
58 where
58 genericQuery :: GenericQ (GenericQ Diff)
59 genericQuery :: GenericQ (GenericQ Diff)
59 genericQuery x y
60 genericQuery x y
60− -- 'ByteString' implements 'Data' instance manually and does not
61+ -- NOTE 'ByteString' implement 'Data' instance manually and does not
61 -- implement 'toConstr', so we have to deal with it in a special way.
62 -- implement 'toConstr', so we have to deal with it in a special way.
62 | Just x' <- cast x,
63 | Just x' <- cast x,
63 Just y' <- cast y =
64 Just y' <- cast y =
@@ -70,10 +71,9 @@ matchIgnoringSrcSpans = genericQuery
70 gzipWithQ
71 gzipWithQ
71 ( genericQuery
72 ( genericQuery
72 `extQ` srcSpanEq
73 `extQ` srcSpanEq
73− `extQ` commentEq
74+ `extQ` hsModuleEq
74 `extQ` sourceTextEq
75 `extQ` sourceTextEq
75 `extQ` hsDocStringEq
76 `extQ` hsDocStringEq
76− `extQ` importDeclQualifiedStyleEq
77 `ext2Q` forLocated
77 `ext2Q` forLocated
78 )
78 )
79 x
79 x
@@ -81,23 +81,16 @@ matchIgnoringSrcSpans = genericQuery
81 | otherwise = Different []
81 | otherwise = Different []
82 srcSpanEq :: SrcSpan -> GenericQ Diff
82 srcSpanEq :: SrcSpan -> GenericQ Diff
83 srcSpanEq _ _ = Same
83 srcSpanEq _ _ = Same
84− commentEq :: Comment -> GenericQ Diff
84+ hsModuleEq :: HsModule GhcPs -> GenericQ Diff
85− commentEq (Comment _ x) d =
85+ hsModuleEq hs0 hs1' =
86− case cast d :: Maybe Comment of
86+ case cast hs1' :: Maybe (HsModule GhcPs) of
87 Nothing -> Different []
87 Nothing -> Different []
88− Just (Comment _ y) ->
88+ Just hs1 ->
89− if x == y
89+ matchIgnoringSrcSpans
90− then Same
90+ hs0 {hsmodImports = sortImports (hsmodImports hs0)}
91− else Different []
91+ hs1 {hsmodImports = sortImports (hsmodImports hs1)}
92 sourceTextEq :: SourceText -> GenericQ Diff
92 sourceTextEq :: SourceText -> GenericQ Diff
93 sourceTextEq _ _ = Same
93 sourceTextEq _ _ = Same
94− importDeclQualifiedStyleEq :: ImportDeclQualifiedStyle -> GenericQ Diff
95− importDeclQualifiedStyleEq d0 d1' =
96− case (d0, cast d1' :: Maybe ImportDeclQualifiedStyle) of
97− (x, Just x') | x == x' -> Same
98− (QualifiedPre, Just QualifiedPost) -> Same
99− (QualifiedPost, Just QualifiedPre) -> Same
100− _ -> Different []
101 hsDocStringEq :: HsDocString -> GenericQ Diff
94 hsDocStringEq :: HsDocString -> GenericQ Diff
102 hsDocStringEq str0 str1' =
95 hsDocStringEq str0 str1' =
103 case cast str1' :: Maybe HsDocString of
96 case cast str1' :: Maybe HsDocString of
@@ -115,7 +108,7 @@ matchIgnoringSrcSpans = genericQuery
115 appendSpan :: SrcSpan -> Diff -> Diff
108 appendSpan :: SrcSpan -> Diff -> Diff
116 appendSpan s (Different ss) | fresh && helpful = Different (s : ss)
109 appendSpan s (Different ss) | fresh && helpful = Different (s : ss)
117 where
110 where
118− fresh = not $ any (`isSubspanOf` s) ss
111+ fresh = not $ any (flip isSubspanOf s) ss
119 helpful = isGoodSrcSpan s
112 helpful = isGoodSrcSpan s
120 appendSpan _ d = d
113 appendSpan _ d = d
121
114
src/Ormolu/Exception.hs+19−24
@@ -8,8 +8,6 @@ module Ormolu.Exception
8where
8where
9
9
10import Control.Exception
10import Control.Exception
11−import Data.List.NonEmpty (NonEmpty (..))
12−import qualified Data.List.NonEmpty as NE
13import Data.Text (Text)
11import Data.Text (Text)
14import qualified GHC
12import qualified GHC
15import Ormolu.Utils (showOutputable)
13import Ormolu.Utils (showOutputable)
@@ -19,7 +17,9 @@ import System.IO
19
17
20-- | Ormolu exception representing all cases when Ormolu can fail.
18-- | Ormolu exception representing all cases when Ormolu can fail.
21data OrmoluException
19data OrmoluException
20+ = -- | Ormolu does not work with source files that use CPP
21+ OrmoluCppEnabled FilePath
22− = -- | Parsing of original source code failed
22+ | -- | Parsing of original source code failed
23 OrmoluParsingFailed GHC.SrcSpan String
23 OrmoluParsingFailed GHC.SrcSpan String
24 | -- | Parsing of formatted source code failed
24 | -- | Parsing of formatted source code failed
25 OrmoluOutputParsingFailed GHC.SrcSpan String
25 OrmoluOutputParsingFailed GHC.SrcSpan String
@@ -27,14 +27,17 @@ data OrmoluException
27 OrmoluASTDiffers FilePath [GHC.SrcSpan]
27 OrmoluASTDiffers FilePath [GHC.SrcSpan]
28 | -- | Formatted source code is not idempotent
28 | -- | Formatted source code is not idempotent
29 OrmoluNonIdempotentOutput GHC.RealSrcLoc Text Text
29 OrmoluNonIdempotentOutput GHC.RealSrcLoc Text Text
30− | -- | Some GHC options were not recognized
31− OrmoluUnrecognizedOpts (NonEmpty String)
32 deriving (Eq, Show)
30 deriving (Eq, Show)
33
31
34instance Exception OrmoluException where
32instance Exception OrmoluException where
35 displayException = \case
33 displayException = \case
34+ OrmoluCppEnabled path ->
35+ unlines
36+ [ "CPP is not supported:",
37+ withIndent path
38+ ]
36 OrmoluParsingFailed s e ->
39 OrmoluParsingFailed s e ->
37− showParsingErr "The GHC parser (in Haddock mode) failed:" s [e]
40+ showParsingErr "Parsing of source code failed:" s [e]
38 OrmoluOutputParsingFailed s e ->
41 OrmoluOutputParsingFailed s e ->
39 showParsingErr "Parsing of formatted code failed:" s [e]
42 showParsingErr "Parsing of formatted code failed:" s [e]
40 ++ "Please, consider reporting the bug.\n"
43 ++ "Please, consider reporting the bug.\n"
@@ -42,12 +45,10 @@ instance Exception OrmoluException where
42 unlines $
45 unlines $
43 [ "AST of input and AST of formatted code differ."
46 [ "AST of input and AST of formatted code differ."
44 ]
47 ]
45− ++ fmap
46− withIndent
47− ( case fmap (\s -> "at " ++ showOutputable s) ss of
48+ ++ ( fmap withIndent $ case fmap (\s -> "at " ++ showOutputable s) ss of
48− [] -> ["in " ++ path]
49+ [] -> ["in " ++ path]
49− xs -> xs
50+ xs -> xs
50− )
51+ )
51 ++ ["Please, consider reporting the bug."]
52 ++ ["Please, consider reporting the bug."]
52 OrmoluNonIdempotentOutput loc left right ->
53 OrmoluNonIdempotentOutput loc left right ->
53 showParsingErr
54 showParsingErr
@@ -55,11 +56,6 @@ instance Exception OrmoluException where
55 loc
56 loc
56 ["before: " ++ show left, "after: " ++ show right]
57 ["before: " ++ show left, "after: " ++ show right]
57 ++ "Please, consider reporting the bug.\n"
58 ++ "Please, consider reporting the bug.\n"
58− OrmoluUnrecognizedOpts opts ->
59− unlines
60− [ "The following GHC options were not recognized:",
61− (withIndent . unwords . NE.toList) opts
62− ]
63
59
64-- | Inside this wrapper 'OrmoluException' will be caught and displayed
60-- | Inside this wrapper 'OrmoluException' will be caught and displayed
65-- nicely using 'displayException'.
61-- nicely using 'displayException'.
@@ -74,13 +70,12 @@ withPrettyOrmoluExceptions m = m `catch` h
74 hPutStrLn stderr (displayException e)
70 hPutStrLn stderr (displayException e)
75 exitWith . ExitFailure $
71 exitWith . ExitFailure $
76 case e of
72 case e of
77− -- Error code 1 is for 'error' or 'notImplemented'
73+ -- Error code 1 is for `error` or `notImplemented`
78− -- 2 used to be for erroring out on CPP
74+ OrmoluCppEnabled _ -> 2
79− OrmoluParsingFailed {} -> 3
75+ OrmoluParsingFailed _ _ -> 3
80− OrmoluOutputParsingFailed {} -> 4
76+ OrmoluOutputParsingFailed _ _ -> 4
81− OrmoluASTDiffers {} -> 5
77+ OrmoluASTDiffers _ _ -> 5
82− OrmoluNonIdempotentOutput {} -> 6
78+ OrmoluNonIdempotentOutput _ _ _ -> 6
83− OrmoluUnrecognizedOpts {} -> 7
84
79
85----------------------------------------------------------------------------
80----------------------------------------------------------------------------
86-- Helpers
81-- Helpers
src/Ormolu/Imports.hs+51−172
@@ -1,202 +1,81 @@
1{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE RankNTypes #-}
2{-# LANGUAGE RankNTypes #-}
3−{-# LANGUAGE RecordWildCards #-}
4
3
5-- | Manipulations on import lists.
4-- | Manipulations on import lists.
6module Ormolu.Imports
5module Ormolu.Imports
7− ( normalizeImports,
6+ ( sortImports,
8 )
7 )
9where
8where
10
9
11import Data.Bifunctor
10import Data.Bifunctor
12−import Data.Char (isAlphaNum)
13import Data.Function (on)
11import Data.Function (on)
14−import Data.List (foldl', nubBy, sortBy, sortOn)
12+import Data.Generics (gcompare)
15−import Data.Map.Strict (Map)
13+import Data.List (sortBy)
16−import qualified Data.Map.Strict as M
17−import FastString (FastString)
18import GHC hiding (GhcPs, IE)
14import GHC hiding (GhcPs, IE)
19−import GHC.Hs.Extension
15+import HsExtension
20−import GHC.Hs.ImpExp (IE (..))
16+import HsImpExp (IE (..))
21−import Ormolu.Utils (notImplemented, showOutputable)
17+import Ormolu.Utils (notImplemented)
22
18
23−-- | Sort and normalize imports.
19+-- | Sort imports by module name. This also sorts explicit import lists for
20+-- each declaration.
24−normalizeImports :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]
21+sortImports :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]
25−normalizeImports =
22+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
23 where
31− g (L l ImportDecl {..}) =
24+ sortImportLists :: ImportDecl GhcPs -> ImportDecl GhcPs
32− L
25+ sortImportLists decl =
33− l
26+ decl
34− ImportDecl
35− { ideclHiding = second (fmap normalizeLies) <$> ideclHiding,
27+ { ideclHiding = second (fmap sortLies) <$> ideclHiding decl
36− ..
37− }
28+ }
38− g _ = notImplemented "XImportDecl"
39
29
40−-- | Combine two import declarations. It should be assumed that 'ImportId's
41−-- are equal.
42−combineImports ::
43− LImportDecl GhcPs ->
44− LImportDecl GhcPs ->
30+-- | Compare two @'LImportDecl' 'GhcPs'@ things.
45− LImportDecl GhcPs
31+compareIdecl :: LImportDecl GhcPs -> LImportDecl GhcPs -> Ordering
46−combineImports (L lx ImportDecl {..}) (L _ y) =
32+compareIdecl (L _ m0) (L _ m1) =
47− L
33+ case (isPrelude n0, isPrelude n1) of
48− lx
34+ (False, False) -> n0 `compare` n1
49− ImportDecl
35+ (True, False) -> GT
50− { ideclHiding = case (ideclHiding, GHC.ideclHiding y) of
36+ (False, True) -> LT
51− (Just (hiding, L l' xs), Just (_, L _ ys)) ->
37+ (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
38 where
39+ n0 = unLoc (ideclName m0)
40+ n1 = unLoc (ideclName m1)
92− isPrelude = moduleNameString moduleName == "Prelude"
41+ isPrelude = (== "Prelude") . moduleNameString
93− moduleName = unLoc ideclName
94−importId _ = notImplemented "XImportDecl"
95
42
96−-- | Normalize a collection of import\/export items.
43+-- | Sort located import or export.
97−normalizeLies :: [LIE GhcPs] -> [LIE GhcPs]
44+sortLies :: [LIE GhcPs] -> [LIE GhcPs]
98−normalizeLies = sortOn (getIewn . unLoc) . M.elems . foldl' combine M.empty
45+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
46
152−-- | A wrapper for @'IEWrappedName' 'RdrName'@ that allows us to define an
47+-- | Sort imports\/exports inside of 'IEThingWith'.
153−-- 'Ord' instance for it.
48+sortThings :: IE GhcPs -> IE GhcPs
154−newtype IEWrappedNameOrd = IEWrappedNameOrd (IEWrappedName RdrName)
49+sortThings = \case
155− deriving (Eq)
50+ IEThingWith NoExt x w xs fl ->
51+ IEThingWith NoExt x w (sortBy (compareIewn `on` unLoc) xs) fl
52+ other -> other
156
53
157−instance Ord IEWrappedNameOrd where
54+-- | Compare two located imports or exports.
158− compare (IEWrappedNameOrd x) (IEWrappedNameOrd y) = compareIewn x y
55+compareIE :: IE GhcPs -> IE GhcPs -> Ordering
56+compareIE = compareIewn `on` getIewn
159
57
160-- | Project @'IEWrappedName' 'RdrName'@ from @'IE' 'GhcPs'@.
58-- | Project @'IEWrappedName' 'RdrName'@ from @'IE' 'GhcPs'@.
161−getIewn :: IE GhcPs -> IEWrappedNameOrd
59+getIewn :: IE GhcPs -> IEWrappedName RdrName
162getIewn = \case
60getIewn = \case
163− IEVar NoExtField x -> IEWrappedNameOrd (unLoc x)
61+ IEVar NoExt x -> unLoc x
164− IEThingAbs NoExtField x -> IEWrappedNameOrd (unLoc x)
62+ IEThingAbs NoExt x -> unLoc x
165− IEThingAll NoExtField x -> IEWrappedNameOrd (unLoc x)
63+ IEThingAll NoExt x -> unLoc x
166− IEThingWith NoExtField x _ _ _ -> IEWrappedNameOrd (unLoc x)
64+ IEThingWith NoExt x _ _ _ -> unLoc x
167− IEModuleContents NoExtField _ -> notImplemented "IEModuleContents"
65+ IEModuleContents NoExt _ -> notImplemented "IEModuleContents"
168− IEGroup NoExtField _ _ -> notImplemented "IEGroup"
66+ IEGroup NoExt _ _ -> notImplemented "IEGroup"
169− IEDoc NoExtField _ -> notImplemented "IEDoc"
67+ IEDoc NoExt _ -> notImplemented "IEDoc"
170− IEDocNamed NoExtField _ -> notImplemented "IEDocNamed"
68+ IEDocNamed NoExt _ -> notImplemented "IEDocNamed"
171− XIE x -> noExtCon x
69+ XIE NoExt -> notImplemented "XIE"
172−
173−-- | Like 'compareIewn' for located wrapped names.
174−compareLIewn :: LIEWrappedName RdrName -> LIEWrappedName RdrName -> Ordering
175−compareLIewn = compareIewn `on` unLoc
176
70
177-- | Compare two @'IEWrapppedName' 'RdrName'@ things.
71-- | Compare two @'IEWrapppedName' 'RdrName'@ things.
178compareIewn :: IEWrappedName RdrName -> IEWrappedName RdrName -> Ordering
72compareIewn :: IEWrappedName RdrName -> IEWrappedName RdrName -> Ordering
179−compareIewn (IEName x) (IEName y) = unLoc x `compareRdrName` unLoc y
73+compareIewn (IEName x) (IEName y) = unLoc x `compare` unLoc y
180compareIewn (IEName _) (IEPattern _) = LT
74compareIewn (IEName _) (IEPattern _) = LT
181compareIewn (IEName _) (IEType _) = LT
75compareIewn (IEName _) (IEType _) = LT
182compareIewn (IEPattern _) (IEName _) = GT
76compareIewn (IEPattern _) (IEName _) = GT
183−compareIewn (IEPattern x) (IEPattern y) = unLoc x `compareRdrName` unLoc y
77+compareIewn (IEPattern x) (IEPattern y) = unLoc x `compare` unLoc y
184compareIewn (IEPattern _) (IEType _) = LT
78compareIewn (IEPattern _) (IEType _) = LT
185compareIewn (IEType _) (IEName _) = GT
79compareIewn (IEType _) (IEName _) = GT
186compareIewn (IEType _) (IEPattern _) = GT
80compareIewn (IEType _) (IEPattern _) = GT
187−compareIewn (IEType x) (IEType y) = unLoc x `compareRdrName` unLoc y
81+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+117−135
@@ -1,5 +1,5 @@
1−{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE RecordWildCards #-}
1{-# LANGUAGE RecordWildCards #-}
2+{-# LANGUAGE StandaloneDeriving #-}
3{-# OPTIONS_GHC -fno-warn-orphans #-}
3{-# OPTIONS_GHC -fno-warn-orphans #-}
4
4
5-- | Parser for Haskell source code.
5-- | Parser for Haskell source code.
@@ -9,39 +9,34 @@ module Ormolu.Parser
9 )
9 )
10where
10where
11
11
12−import Bag (bagToList)
13import qualified CmdLineParser as GHC
12import qualified CmdLineParser as GHC
14import Control.Exception
13import Control.Exception
14+import Control.Monad
15import Control.Monad.IO.Class
15import Control.Monad.IO.Class
16−import qualified Data.List as L
16+import Data.List ((\\), foldl', isPrefixOf)
17−import qualified Data.List.NonEmpty as NE
18−import Data.Ord (Down (Down))
17+import Data.Maybe (catMaybes)
19−import qualified Data.Text as T
18+import qualified DynFlags as GHC
20−import DynFlags as GHC
21−import ErrUtils (Severity (..), errMsgSeverity, errMsgSpan)
22import qualified FastString as GHC
19import qualified FastString as GHC
23−import GHC hiding (IE, UnicodeSyntax)
20+import GHC hiding (IE, parseModule, parser)
24−import GHC.DynFlags (baseDynFlags)
25import GHC.LanguageExtensions.Type (Extension (..))
21import GHC.LanguageExtensions.Type (Extension (..))
22+import GHC.Paths (libdir)
26import qualified HeaderInfo as GHC
23import qualified HeaderInfo as GHC
27−import qualified HscTypes as GHC
28import qualified Lexer as GHC
24import qualified Lexer as GHC
29import Ormolu.Config
25import Ormolu.Config
30import Ormolu.Exception
26import Ormolu.Exception
31import Ormolu.Parser.Anns
27import Ormolu.Parser.Anns
32import Ormolu.Parser.CommentStream
28import Ormolu.Parser.CommentStream
33import Ormolu.Parser.Result
29import Ormolu.Parser.Result
34−import Ormolu.Processing.Preprocess (preprocess)
35−import Ormolu.Utils (incSpanLine, removeIndentation)
36−import qualified Panic as GHC
30+import qualified Outputable as GHC
37import qualified Parser as GHC
31import qualified Parser as GHC
32+import qualified SrcLoc as GHC
38import qualified StringBuffer as GHC
33import qualified StringBuffer as GHC
39
34
40-- | Parse a complete module from string.
35-- | Parse a complete module from string.
41parseModule ::
36parseModule ::
42 MonadIO m =>
37 MonadIO m =>
43 -- | Ormolu configuration
38 -- | Ormolu configuration
44− Config RegionDeltas ->
39+ Config ->
45 -- | File name (only for source location annotations)
40 -- | File name (only for source location annotations)
46 FilePath ->
41 FilePath ->
47 -- | Input for parser
42 -- | Input for parser
@@ -50,79 +45,32 @@ parseModule ::
50 ( [GHC.Warn],
45 ( [GHC.Warn],
51 Either (SrcSpan, String) ParseResult
46 Either (SrcSpan, String) ParseResult
52 )
47 )
53−parseModule Config {..} path rawInput = liftIO $ do
48+parseModule Config {..} path input' = liftIO $ do
54− let (literalPrefix, indentedInput, literalSuffix, extraComments) =
49+ let (input, extraComments) = stripLinePragmas path input'
55− preprocess path rawInput cfgRegion
50+ (ws, dynFlags) <- ghcWrapper $ do
56− (input, indent) = removeIndentation indentedInput
51+ dynFlags0 <- initDynFlagsPure path input
57− -- It's important that 'setDefaultExts' is done before
52+ (dynFlags1, _, ws) <-
58− -- 'parsePragmasIntoDynFlags', because otherwise we might enable an
53+ GHC.parseDynamicFilePragma
59− -- extension that was explicitly disabled in the file.
54+ dynFlags0
60− let baseFlags =
61− GHC.setGeneralFlag'
62− GHC.Opt_Haddock
63− (setDefaultExts baseDynFlags)
64− extraOpts = dynOptionToLocatedStr <$> cfgDynOptions
55+ (dynOptionToLocatedStr <$> cfgDynOptions)
65− (warnings, dynFlags) <-
56+ return (ws, GHC.setGeneralFlag' GHC.Opt_Haddock dynFlags1)
66− parsePragmasIntoDynFlags baseFlags extraOpts path rawInput >>= \case
57+ -- NOTE It's better to throw this outside of 'ghcWrapper' because
67− Right res -> pure res
58+ -- otherwise the exception will be wrapped as a GHC panic, which we don't
68− Left err ->
59+ -- want.
69− let loc =
60+ when (GHC.xopt Cpp dynFlags && not cfgTolerateCpp) $
70− mkSrcSpan
61+ throwIO (OrmoluCppEnabled path)
71− (mkSrcLoc (GHC.mkFastString path) 1 1)
72− (mkSrcLoc (GHC.mkFastString path) 1 1)
73− in throwIO (OrmoluParsingFailed loc err)
74− let useRecordDot =
75− "record-dot-preprocessor" == pgm_F dynFlags
76− || any
77− (("RecordDotPreprocessor" ==) . moduleNameString)
78− (pluginModNames dynFlags)
79− pStateErrors = \pstate ->
80− let errs = bagToList $ GHC.getErrorMessages pstate dynFlags
81− fixupErrSpan = incSpanLine (regionPrefixLength cfgRegion)
82− in case L.sortOn (Down . SeverityOrd . errMsgSeverity) errs of
83− [] -> Nothing
84− err : _ ->
85− -- Show instance returns a short error message
86− Just (fixupErrSpan (errMsgSpan err), show err)
87− r = case runParser GHC.parseModule dynFlags path input of
62+ let r = case runParser GHC.parseModule dynFlags path input of
88− GHC.PFailed pstate ->
63+ GHC.PFailed _ ss m ->
89− case pStateErrors pstate of
64+ Left (ss, GHC.showSDoc dynFlags m)
90− Just err -> Left err
91− Nothing -> error "PFailed does not have an error"
92− GHC.POk pstate (L _ hsModule) ->
65+ GHC.POk pstate pmod ->
93− case pStateErrors pstate of
94− -- Some parse errors (pattern/arrow syntax in expr context)
95− -- do not cause a parse error, but they are replaced with "_"
96− -- by the parser and the modified AST is propagated to the
97− -- later stages; but we fail in those cases.
98− Just err -> Left err
99− Nothing ->
100− let (stackHeader, shebangs, pragmas, comments) =
101− mkCommentStream input extraComments pstate
66+ let (comments, exts) = mkCommentStream extraComments pstate
102− in Right
103− ParseResult
67+ in Right ParseResult
104− { prParsedSource = hsModule,
68+ { prParsedSource = pmod,
105− prAnns = mkAnns pstate,
69+ prAnns = mkAnns pstate,
106− prStackHeader = stackHeader,
107− prShebangs = shebangs,
108− prPragmas = pragmas,
109− prCommentStream = comments,
70+ prCommentStream = comments,
110− prUseRecordDot = useRecordDot,
71+ prExtensions = exts
111− prImportQualifiedPost =
112− GHC.xopt ImportQualifiedPost dynFlags,
113− prLiteralPrefix = T.pack literalPrefix,
114− prLiteralSuffix = T.pack literalSuffix,
115− prIndent = indent
116− }
72+ }
117− return (warnings, r)
73+ return (ws, r)
118−
119−-- | Enable all language extensions that we think should be enabled by
120−-- default for ease of use.
121−setDefaultExts :: DynFlags -> DynFlags
122−setDefaultExts flags = L.foldl' xopt_set flags autoExts
123− where
124− autoExts = allExts L.\\ manualExts
125− allExts = [minBound .. maxBound]
126
74
127-- | Extensions that are not enabled automatically and should be activated
75-- | Extensions that are not enabled automatically and should be activated
128-- by user.
76-- by user.
@@ -143,13 +91,55 @@ manualExts =
143 MonadComprehensions,
91 MonadComprehensions,
144 UnboxedSums,
92 UnboxedSums,
145 UnicodeSyntax, -- gives special meanings to operators like (→)
93 UnicodeSyntax, -- gives special meanings to operators like (→)
146− TemplateHaskellQuotes, -- enables TH subset of quasi-quotes, this
94+ TemplateHaskellQuotes -- enables TH subset of quasi-quotes, this
147 -- apparently interferes with QuasiQuotes in
95 -- apparently interferes with QuasiQuotes in
148 -- weird ways
96 -- weird ways
149− ImportQualifiedPost -- affects how Ormolu renders imports, so the
150− -- decision of enabling this style is left to the user
151 ]
97 ]
152
98
99+----------------------------------------------------------------------------
100+-- Helpers (taken from ghc-exactprint)
101+
102+-- | Requires GhcMonad constraint because there is no pure variant of
103+-- 'parseDynamicFilePragma'. Yet, in constrast to 'initDynFlags', it does
104+-- not (try to) read the file at filepath, but solely depends on the module
105+-- source in the input string.
106+--
107+-- Passes "-hide-all-packages" to the GHC API to prevent parsing of package
108+-- environment files. However this only works if there is no invocation of
109+-- 'setSessionDynFlags' before calling 'initDynFlagsPure'. See GHC tickets
110+-- #15513, #15541.
111+initDynFlagsPure ::
112+ GHC.GhcMonad m =>
113+ -- | Module path
114+ FilePath ->
115+ -- | Module contents
116+ String ->
117+ -- | Dynamic flags for that module
118+ m GHC.DynFlags
119+initDynFlagsPure fp input = do
120+ -- I was told we could get away with using the 'unsafeGlobalDynFlags'. as
121+ -- long as 'parseDynamicFilePragma' is impure there seems to be no reason
122+ -- to use it.
123+ dflags0 <- setDefaultExts <$> GHC.getSessionDynFlags
124+ let tokens = GHC.getOptions dflags0 (GHC.stringToStringBuffer input) fp
125+ (dflags1, _, _) <- GHC.parseDynamicFilePragma dflags0 tokens
126+ -- Turn this on last to avoid T10942
127+ let dflags2 = dflags1 `GHC.gopt_set` GHC.Opt_KeepRawTokenStream
128+ -- Prevent parsing of .ghc.environment.* "package environment files"
129+ (dflags3, _, _) <-
130+ GHC.parseDynamicFlagsCmdLine
131+ dflags2
132+ [GHC.noLoc "-hide-all-packages"]
133+ _ <- GHC.setSessionDynFlags dflags3
134+ return dflags3
135+
136+-- | Default runner of 'GHC.Ghc' action in 'IO'.
137+ghcWrapper :: GHC.Ghc a -> IO a
138+ghcWrapper act =
139+ let GHC.FlushOut flushOut = GHC.defaultFlushOut
140+ in GHC.runGhc (Just libdir) act
141+ `finally` flushOut
142+
153-- | Run a 'GHC.P' computation.
143-- | Run a 'GHC.P' computation.
154runParser ::
144runParser ::
155 -- | Computation to run
145 -- | Computation to run
@@ -168,52 +158,44 @@ runParser parser flags filename input = GHC.unP parser parseState
168 buffer = GHC.stringToStringBuffer input
158 buffer = GHC.stringToStringBuffer input
169 parseState = GHC.mkPState flags buffer location
159 parseState = GHC.mkPState flags buffer location
170
160
171−-- | Wrap GHC's 'Severity' to add 'Ord' instance.
161+-- | Remove GHC style line pragams (@{-# LINE .. #-}@) and convert them into
172−newtype SeverityOrd = SeverityOrd Severity
162+-- comments.
163+stripLinePragmas :: FilePath -> String -> (String, [Located String])
164+stripLinePragmas path = unlines' . unzip . findLines path . lines
165+ where
166+ unlines' (a, b) = (unlines a, catMaybes b)
173
167
174−instance Eq SeverityOrd where
168+findLines :: FilePath -> [String] -> [(String, Maybe (Located String))]
175− s1 == s2 = compare s1 s2 == EQ
169+findLines path = zipWith (checkLine path) [1 ..]
176
170
177−instance Ord SeverityOrd where
171+checkLine :: FilePath -> Int -> String -> (String, Maybe (Located String))
178− compare (SeverityOrd s1) (SeverityOrd s2) =
172+checkLine path line s
179− compare (f s1) (f s2)
173+ | "{-# LINE" `isPrefixOf` s =
180− where
174+ let (pragma, res) = getPragma s
181− f :: Severity -> Int
175+ size = length pragma
182− f SevOutput = 1
176+ ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (size + 1))
183− f SevFatal = 2
177+ in (res, Just $ L ss pragma)
184− f SevInteractive = 3
178+ | "#!" `isPrefixOf` s =
185− f SevDump = 4
179+ let ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (length s))
186− f SevInfo = 5
180+ in ("", Just $ L ss s)
187− f SevWarning = 6
181+ | otherwise = (s, Nothing)
188− f SevError = 7
182+ where
183+ mkSrcLoc' = mkSrcLoc (GHC.mkFastString path) line
189
184
190−----------------------------------------------------------------------------
185+getPragma :: String -> (String, String)
191−-- Helpers taken from HLint
186+getPragma [] = error "Ormolu.Parser.getPragma: input must not be empty"
187+getPragma s@(x : xs)
188+ | "#-}" `isPrefixOf` s = ("#-}", " " ++ drop 3 s)
189+ | otherwise =
190+ let (prag, remline) = getPragma xs
191+ in (x : prag, ' ' : remline)
192
192
193−parsePragmasIntoDynFlags ::
193+-- | Enable all language extensions that we think should be enabled by
194− -- | Pre-set 'DynFlags'
194+-- default for ease of use.
195− DynFlags ->
195+setDefaultExts :: DynFlags -> DynFlags
196− -- | Extra options (provided by user)
196+setDefaultExts flags = foldl' GHC.xopt_set flags autoExts
197− [Located String] ->
198− -- | File name (only for source location annotations)
199− FilePath ->
200− -- | Input for parser
201− String ->
202− IO (Either String ([GHC.Warn], DynFlags))
203−parsePragmasIntoDynFlags flags extraOpts filepath str =
204− catchErrors $ do
205− let opts = GHC.getOptions flags (GHC.stringToStringBuffer str) filepath
206− (flags', leftovers, warnings) <-
207− parseDynamicFilePragma flags (opts <> extraOpts)
208− case NE.nonEmpty leftovers of
209− Nothing -> return ()
210− Just unrecognizedOpts ->
211− throwIO (OrmoluUnrecognizedOpts (unLoc <$> unrecognizedOpts))
212− let flags'' = flags' `gopt_set` Opt_KeepRawTokenStream
213− return $ Right (warnings, flags'')
214 where
197 where
215− catchErrors act =
198+ autoExts = allExts \\ manualExts
216− GHC.handleGhcException
199+ allExts = [minBound .. maxBound]
217− reportErr
200+
218− (GHC.handleSourceError reportErr act)
201+deriving instance Bounded Extension
219− reportErr e = return $ Left (show e)
src/Ormolu/Parser/CommentStream.hs+64−152
@@ -1,77 +1,79 @@
1+{-# LANGUAGE BangPatterns #-}
1{-# LANGUAGE DeriveDataTypeable #-}
2{-# LANGUAGE DeriveDataTypeable #-}
2{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3{-# LANGUAGE LambdaCase #-}
4{-# LANGUAGE LambdaCase #-}
5+{-# LANGUAGE TupleSections #-}
4
6
5-- | Functions for working with comment stream.
7-- | Functions for working with comment stream.
6module Ormolu.Parser.CommentStream
8module Ormolu.Parser.CommentStream
7− ( -- * Comment stream
8− CommentStream (..),
9+ ( CommentStream (..),
9− mkCommentStream,
10− showCommentStream,
11−
12− -- * Comment
13 Comment (..),
10 Comment (..),
14− unComment,
11+ mkCommentStream,
15− hasAtomsBefore,
12+ isPrevHaddock,
16 isMultilineComment,
13 isMultilineComment,
14+ showCommentStream,
17 )
15 )
18where
16where
19
17
20import Data.Char (isSpace)
18import Data.Char (isSpace)
21import Data.Data (Data)
19import Data.Data (Data)
22−import qualified Data.List as L
20+import Data.Either (partitionEithers)
21+import Data.List (dropWhileEnd, isPrefixOf, sortOn)
23import Data.List.NonEmpty (NonEmpty (..))
22import Data.List.NonEmpty (NonEmpty (..))
24import qualified Data.List.NonEmpty as NE
23import qualified Data.List.NonEmpty as NE
25import Data.Maybe (mapMaybe)
24import Data.Maybe (mapMaybe)
26import qualified GHC
25import qualified GHC
27import qualified Lexer as GHC
26import qualified Lexer as GHC
28import Ormolu.Parser.Pragma
27import Ormolu.Parser.Pragma
29−import Ormolu.Parser.Shebang
30−import Ormolu.Processing.Common
31−import Ormolu.Utils (onTheSameLine, showOutputable)
28+import Ormolu.Utils (showOutputable)
32import SrcLoc
29import SrcLoc
33
30
34−----------------------------------------------------------------------------
35−-- Comment stream
36−
37-- | A stream of 'RealLocated' 'Comment's in ascending order with respect to
31-- | A stream of 'RealLocated' 'Comment's in ascending order with respect to
38-- beginning of corresponding spans.
32-- beginning of corresponding spans.
39newtype CommentStream = CommentStream [RealLocated Comment]
33newtype CommentStream = CommentStream [RealLocated Comment]
40 deriving (Eq, Data, Semigroup, Monoid)
34 deriving (Eq, Data, Semigroup, Monoid)
41
35
36+-- | A wrapper for a single comment. The 'NonEmpty' list inside contains
37+-- lines of multiline comment @{- … -}@ or just single item\/line otherwise.
38+newtype Comment = Comment (NonEmpty String)
39+ deriving (Eq, Show, Data)
40+
42−-- | Create 'CommentStream' from 'GHC.PState'. The pragmas and shebangs are
41+-- | Create 'CommentStream' from 'GHC.PState'. We also create a 'Set' of
42+-- extensions here, which is not sorted in any way. The pragma comment are
43−-- removed from the 'CommentStream'. Shebangs are only extracted from the
43+-- removed from the 'CommentStream'.
44−-- comments that come from the first argument.
45mkCommentStream ::
44mkCommentStream ::
46− -- | Original input
47− String ->
48 -- | Extra comments to include
45 -- | Extra comments to include
49 [Located String] ->
46 [Located String] ->
50 -- | Parser state to use for comment extraction
47 -- | Parser state to use for comment extraction
51 GHC.PState ->
48 GHC.PState ->
52− -- | Stack header, shebangs, pragmas, and comment stream
49+ -- | Comment stream and a set of extracted pragmas
53− ( Maybe (RealLocated Comment),
50+ (CommentStream, [Pragma])
54− [Shebang],
55− [([RealLocated Comment], Pragma)],
56− CommentStream
57− )
58−mkCommentStream input extraComments pstate =
51+mkCommentStream extraComments pstate =
59− ( mstackHeader,
52+ ( CommentStream $
60− shebangs,
53+ -- NOTE It's easier to normalize pragmas right when we construct comment
61− pragmas,
54+ -- streams. Because this way we need to do it only once and when we
62− CommentStream comments
55+ -- perform checking later they'll automatically match.
56+ mkComment <$> sortOn (realSrcSpanStart . getLoc) comments,
57+ pragmas
63 )
58 )
64 where
59 where
65− (comments, pragmas) = extractPragmas input rawComments1
60+ (comments, pragmas) = partitionEithers (partitionComments <$> rawComments)
66− (rawComments1, mstackHeader) = extractStackHeader rawComments0
61+ rawComments =
67− rawComments0 =
68− L.sortOn (realSrcSpanStart . getRealSrcSpan) . mapMaybe toRealSpan $
62+ mapMaybe toRealSpan $
69− otherExtraComments
63+ extraComments
70 ++ mapMaybe (liftMaybe . fmap unAnnotationComment) (GHC.comment_q pstate)
64 ++ mapMaybe (liftMaybe . fmap unAnnotationComment) (GHC.comment_q pstate)
71 ++ concatMap
65 ++ concatMap
72 (mapMaybe (liftMaybe . fmap unAnnotationComment) . snd)
66 (mapMaybe (liftMaybe . fmap unAnnotationComment) . snd)
73 (GHC.annotations_comments pstate)
67 (GHC.annotations_comments pstate)
74− (shebangs, otherExtraComments) = extractShebangs extraComments
68+
69+-- | Test whether a 'Comment' looks like a Haddock following a definition,
70+-- i.e. something starting with @-- ^@.
71+isPrevHaddock :: Comment -> Bool
72+isPrevHaddock (Comment (x :| _)) = "-- ^" `isPrefixOf` x
73+
74+-- | Is this comment multiline-style?
75+isMultilineComment :: Comment -> Bool
76+isMultilineComment (Comment (x :| _)) = "{-" `isPrefixOf` x
75
77
76-- | Pretty-print a 'CommentStream'.
78-- | Pretty-print a 'CommentStream'.
77showCommentStream :: CommentStream -> String
79showCommentStream :: CommentStream -> String
@@ -82,117 +84,28 @@ showCommentStream (CommentStream xs) =
82 showComment (GHC.L l str) = showOutputable l ++ " " ++ show str
84 showComment (GHC.L l str) = showOutputable l ++ " " ++ show str
83
85
84----------------------------------------------------------------------------
86----------------------------------------------------------------------------
85−-- Comment
87+-- 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
88
94-- | Normalize comment string. Sometimes one multi-line comment is turned
89-- | Normalize comment string. Sometimes one multi-line comment is turned
95-- into several lines for subsequent outputting with correct indentation for
90-- into several lines for subsequent outputting with correct indentation for
96-- each line.
91-- each line.
97−mkComment ::
92+mkComment :: RealLocated String -> RealLocated Comment
98− -- | Lines of original input with their indices
93+mkComment (L l s) =
99− [(Int, String)] ->
94+ L l . Comment . fmap dropTrailing $
100− -- | Raw comment string
95+ if "{-" `isPrefixOf` s
101− RealLocated String ->
96+ then case NE.nonEmpty (lines s) of
102− -- | Remaining lines of original input and the constructed 'Comment'
97+ Nothing -> s :| []
103− ([(Int, String)], RealLocated Comment)
98+ Just (x :| xs) ->
104−mkComment ls (L l s) = (ls', comment)
99+ let getIndent y =
100+ if all isSpace y
101+ then startIndent
102+ else length (takeWhile isSpace y)
103+ n = minimum (startIndent : fmap getIndent xs)
104+ in x :| (drop n <$> xs)
105+ else s :| []
105 where
106 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
107+ dropTrailing = dropWhileEnd isSpace
132 startIndent = srcSpanStartCol l - 1
108 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−
139−-- | Check whether the 'Comment' had some non-whitespace atoms in front of
140−-- it in the original input.
141−hasAtomsBefore :: Comment -> Bool
142−hasAtomsBefore (Comment atomsBefore _) = atomsBefore
143−
144−-- | Is this comment multiline-style?
145−isMultilineComment :: Comment -> Bool
146−isMultilineComment (Comment _ (x :| _)) = "{-" `L.isPrefixOf` x
147−
148−----------------------------------------------------------------------------
149−-- Helpers
150−
151−-- | Detect and extract stack header if it is present.
152−extractStackHeader ::
153− -- | Comment stream to analyze
154− [RealLocated String] ->
155− ([RealLocated String], Maybe (RealLocated Comment))
156−extractStackHeader = \case
157− [] -> ([], Nothing)
158− (x : xs) ->
159− let comment = snd (mkComment [] x)
160− in if isStackHeader (unRealSrcSpan comment)
161− then (xs, Just comment)
162− else (x : xs, Nothing)
163− where
164− isStackHeader (Comment _ (x :| _)) =
165− "stack" `L.isPrefixOf` dropWhile isSpace (drop 2 x)
166−
167−-- | Extract pragmas and their associated comments.
168−extractPragmas ::
169− -- | Input
170− String ->
171− -- | Comment stream to analyze
172− [RealLocated String] ->
173− ([RealLocated Comment], [([RealLocated Comment], Pragma)])
174−extractPragmas input = go initialLs id id
175− where
176− initialLs = zip [1 ..] (lines input)
177− go ls csSoFar pragmasSoFar = \case
178− [] -> (csSoFar [], pragmasSoFar [])
179− (x : xs) ->
180− case parsePragma (unRealSrcSpan x) of
181− Nothing ->
182− let (ls', x') = mkComment ls x
183− in go ls' (csSoFar . (x' :)) pragmasSoFar xs
184− Just pragma ->
185− let combined ys = (csSoFar ys, pragma)
186− go' ls' ys rest = go ls' id (pragmasSoFar . (combined ys :)) rest
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
109
197-- | Get a 'String' from 'GHC.AnnotationComment'.
110-- | Get a 'String' from 'GHC.AnnotationComment'.
198unAnnotationComment :: GHC.AnnotationComment -> Maybe String
111unAnnotationComment :: GHC.AnnotationComment -> Maybe String
@@ -214,13 +127,12 @@ toRealSpan :: Located a -> Maybe (RealLocated a)
214toRealSpan (L (RealSrcSpan l) a) = Just (L l a)
127toRealSpan (L (RealSrcSpan l) a) = Just (L l a)
215toRealSpan _ = Nothing
128toRealSpan _ = Nothing
216
129
217−-- | Remove consecutive blank lines.
130+-- | If a given comment is a pragma, return it in parsed form in 'Right'.
218−removeConseqBlanks :: NonEmpty String -> NonEmpty String
131+-- Otherwise return the original comment unchanged.
219−removeConseqBlanks (x :| xs) = x :| go (null x) id xs
132+partitionComments ::
220− where
133+ RealLocated String ->
221− go seenBlank acc = \case
134+ Either (RealLocated String) Pragma
222− [] -> acc []
135+partitionComments input =
223− (y : ys) ->
136+ case parsePragma (unLoc input) of
224− if seenBlank && null y
137+ Nothing -> Left input
225− then go True acc ys
138+ Just pragma -> Right pragma
226− else go (null y) (acc . (y :)) ys
src/Ormolu/Parser/Pragma.hs+11−14
@@ -10,7 +10,7 @@ where
10
10
11import Control.Monad
11import Control.Monad
12import Data.Char (isSpace, toLower)
12import Data.Char (isSpace, toLower)
13−import qualified Data.List as L
13+import Data.List
14import qualified EnumSet as ES
14import qualified EnumSet as ES
15import FastString (mkFastString, unpackFS)
15import FastString (mkFastString, unpackFS)
16import qualified Lexer as L
16import qualified Lexer as L
@@ -35,8 +35,8 @@ parsePragma ::
35 String ->
35 String ->
36 Maybe Pragma
36 Maybe Pragma
37parsePragma input = do
37parsePragma input = do
38− inputNoPrefix <- L.stripPrefix "{-#" input
38+ inputNoPrefix <- stripPrefix "{-#" input
39− guard ("#-}" `L.isSuffixOf` input)
39+ guard ("#-}" `isSuffixOf` input)
40 let contents = take (length inputNoPrefix - 3) inputNoPrefix
40 let contents = take (length inputNoPrefix - 3) inputNoPrefix
41 (pragmaName, cs) = (break isSpace . dropWhile isSpace) contents
41 (pragmaName, cs) = (break isSpace . dropWhile isSpace) contents
42 case toLower <$> pragmaName of
42 case toLower <$> pragmaName of
@@ -46,7 +46,7 @@ parsePragma input = do
46 _ -> Nothing
46 _ -> Nothing
47 where
47 where
48 trimSpaces :: String -> String
48 trimSpaces :: String -> String
49− trimSpaces = L.dropWhileEnd isSpace . dropWhile isSpace
49+ trimSpaces = dropWhileEnd isSpace . dropWhile isSpace
50
50
51-- | Assuming the input consists of a series of tokens from a language
51-- | Assuming the input consists of a series of tokens from a language
52-- pragma, return the set of enabled extensions.
52-- pragma, return the set of enabled extensions.
@@ -54,7 +54,7 @@ parseExtensions :: String -> Maybe [String]
54parseExtensions str = tokenize str >>= go
54parseExtensions str = tokenize str >>= go
55 where
55 where
56 go = \case
56 go = \case
57− [L.ITconid ext] -> return [unpackFS ext]
57+ (L.ITconid ext : []) -> return [unpackFS ext]
58 (L.ITconid ext : L.ITcomma : xs) -> (unpackFS ext :) <$> go xs
58 (L.ITconid ext : L.ITcomma : xs) -> (unpackFS ext :) <$> go xs
59 _ -> Nothing
59 _ -> Nothing
60
60
@@ -68,15 +68,12 @@ tokenize input =
68 location = mkRealSrcLoc (mkFastString "") 1 1
68 location = mkRealSrcLoc (mkFastString "") 1 1
69 buffer = stringToStringBuffer input
69 buffer = stringToStringBuffer input
70 parseState = L.mkPStatePure parserFlags buffer location
70 parseState = L.mkPStatePure parserFlags buffer location
71− parserFlags =
71+ parserFlags = L.ParserFlags
72− L.mkParserFlags'
73− ES.empty
72+ { L.pWarningFlags = ES.empty,
74− ES.empty
73+ L.pExtensionFlags = ES.empty,
75− (newSimpleUnitId (ComponentId (mkFastString "")))
74+ L.pThisPackage = newSimpleUnitId (ComponentId (mkFastString "")),
76− True
75+ L.pExtsBitmap = 0xffffffffffffffff
77− True
76+ }
78− True
79− True
80
77
81-- | Haskell lexer.
78-- | Haskell lexer.
82pLexer :: L.P [L.Token]
79pLexer :: L.P [L.Token]
src/Ormolu/Parser/Result.hs+11−26
@@ -7,38 +7,23 @@ 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
14import Ormolu.Parser.Pragma (Pragma)
13import Ormolu.Parser.Pragma (Pragma)
15−import Ormolu.Parser.Shebang (Shebang)
16
14
17-- | A collection of data that represents a parsed module in Ormolu.
15-- | A collection of data that represents a parsed module in Ormolu.
18−data ParseResult = ParseResult
16+data ParseResult
17+ = 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
24− prStackHeader :: Maybe (RealLocated Comment),
25− -- | Shebangs found in the input
26− prShebangs :: [Shebang],
27− -- | Pragmas and the associated comments
28− prPragmas :: [([RealLocated Comment], Pragma)],
29− -- | Comment stream
22+ -- | Comment stream
30− prCommentStream :: CommentStream,
23+ prCommentStream :: CommentStream,
31− -- | Whether or not record dot syntax is enabled
24+ -- | Extensions enabled in that module
32− prUseRecordDot :: Bool,
25+ prExtensions :: [Pragma]
33− -- | Whether or not ImportQualifiedPost is enabled
34− 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− }
26+ }
42
27
43-- | Pretty-print a 'ParseResult'.
28-- | Pretty-print a 'ParseResult'.
44prettyPrintParseResult :: ParseResult -> String
29prettyPrintParseResult :: ParseResult -> String
src/Ormolu/Parser/Shebang.hsdeleted−27
@@ -1,27 +0,0 @@
1−{-# LANGUAGE DeriveDataTypeable #-}
2−
3−-- | A module for dealing with shebangs.
4−module Ormolu.Parser.Shebang
5− ( Shebang (..),
6− extractShebangs,
7− isShebang,
8− )
9−where
10−
11−import Data.Data (Data)
12−import qualified Data.List as L
13−import SrcLoc
14−
15−-- | A wrapper for a shebang.
16−newtype Shebang = Shebang (Located String)
17− deriving (Eq, Data)
18−
19−-- | Extract shebangs from the beginning of a comment stream.
20−extractShebangs :: [Located String] -> ([Shebang], [Located String])
21−extractShebangs comments = (Shebang <$> shebangs, rest)
22− where
23− (shebangs, rest) = span (isShebang . unLoc) comments
24−
25−-- | Return 'True' if given 'String' is a shebang.
26−isShebang :: String -> Bool
27−isShebang str = "#!" `L.isPrefixOf` str
src/Ormolu/Printer.hs+7−17
@@ -1,3 +1,5 @@
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE RecordWildCards #-}
3{-# LANGUAGE RecordWildCards #-}
2
4
3-- | Pretty-printer for Haskell AST.
5-- | Pretty-printer for Haskell AST.
@@ -11,7 +13,6 @@ import Ormolu.Parser.Result
11import Ormolu.Printer.Combinators
13import Ormolu.Printer.Combinators
12import Ormolu.Printer.Meat.Module
14import Ormolu.Printer.Meat.Module
13import Ormolu.Printer.SpanStream
15import Ormolu.Printer.SpanStream
14−import Ormolu.Processing.Postprocess (postprocess)
15
16
16-- | Render a module.
17-- | Render a module.
17printModule ::
18printModule ::
@@ -20,19 +21,8 @@ printModule ::
20 -- | Resulting rendition
21 -- | Resulting rendition
21 Text
22 Text
22printModule ParseResult {..} =
23printModule ParseResult {..} =
23− prLiteralPrefix <> region <> prLiteralSuffix
24− where
25− region =
26− postprocess prIndent $
27− runR
24+ runR
28− ( p_hsModule
29− prStackHeader
30− prShebangs
31− prPragmas
32− prImportQualifiedPost
33− prParsedSource
25+ (p_hsModule prExtensions prParsedSource)
34− )
35− (mkSpanStream prParsedSource)
26+ (mkSpanStream prParsedSource)
36− prCommentStream
27+ prCommentStream
37− prAnns
28+ prAnns
38− prUseRecordDot
src/Ormolu/Printer/Combinators.hs+30−41
@@ -1,7 +1,6 @@
1−{-# LANGUAGE FlexibleContexts #-}
2−{-# LANGUAGE GADTs #-}
3{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE LambdaCase #-}
4{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE RecordWildCards #-}
5
4
6-- | Printing combinators. The definitions here are presented in such an
5-- | Printing combinators. The definitions here are presented in such an
7-- order so you can just go through the Haddocks and by the end of the file
6-- order so you can just go through the Haddocks and by the end of the file
@@ -21,7 +20,6 @@ module Ormolu.Printer.Combinators
21 space,
20 space,
22 newline,
21 newline,
23 inci,
22 inci,
24− inciIf,
25 located,
23 located,
26 located',
24 located',
27 switchLayout,
25 switchLayout,
@@ -52,57 +50,57 @@ module Ormolu.Printer.Combinators
52
50
53 -- ** Literals
51 -- ** Literals
54 comma,
52 comma,
55− commaDel,
56− equals,
57
53
58− -- ** Stateful markers
54+ -- ** Comments
59− SpanMark (..),
60− spanMarkSpan,
61 HaddockStyle (..),
55 HaddockStyle (..),
62− setSpanMark,
56+ setLastCommentSpan,
63− getSpanMark,
57+ getLastCommentSpan,
64 )
58 )
65where
59where
66
60
67import Control.Monad
61import Control.Monad
62+import Data.Data (Data)
68import Data.List (intersperse)
63import Data.List (intersperse)
69import Data.Text (Text)
64import Data.Text (Text)
70import Ormolu.Printer.Comments
65import Ormolu.Printer.Comments
71import Ormolu.Printer.Internal
66import Ormolu.Printer.Internal
67+import Ormolu.Utils (isModule)
72import SrcLoc
68import SrcLoc
73
69
74----------------------------------------------------------------------------
70----------------------------------------------------------------------------
75-- Basic
71-- Basic
76
72
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
73-- | Enter a 'Located' entity. This combinator handles outputting comments
87-- and sets layout (single-line vs multi-line) for the inner computation.
74-- 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
75-- Roughly, the rule for using 'located' is that every time there is a
89-- 'Located' wrapper, it should be “discharged” with a corresponding
76-- 'Located' wrapper, it should be “discharged” with a corresponding
90-- 'located' invocation.
77-- 'located' invocation.
91located ::
78located ::
79+ Data a =>
92 -- | Thing to enter
80 -- | Thing to enter
93 Located a ->
81 Located a ->
94 -- | How to render inner value
82 -- | How to render inner value
95 (a -> R ()) ->
83 (a -> R ()) ->
96 R ()
84 R ()
97−located (L (UnhelpfulSpan _) a) f = f a
85+located loc f = do
98−located (L (RealSrcSpan l) a) f = do
86+ let withRealLocated (L l a) g =
87+ case l of
88+ UnhelpfulSpan _ -> return ()
89+ RealSrcSpan l' -> g (L l' a)
99− spitPrecedingComments l
90+ withRealLocated loc spitPrecedingComments
91+ let setEnclosingSpan =
92+ case getLoc loc of
93+ UnhelpfulSpan _ -> id
94+ RealSrcSpan orf ->
95+ if isModule (unLoc loc)
96+ then id
100− withEnclosingSpan l $
97+ else withEnclosingSpan orf
101− switchLayout [RealSrcSpan l] (f a)
98+ setEnclosingSpan $ switchLayout [getLoc loc] (f (unLoc loc))
102− spitFollowingComments l
99+ withRealLocated loc spitFollowingComments
103
100
104-- | A version of 'located' with arguments flipped.
101-- | A version of 'located' with arguments flipped.
105located' ::
102located' ::
103+ Data a =>
106 -- | How to render inner value
104 -- | How to render inner value
107 (a -> R ()) ->
105 (a -> R ()) ->
108 -- | Thing to enter
106 -- | Thing to enter
@@ -185,12 +183,10 @@ sepSemi f xs = vlayout singleLine multiLine
185 xs' ->
183 xs' ->
186 if ub
184 if ub
187 then do
185 then do
188− txt "{"
186+ txt "{ "
189− space
190− sep (txt ";" >> space) (dontUseBraces . f) xs'
187+ sep (txt "; ") (dontUseBraces . f) xs'
191− space
192− txt "}"
188+ txt " }"
193− else sep (txt ";" >> space) f xs'
189+ else sep (txt "; ") f xs'
194 multiLine =
190 multiLine =
195 sep newline (dontUseBraces . f) xs
191 sep newline (dontUseBraces . f) xs
196
192
@@ -203,7 +199,6 @@ data BracketStyle
203 N
199 N
204 | -- | Shifted one level
200 | -- | Shifted one level
205 S
201 S
206− deriving (Eq, Show)
207
202
208-- | Surround given entity by backticks.
203-- | Surround given entity by backticks.
209backticks :: R () -> R ()
204backticks :: R () -> R ()
@@ -280,7 +275,9 @@ brackets_ needBreaks open close style m = sitcc (vlayout singleLine multiLine)
280 then newline >> inci m
275 then newline >> inci m
281 else space >> sitcc m
276 else space >> sitcc m
282 newline
277 newline
278+ case style of
279+ N -> txt close
283− inciIf (style == S) (txt close)
280+ S -> inci (txt close)
284
281
285----------------------------------------------------------------------------
282----------------------------------------------------------------------------
286-- Literals
283-- Literals
@@ -288,11 +285,3 @@ brackets_ needBreaks open close style m = sitcc (vlayout singleLine multiLine)
288-- | Print @,@.
285-- | Print @,@.
289comma :: R ()
286comma :: R ()
290comma = txt ","
287comma = 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+78−69
@@ -7,17 +7,17 @@ module Ormolu.Printer.Comments
7 ( spitPrecedingComments,
7 ( spitPrecedingComments,
8 spitFollowingComments,
8 spitFollowingComments,
9 spitRemainingComments,
9 spitRemainingComments,
10− spitCommentNow,
11− spitCommentPending,
12 )
10 )
13where
11where
14
12
15import Control.Monad
13import Control.Monad
14+import Data.Coerce (coerce)
15+import Data.Data (Data)
16import qualified Data.List.NonEmpty as NE
16import qualified Data.List.NonEmpty as NE
17−import Data.Maybe (listToMaybe)
18import qualified Data.Text as T
17import qualified Data.Text as T
19import Ormolu.Parser.CommentStream
18import Ormolu.Parser.CommentStream
20import Ormolu.Printer.Internal
19import Ormolu.Printer.Internal
20+import Ormolu.Utils (isModule)
21import SrcLoc
21import SrcLoc
22
22
23----------------------------------------------------------------------------
23----------------------------------------------------------------------------
@@ -25,91 +25,105 @@ import SrcLoc
25
25
26-- | Output all preceding comments for an element at given location.
26-- | Output all preceding comments for an element at given location.
27spitPrecedingComments ::
27spitPrecedingComments ::
28+ Data a =>
28− -- | Span of the element to attach comments to
29+ -- | AST element to attach comments to
29− RealSrcSpan ->
30+ RealLocated a ->
30 R ()
31 R ()
31spitPrecedingComments ref = do
32spitPrecedingComments ref = do
33+ r <- getLastCommentSpan
34+ case r of
35+ Just (Just Pipe, _) ->
36+ -- We should not insert comments between pipe Haddock and the thing
37+ -- it's attached to.
38+ return ()
39+ _ -> do
32− gotSome <- handleCommentSeries (spitPrecedingComment ref)
40+ gotSome <- handleCommentSeries (spitPrecedingComment ref)
33− when gotSome $ do
41+ when gotSome $ do
34− lastMark <- getSpanMark
35− -- Insert a blank line between the preceding comments and the thing
42+ -- Insert a blank line between the preceding comments and the thing
36− -- after them if there was a blank line in the input.
43+ -- after them if there was a blank line in the input.
44+ lastSpn <- fmap snd <$> getLastCommentSpan
37− when (needsNewlineBefore ref lastMark) newline
45+ when (needsNewlineBefore (getLoc ref) lastSpn) newline
38
46
39-- | Output all comments following an element at given location.
47-- | Output all comments following an element at given location.
40spitFollowingComments ::
48spitFollowingComments ::
49+ Data a =>
41− -- | Span of the element to attach comments to
50+ -- | AST element of attach comments to
42− RealSrcSpan ->
51+ RealLocated a ->
43 R ()
52 R ()
44spitFollowingComments ref = do
53spitFollowingComments ref = do
45− trimSpanStream ref
54+ trimSpanStream (getLoc ref)
46 void $ handleCommentSeries (spitFollowingComment ref)
55 void $ handleCommentSeries (spitFollowingComment ref)
47
56
48-- | Output all remaining comments in the comment stream.
57-- | Output all remaining comments in the comment stream.
49spitRemainingComments :: R ()
58spitRemainingComments :: 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
59+spitRemainingComments = void $ handleCommentSeries spitRemainingComment
55
60
56----------------------------------------------------------------------------
61----------------------------------------------------------------------------
57-- Single-comment functions
62-- Single-comment functions
58
63
59-- | Output a single preceding comment for an element at given location.
64-- | Output a single preceding comment for an element at given location.
60spitPrecedingComment ::
65spitPrecedingComment ::
66+ Data a =>
61− -- | Span of the element to attach comments to
67+ -- | AST element to attach comments to
68+ RealLocated a ->
69+ -- | Location of last comment in the series
62− RealSrcSpan ->
70+ Maybe RealSrcSpan ->
63 -- | Are we done?
71 -- | Are we done?
64 R Bool
72 R Bool
65−spitPrecedingComment ref = do
73+spitPrecedingComment (L ref a) mlastSpn = do
66− mlastMark <- getSpanMark
67 let p (L l _) = realSrcSpanEnd l <= realSrcSpanStart ref
74 let p (L l _) = realSrcSpanEnd l <= realSrcSpanStart ref
68 withPoppedComment p $ \l comment -> do
75 withPoppedComment p $ \l comment -> do
69− lineSpans <- thisLineSpans
76+ dirtyLine <-
70− let thisCommentLine = srcLocLine (realSrcSpanStart l)
77+ case mlastSpn of
71− needsNewline =
78+ -- NOTE When the current line is dirty it means that something that
72− case listToMaybe lineSpans of
79+ -- can have comments attached to it is already on the line. To avoid
73− Nothing -> False
80+ -- problems with idempotence we cannot output the first comment
74− Just spn -> srcLocLine (realSrcSpanEnd spn) /= thisCommentLine
81+ -- immediately because it'll be attached to the previous element (on
82+ -- the same line) on the next run, so we play safe here and output
83+ -- an extra 'newline' in this case.
84+ Nothing -> isLineDirty -- only for very first preceding comment
85+ Just _ -> return False
75− when (needsNewline || needsNewlineBefore l mlastMark) newline
86+ when (dirtyLine || needsNewlineBefore l mlastSpn) newline
76 spitCommentNow l comment
87 spitCommentNow l comment
77− if theSameLinePre l ref
88+ if theSameLinePre l ref && not (isModule a)
78 then space
89 then space
79 else newline
90 else newline
80
91
81-- | Output a comment that follows element at given location immediately on
92-- | Output a comment that follows element at given location immediately on
82-- the same line, if there is any.
93-- the same line, if there is any.
83spitFollowingComment ::
94spitFollowingComment ::
95+ Data a =>
84 -- | AST element to attach comments to
96 -- | AST element to attach comments to
97+ RealLocated a ->
98+ -- | Location of last comment in the series
85− RealSrcSpan ->
99+ Maybe RealSrcSpan ->
86 -- | Are we done?
100 -- | Are we done?
87 R Bool
101 R Bool
88−spitFollowingComment ref = do
102+spitFollowingComment (L ref a) mlastSpn = do
89− mlastMark <- getSpanMark
90 mnSpn <- nextEltSpan
103 mnSpn <- nextEltSpan
91 -- Get first enclosing span that is not equal to reference span, i.e. it's
104 -- Get first enclosing span that is not equal to reference span, i.e. it's
92 -- truly something enclosing the AST element.
105 -- truly something enclosing the AST element.
93 meSpn <- getEnclosingSpan (/= ref)
106 meSpn <- getEnclosingSpan (/= ref)
94− withPoppedComment (commentFollowsElt ref mnSpn meSpn mlastMark) $ \l comment ->
107+ withPoppedComment (commentFollowsElt ref mnSpn meSpn mlastSpn) $ \l comment ->
95− if theSameLinePost l ref
108+ if theSameLinePost l ref && not (isModule a)
96 then
109 then
97 if isMultilineComment comment
110 if isMultilineComment comment
98 then space >> spitCommentNow l comment
111 then space >> spitCommentNow l comment
99 else spitCommentPending OnTheSameLine l comment
112 else spitCommentPending OnTheSameLine l comment
100 else do
113 else do
101− when (needsNewlineBefore l mlastMark) $
114+ when (needsNewlineBefore l mlastSpn) $
102 registerPendingCommentLine OnNextLine ""
115 registerPendingCommentLine OnNextLine ""
103 spitCommentPending OnNextLine l comment
116 spitCommentPending OnNextLine l comment
104
117
105-- | Output a single remaining comment from the comment stream.
118-- | Output a single remaining comment from the comment stream.
106spitRemainingComment ::
119spitRemainingComment ::
120+ -- | Location of last comment in the series
121+ Maybe RealSrcSpan ->
107 -- | Are we done?
122 -- | Are we done?
108 R Bool
123 R Bool
109−spitRemainingComment = do
124+spitRemainingComment mlastSpn =
110− mlastMark <- getSpanMark
111 withPoppedComment (const True) $ \l comment -> do
125 withPoppedComment (const True) $ \l comment -> do
112− when (needsNewlineBefore l mlastMark) newline
126+ when (needsNewlineBefore l mlastSpn) newline
113 spitCommentNow l comment
127 spitCommentNow l comment
114 newline
128 newline
115
129
@@ -120,13 +134,13 @@ spitRemainingComment = do
120handleCommentSeries ::
134handleCommentSeries ::
121 -- | Given location of previous comment, output the next comment
135 -- | Given location of previous comment, output the next comment
122 -- returning 'True' if we're done
136 -- returning 'True' if we're done
123− R Bool ->
137+ (Maybe RealSrcSpan -> R Bool) ->
124 -- | Whether we printed any comments
138 -- | Whether we printed any comments
125 R Bool
139 R Bool
126handleCommentSeries f = go False
140handleCommentSeries f = go False
127 where
141 where
128 go gotSome = do
142 go gotSome = do
129− done <- f
143+ done <- getLastCommentSpan >>= f . fmap snd
130 if done
144 if done
131 then return gotSome
145 then return gotSome
132 else go True
146 else go True
@@ -152,14 +166,13 @@ needsNewlineBefore ::
152 -- | Current comment span
166 -- | Current comment span
153 RealSrcSpan ->
167 RealSrcSpan ->
154 -- | Last printed comment span
168 -- | Last printed comment span
155− Maybe SpanMark ->
169+ Maybe RealSrcSpan ->
156 Bool
170 Bool
157−needsNewlineBefore _ (Just (HaddockSpan _ _)) = True
171+needsNewlineBefore l mlastSpn =
158−needsNewlineBefore l mlastMark =
172+ case mlastSpn of
159− case spanMarkSpan <$> mlastMark of
160 Nothing -> False
173 Nothing -> False
161− Just lastMark ->
174+ Just lastSpn ->
162− srcSpanStartLine l > srcSpanEndLine lastMark + 1
175+ srcSpanStartLine l > srcSpanEndLine lastSpn + 1
163
176
164-- | Is the preceding comment and AST element are on the same line?
177-- | Is the preceding comment and AST element are on the same line?
165theSameLinePre ::
178theSameLinePre ::
@@ -190,11 +203,11 @@ commentFollowsElt ::
190 -- | Location of enclosing AST element
203 -- | Location of enclosing AST element
191 Maybe RealSrcSpan ->
204 Maybe RealSrcSpan ->
192 -- | Location of last comment in the series
205 -- | Location of last comment in the series
193− Maybe SpanMark ->
206+ Maybe RealSrcSpan ->
194 -- | Comment to test
207 -- | Comment to test
195 RealLocated Comment ->
208 RealLocated Comment ->
196 Bool
209 Bool
197−commentFollowsElt ref mnSpn meSpn mlastMark (L l comment) =
210+commentFollowsElt ref mnSpn meSpn mlastSpn (L l comment) =
198 -- A comment follows a AST element if all 4 conditions are satisfied:
211 -- A comment follows a AST element if all 4 conditions are satisfied:
199 goesAfter
212 goesAfter
200 && logicallyFollows
213 && logicallyFollows
@@ -207,8 +220,9 @@ commentFollowsElt ref mnSpn meSpn mlastMark (L l comment) =
207 -- 2) The comment logically belongs to the element, four cases:
220 -- 2) The comment logically belongs to the element, four cases:
208 logicallyFollows =
221 logicallyFollows =
209 theSameLinePost l ref -- a) it's on the same line
222 theSameLinePost l ref -- a) it's on the same line
223+ || isPrevHaddock comment -- b) it's a Haddock string starting with -- ^
210− || continuation -- b) it's a continuation of a comment block
224+ || continuation -- c) it's a continuation of a comment block
211− || lastInEnclosing -- c) it's the last element in the enclosing construct
225+ || lastInEnclosing -- d) it's the last element in the enclosing construct
212
226
213 -- 3) There is no other AST element between this element and the comment:
227 -- 3) There is no other AST element between this element and the comment:
214 noEltBetween =
228 noEltBetween =
@@ -230,20 +244,15 @@ commentFollowsElt ref mnSpn meSpn mlastMark (L l comment) =
230 Nothing -> True
244 Nothing -> True
231 Just espn ->
245 Just espn ->
232 let startColumn = srcLocCol . realSrcSpanStart
246 let startColumn = srcLocCol . realSrcSpanStart
233− in startColumn espn > startColumn ref
247+ in if startColumn espn > startColumn ref
248+ then True
249+ else
234− || ( abs (startColumn espn - startColumn l)
250+ abs (startColumn espn - startColumn l)
235− >= abs (startColumn ref - startColumn l)
251+ >= abs (startColumn ref - startColumn l)
236− )
237 continuation =
252 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
253+ case mlastSpn of
242− Just (HaddockSpan _ _) -> False
254+ Nothing -> False
243− Just (CommentSpan spn) ->
244− srcSpanEndLine spn + 1 == srcSpanStartLine l
255+ Just spn -> srcSpanEndLine spn + 1 == srcSpanStartLine l
245− _ -> False
246− )
247 lastInEnclosing =
256 lastInEnclosing =
248 case meSpn of
257 case meSpn of
249 -- When there is no enclosing element, return false
258 -- When there is no enclosing element, return false
@@ -265,9 +274,9 @@ spitCommentNow spn comment = do
265 . sequence_
274 . sequence_
266 . NE.intersperse newline
275 . NE.intersperse newline
267 . fmap (txt . T.pack)
276 . fmap (txt . T.pack)
268− . unComment
277+ . coerce
269 $ comment
278 $ comment
270− setSpanMark (CommentSpan spn)
279+ setLastCommentSpan Nothing spn
271
280
272-- | Output a 'Comment' at the end of correct line or after it depending on
281-- | Output a 'Comment' at the end of correct line or after it depending on
273-- 'CommentPosition'. Used for comments that may potentially follow on the
282-- 'CommentPosition'. Used for comments that may potentially follow on the
@@ -281,6 +290,6 @@ spitCommentPending position spn comment = do
281 . sequence_
290 . sequence_
282 . NE.toList
291 . NE.toList
283 . fmap (registerPendingCommentLine position . T.pack)
292 . fmap (registerPendingCommentLine position . T.pack)
284− . unComment
293+ . coerce
285 $ comment
294 $ comment
286− setSpanMark (CommentSpan spn)
295+ setLastCommentSpan Nothing spn
src/Ormolu/Printer/Internal.hs+110−173
@@ -14,11 +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,
21− useRecordDot,
20+ isLineDirty,
22 inci,
21 inci,
23 sitcc,
22 sitcc,
24 Layout (..),
23 Layout (..),
@@ -39,14 +38,9 @@ module Ormolu.Printer.Internal
39 popComment,
38 popComment,
40 getEnclosingSpan,
39 getEnclosingSpan,
41 withEnclosingSpan,
40 withEnclosingSpan,
42− thisLineSpans,
43−
44− -- * Stateful markers
45− SpanMark (..),
46− spanMarkSpan,
47 HaddockStyle (..),
41 HaddockStyle (..),
48− setSpanMark,
42+ setLastCommentSpan,
49− getSpanMark,
43+ getLastCommentSpan,
50
44
51 -- * Annotations
45 -- * Annotations
52 getAnns,
46 getAnns,
@@ -68,6 +62,7 @@ import Ormolu.Parser.CommentStream
68import Ormolu.Printer.SpanStream
62import Ormolu.Printer.SpanStream
69import Ormolu.Utils (showOutputable)
63import Ormolu.Utils (showOutputable)
70import Outputable (Outputable)
64import Outputable (Outputable)
65+import SrcLoc
71
66
72----------------------------------------------------------------------------
67----------------------------------------------------------------------------
73-- The 'R' monad
68-- The 'R' monad
@@ -79,44 +74,43 @@ newtype R a = R (ReaderT RC (State SC) a)
79
74
80-- | Reader context of 'R'. This should be used when we control rendering by
75-- | Reader context of 'R'. This should be used when we control rendering by
81-- enclosing certain expressions with wrappers.
76-- enclosing certain expressions with wrappers.
82−data RC = RC
77+data RC
78+ = RC
83− { -- | Indentation level, as the column index we need to start from after
79+ { -- | Indentation level, as the column index we need to start from after
84− -- a newline if we break lines
80+ -- a newline if we break lines
85− rcIndent :: !Int,
81+ rcIndent :: !Int,
86− -- | Current layout
82+ -- | Current layout
87− rcLayout :: Layout,
83+ rcLayout :: Layout,
88− -- | Spans of enclosing elements of AST
84+ -- | Spans of enclosing elements of AST
89− rcEnclosingSpans :: [RealSrcSpan],
85+ rcEnclosingSpans :: [RealSrcSpan],
90− -- | Collection of annotations
86+ -- | Collection of annotations
91− rcAnns :: Anns,
87+ rcAnns :: Anns,
92− -- | Whether the last expression in the layout can use braces
88+ -- | If the last expression in the layout can use braces
93− rcCanUseBraces :: Bool,
89+ rcCanUseBraces :: Bool
94− -- | Whether the source could have used the record dot preprocessor
95− rcUseRecDot :: Bool
96− }
90+ }
97
91
98-- | State context of 'R'.
92-- | State context of 'R'.
99−data SC = SC
93+data SC
94+ = SC
100− { -- | Index of the next column to render
95+ { -- | Index of the next column to render
101− scColumn :: !Int,
96+ scColumn :: !Int,
102− -- | Indentation level that was used for the current line
103− scIndent :: !Int,
104− -- | Rendered source code so far
97+ -- | Rendered source code so far
105− scBuilder :: Builder,
98+ scBuilder :: Builder,
106− -- | Span stream
99+ -- | Span stream
107− scSpanStream :: SpanStream,
100+ scSpanStream :: SpanStream,
108− -- | Spans of atoms that have been printed on the current line so far
109− scThisLineSpans :: [RealSrcSpan],
110− -- | Comment stream
101+ -- | Comment stream
111− scCommentStream :: CommentStream,
102+ scCommentStream :: CommentStream,
112− -- | Pending comment lines (in reverse order) to be inserted before next
103+ -- | Pending comment lines (in reverse order) to be inserted before next
113− -- newline, 'Int' is the indentation level
104+ -- newline, 'Int' is the indentation level
114− scPendingComments :: ![(CommentPosition, Text)],
105+ scPendingComments :: ![(CommentPosition, Int, Text)],
106+ -- | Whether the current line is “dirty”, that is, already contains
107+ -- atoms that can have comments attached to them
108+ scDirtyLine :: !Bool,
115− -- | Whether to output a space before the next output
109+ -- | Whether to output a space before the next output
116− scRequestedDelimiter :: !RequestedDelimiter,
110+ scRequestedDelimiter :: !RequestedDelimiter,
117− -- | An auxiliary marker for keeping track of last output element
111+ -- | Span of last output comment
118− scSpanMark :: !(Maybe SpanMark)
112+ scLastCommentSpan :: !(Maybe (Maybe HaddockStyle, RealSrcSpan))
119− }
113+ }
120
114
121-- | Make sure next output is delimited by one of the following.
115-- | Make sure next output is delimited by one of the following.
122data RequestedDelimiter
116data RequestedDelimiter
@@ -158,55 +152,32 @@ runR ::
158 CommentStream ->
152 CommentStream ->
159 -- | Annotations
153 -- | Annotations
160 Anns ->
154 Anns ->
161− -- | Use Record Dot Syntax
162− Bool ->
163 -- | Resulting rendition
155 -- | Resulting rendition
164 Text
156 Text
165−runR (R m) sstream cstream anns recDot =
157+runR (R m) sstream cstream anns =
166 TL.toStrict . toLazyText . scBuilder $ execState (runReaderT m rc) sc
158 TL.toStrict . toLazyText . scBuilder $ execState (runReaderT m rc) sc
167 where
159 where
168− rc =
160+ rc = RC
169− RC
170− { rcIndent = 0,
161+ { rcIndent = 0,
171− rcLayout = MultiLine,
162+ rcLayout = MultiLine,
172− rcEnclosingSpans = [],
163+ rcEnclosingSpans = [],
173− rcAnns = anns,
164+ rcAnns = anns,
174− rcCanUseBraces = False,
165+ rcCanUseBraces = False
175− rcUseRecDot = recDot
176− }
166+ }
177− sc =
167+ sc = SC
178− SC
179− { scColumn = 0,
168+ { scColumn = 0,
180− scIndent = 0,
181− scBuilder = mempty,
169+ scBuilder = mempty,
182− scSpanStream = sstream,
170+ scSpanStream = sstream,
183− scThisLineSpans = [],
184− scCommentStream = cstream,
171+ scCommentStream = cstream,
185− scPendingComments = [],
172+ scPendingComments = [],
173+ scDirtyLine = False,
186− scRequestedDelimiter = VeryBeginning,
174+ scRequestedDelimiter = VeryBeginning,
187− scSpanMark = Nothing
175+ scLastCommentSpan = Nothing
188− }
176+ }
189
177
190----------------------------------------------------------------------------
178----------------------------------------------------------------------------
191-- Internal functions
179-- Internal functions
192
180
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
181-- | 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
182-- breaks. 'txt' is used to output all sorts of “fixed” bits of syntax like
212-- keywords and pipes @|@ in functional dependencies.
183-- keywords and pipes @|@ in functional dependencies.
@@ -218,15 +189,7 @@ txt ::
218 -- | 'Text' to output
189 -- | 'Text' to output
219 Text ->
190 Text ->
220 R ()
191 R ()
221−txt = spit SimpleText
192+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
193
231-- | Output 'Outputable' fragment of AST. This can be used to output numeric
194-- | Output 'Outputable' fragment of AST. This can be used to output numeric
232-- literals and similar. Everything that doesn't have inner structure but
195-- literals and similar. Everything that doesn't have inner structure but
@@ -235,61 +198,48 @@ atom ::
235 Outputable a =>
198 Outputable a =>
236 a ->
199 a ->
237 R ()
200 R ()
238−atom = spit Atom . T.pack . showOutputable
201+atom = spit True False . T.pack . showOutputable
239
202
240-- | Low-level non-public helper to define 'txt' and 'atom'.
203-- | Low-level non-public helper to define 'txt' and 'atom'.
241spit ::
204spit ::
242− -- | Type of the thing to spit
205+ -- | Should we mark the line as dirty?
243− SpitType ->
206+ Bool ->
207+ -- | Used during outputting of pending comments?
208+ Bool ->
244 -- | 'Text' to output
209 -- | 'Text' to output
245 Text ->
210 Text ->
246 R ()
211 R ()
247−spit _ "" = return ()
212+spit dirty printingComments txt' = do
248−spit stype text = do
249 requestedDel <- R (gets scRequestedDelimiter)
213 requestedDel <- R (gets scRequestedDelimiter)
250− pendingComments <- R (gets scPendingComments)
251− when (stype == InterferingText && not (null pendingComments)) newline
252 case requestedDel of
214 case requestedDel of
253 RequestedNewline -> do
215 RequestedNewline -> do
254 R . modify $ \sc ->
216 R . modify $ \sc ->
255 sc
217 sc
256 { scRequestedDelimiter = RequestedNothing
218 { scRequestedDelimiter = RequestedNothing
257 }
219 }
258− case stype of
220+ if printingComments
259− CommentPart -> newlineRaw
221+ then newlineRaw
260− _ -> newline
222+ else newline
261 _ -> return ()
223 _ -> return ()
262 R $ do
224 R $ do
263 i <- asks rcIndent
225 i <- asks rcIndent
264 c <- gets scColumn
226 c <- gets scColumn
265− closestEnclosing <- listToMaybe <$> asks rcEnclosingSpans
227+ let spaces =
266− let indentedTxt = spaces <> text
228+ if c < i
267− spaces = T.replicate spacesN " "
229+ then T.replicate (i - c) " "
268− spacesN =
269− if c == 0
270− then i
271− else bool 0 1 (requestedDel == RequestedSpace)
230+ else bool mempty " " (requestedDel == RequestedSpace)
231+ indentedTxt = spaces <> txt'
272 modify $ \sc ->
232 modify $ \sc ->
273 sc
233 sc
274 { scBuilder = scBuilder sc <> fromText indentedTxt,
234 { scBuilder = scBuilder sc <> fromText indentedTxt,
275 scColumn = scColumn sc + T.length indentedTxt,
235 scColumn = scColumn sc + T.length indentedTxt,
276− scIndent =
236+ 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,
237 scRequestedDelimiter = RequestedNothing,
288− scSpanMark =
238+ scLastCommentSpan =
289− -- If there are pending comments, do not reset last comment
239+ -- NOTE If there are pending comments, do not reset last comment
290 -- location.
240 -- location.
291− if (stype == CommentPart) || (not . null . scPendingComments) sc
241+ if printingComments || (not . null . scPendingComments) sc
292− then scSpanMark sc
242+ then scLastCommentSpan sc
293 else Nothing
243 else Nothing
294 }
244 }
295
245
@@ -320,22 +270,21 @@ space = R . modify $ \sc ->
320-- hard to output more than one blank newline in a row.
270-- hard to output more than one blank newline in a row.
321newline :: R ()
271newline :: R ()
322newline = do
272newline = do
323− indent <- R (gets scIndent)
324 cs <- reverse <$> R (gets scPendingComments)
273 cs <- reverse <$> R (gets scPendingComments)
325 case cs of
274 case cs of
326 [] -> newlineRaw
275 [] -> newlineRaw
327− ((position, _) : _) -> do
276+ ((position, _, _) : _) -> do
328 case position of
277 case position of
329 OnTheSameLine -> space
278 OnTheSameLine -> space
330 OnNextLine -> newlineRaw
279 OnNextLine -> newlineRaw
331− R . forM_ cs $ \(_, text) ->
280+ R . forM_ cs $ \(_, indent, txt') ->
332 let modRC rc =
281 let modRC rc =
333 rc
282 rc
334 { rcIndent = indent
283 { rcIndent = indent
335 }
284 }
336 R m = do
285 R m = do
337− unless (T.null text) $
286+ unless (T.null txt') $
338− spit CommentPart text
287+ spit False True txt'
339 newlineRaw
288 newlineRaw
340 in local modRC m
289 in local modRC m
341 R . modify $ \sc ->
290 R . modify $ \sc ->
@@ -356,8 +305,7 @@ newlineRaw = R . modify $ \sc ->
356 VeryBeginning -> builderSoFar
305 VeryBeginning -> builderSoFar
357 _ -> builderSoFar <> "\n",
306 _ -> builderSoFar <> "\n",
358 scColumn = 0,
307 scColumn = 0,
359− scIndent = 0,
308+ scDirtyLine = False,
360− scThisLineSpans = [],
361 scRequestedDelimiter = case scRequestedDelimiter sc of
309 scRequestedDelimiter = case scRequestedDelimiter sc of
362 AfterNewline -> RequestedNewline
310 AfterNewline -> RequestedNewline
363 RequestedNewline -> RequestedNewline
311 RequestedNewline -> RequestedNewline
@@ -365,9 +313,10 @@ newlineRaw = R . modify $ \sc ->
365 _ -> AfterNewline
313 _ -> AfterNewline
366 }
314 }
367
315
368−-- | Return 'True' if we should print record dot syntax.
316+-- | Check if the current line is “dirty”, that is, there is something on it
369−useRecordDot :: R Bool
317+-- that can have comments attached to it.
370−useRecordDot = R (asks rcUseRecDot)
318+isLineDirty :: R Bool
319+isLineDirty = R (gets scDirtyLine)
371
320
372-- | Increase indentation level by one indentation step for the inner
321-- | Increase indentation level by one indentation step for the inner
373-- computation. 'inci' should be used when a part of code must be more
322-- computation. 'inci' should be used when a part of code must be more
@@ -384,7 +333,8 @@ inci (R m) = R (local modRC m)
384
333
385-- | Set indentation level for the inner computation equal to current
334-- | Set indentation level for the inner computation equal to current
386-- column. This makes sure that the entire inner block is uniformly
335-- column. This makes sure that the entire inner block is uniformly
387−-- \"shifted\" to the right.
336+-- \"shifted\" to the right. Only works (and makes sense) when enclosing
337+-- layout is multi-line.
388sitcc :: R () -> R ()
338sitcc :: R () -> R ()
389sitcc (R m) = do
339sitcc (R m) = do
390 requestedDel <- R (gets scRequestedDelimiter)
340 requestedDel <- R (gets scRequestedDelimiter)
@@ -392,9 +342,16 @@ sitcc (R m) = do
392 c <- R (gets scColumn)
342 c <- R (gets scColumn)
393 let modRC rc =
343 let modRC rc =
394 rc
344 rc
395− { rcIndent = max i (c + bool 0 1 (requestedDel == RequestedSpace))
345+ { rcIndent = max i c + bool 0 1 (requestedDel == RequestedSpace)
396 }
346 }
347+ vlayout (R m) . R $ do
348+ modify $ \sc ->
349+ sc
350+ { scRequestedDelimiter = case requestedDel of
351+ RequestedSpace -> RequestedNothing
352+ other -> other
353+ }
397− R (local modRC m)
354+ local modRC m
398
355
399-- | Set 'Layout' for internal computation.
356-- | Set 'Layout' for internal computation.
400enterLayout :: Layout -> R () -> R ()
357enterLayout :: Layout -> R () -> R ()
@@ -435,10 +392,11 @@ registerPendingCommentLine ::
435 -- | 'Text' to output
392 -- | 'Text' to output
436 Text ->
393 Text ->
437 R ()
394 R ()
438−registerPendingCommentLine position text = R $ do
395+registerPendingCommentLine position txt' = R $ do
396+ i <- asks rcIndent
439 modify $ \sc ->
397 modify $ \sc ->
440 sc
398 sc
441− { scPendingComments = (position, text) : scPendingComments sc
399+ { scPendingComments = (position, i, txt') : scPendingComments sc
442 }
400 }
443
401
444-- | Drop elements that begin before or at the same place as given
402-- | Drop elements that begin before or at the same place as given
@@ -497,29 +455,6 @@ withEnclosingSpan spn (R m) = R (local modRC m)
497 { rcEnclosingSpans = spn : rcEnclosingSpans rc
455 { rcEnclosingSpans = spn : rcEnclosingSpans rc
498 }
456 }
499
457
500−-- | Get spans on this line so far.
501−thisLineSpans :: R [RealSrcSpan]
502−thisLineSpans = R (gets scThisLineSpans)
503−
504−----------------------------------------------------------------------------
505−-- Stateful markers
506−
507−-- | An auxiliary marker for keeping track of last output element.
508−data SpanMark
509− = -- | Haddock comment
510− HaddockSpan HaddockStyle RealSrcSpan
511− | -- | Non-haddock comment
512− CommentSpan RealSrcSpan
513− | -- | A statement in a do-block and such span
514− StatementSpan RealSrcSpan
515−
516−-- | Project 'RealSrcSpan' from 'SpanMark'.
517−spanMarkSpan :: SpanMark -> RealSrcSpan
518−spanMarkSpan = \case
519− HaddockSpan _ s -> s
520− CommentSpan s -> s
521− StatementSpan s -> s
522−
523-- | Haddock string style.
458-- | Haddock string style.
524data HaddockStyle
459data HaddockStyle
525 = -- | @-- |@
460 = -- | @-- |@
@@ -532,18 +467,20 @@ data HaddockStyle
532 Named String
467 Named String
533
468
534-- | Set span of last output comment.
469-- | Set span of last output comment.
535−setSpanMark ::
470+setLastCommentSpan ::
536− -- | Span mark to set
471+ -- | 'HaddockStyle' or 'Nothing' if it's a non-Haddock comment
537− SpanMark ->
472+ Maybe HaddockStyle ->
473+ -- | Location of last printed comment
474+ RealSrcSpan ->
538 R ()
475 R ()
539−setSpanMark spnMark = R . modify $ \sc ->
476+setLastCommentSpan mhStyle spn = R . modify $ \sc ->
540 sc
477 sc
541− { scSpanMark = Just spnMark
478+ { scLastCommentSpan = Just (mhStyle, spn)
542 }
479 }
543
480
544-- | Get span of last output comment.
481-- | Get span of last output comment.
545−getSpanMark :: R (Maybe SpanMark)
482+getLastCommentSpan :: R (Maybe (Maybe HaddockStyle, RealSrcSpan))
546−getSpanMark = R (gets scSpanMark)
483+getLastCommentSpan = R (gets scLastCommentSpan)
547
484
548----------------------------------------------------------------------------
485----------------------------------------------------------------------------
549-- Annotations
486-- Annotations
@@ -567,7 +504,7 @@ dontUseBraces (R r) = R (local (\i -> i {rcCanUseBraces = False}) r)
567
504
568-- | Return 'True' if we can use braces in this context.
505-- | Return 'True' if we can use braces in this context.
569canUseBraces :: R Bool
506canUseBraces :: R Bool
570−canUseBraces = R (asks rcCanUseBraces)
507+canUseBraces = R $ asks rcCanUseBraces
571
508
572----------------------------------------------------------------------------
509----------------------------------------------------------------------------
573-- Constants
510-- Constants
src/Ormolu/Printer/Meat/Common.hs+22−25
@@ -17,12 +17,14 @@ where
17
17
18import Control.Monad
18import Control.Monad
19import Data.List (isPrefixOf)
19import Data.List (isPrefixOf)
20+import Data.Maybe (isJust)
20import qualified Data.Text as T
21import qualified Data.Text as T
21import GHC hiding (GhcPs, IE)
22import GHC hiding (GhcPs, IE)
22import Name (nameStableString)
23import Name (nameStableString)
23import OccName (OccName (..))
24import OccName (OccName (..))
24import Ormolu.Printer.Combinators
25import Ormolu.Printer.Combinators
25import Ormolu.Utils
26import Ormolu.Utils
27+import RdrName (RdrName (..))
26
28
27-- | Data and type family style.
29-- | Data and type family style.
28data FamilyStyle
30data FamilyStyle
@@ -74,10 +76,10 @@ p_rdrName l@(L spn _) = located l $ \x -> do
74 Qual mname occName ->
76 Qual mname occName ->
75 p_qualName mname occName
77 p_qualName mname occName
76 Orig _ occName ->
78 Orig _ occName ->
77− -- This is used when GHC generates code that will be fed into
79+ -- NOTE This is used when GHC generates code that will be fed
78− -- the renamer (e.g. from deriving clauses), but where we want
80+ -- into the renamer (e.g. from deriving clauses), but where we
79− -- to say that something comes from given module which is not
81+ -- want to say that something comes from given module which is
80− -- specified in the source code, e.g. @Prelude.map@.
82+ -- not specified in the source code, e.g. @Prelude.map@.
81 --
83 --
82 -- My current understanding is that the provided module name
84 -- My current understanding is that the provided module name
83 -- serves no purpose for us and can be safely ignored.
85 -- serves no purpose for us and can be safely ignored.
@@ -97,9 +99,9 @@ doesNotNeedExtraParens :: RdrName -> Bool
97doesNotNeedExtraParens = \case
99doesNotNeedExtraParens = \case
98 Exact name ->
100 Exact name ->
99 let s = nameStableString name
101 let s = nameStableString name
100− in -- I'm not sure this "stable string" is stable enough, but it looks
102+ in -- NOTE I'm not sure this "stable string" is stable enough, but it looks
101− -- like this is the most robust way to tell if we're looking at
103+ -- like this is the most robust way to tell if we're looking at exactly
102− -- exactly this piece of built-in syntax.
104+ -- this piece of built-in syntax.
103 ("$ghc-prim$GHC.Tuple$" `isPrefixOf` s)
105 ("$ghc-prim$GHC.Tuple$" `isPrefixOf` s)
104 || ("$ghc-prim$GHC.Types$[]" `isPrefixOf` s)
106 || ("$ghc-prim$GHC.Types$[]" `isPrefixOf` s)
105 _ -> False
107 _ -> False
@@ -114,14 +116,14 @@ p_qualName mname occName = do
114p_infixDefHelper ::
116p_infixDefHelper ::
115 -- | Whether to format in infix style
117 -- | Whether to format in infix style
116 Bool ->
118 Bool ->
117− -- | Whether to bump indentation for arguments
119+ -- | Indentation-bumping wrapper
118− Bool ->
120+ (R () -> R ()) ->
119 -- | How to print the operator\/name
121 -- | How to print the operator\/name
120 R () ->
122 R () ->
121 -- | How to print the arguments
123 -- | How to print the arguments
122 [R ()] ->
124 [R ()] ->
123 R ()
125 R ()
124−p_infixDefHelper isInfix indentArgs name args =
126+p_infixDefHelper isInfix inci' name args =
125 case (isInfix, args) of
127 case (isInfix, args) of
126 (True, p0 : p1 : ps) -> do
128 (True, p0 : p1 : ps) -> do
127 let parens' =
129 let parens' =
@@ -131,18 +133,18 @@ p_infixDefHelper isInfix indentArgs name args =
131 parens' $ do
133 parens' $ do
132 p0
134 p0
133 breakpoint
135 breakpoint
134− inci . sitcc $ do
136+ inci $ sitcc $ do
135 name
137 name
136 space
138 space
137 p1
139 p1
138− unless (null ps) . inciIf indentArgs $ do
140+ unless (null ps) . inci' $ do
139 breakpoint
141 breakpoint
140 sitcc (sep breakpoint sitcc ps)
142 sitcc (sep breakpoint sitcc ps)
141 (_, ps) -> do
143 (_, ps) -> do
142 name
144 name
143 unless (null ps) $ do
145 unless (null ps) $ do
144 breakpoint
146 breakpoint
145− inciIf indentArgs $ sitcc (sep breakpoint sitcc args)
147+ inci' $ sitcc (sep breakpoint sitcc args)
146
148
147-- | Print a Haddock.
149-- | Print a Haddock.
148p_hsDocString ::
150p_hsDocString ::
@@ -154,22 +156,17 @@ p_hsDocString ::
154 LHsDocString ->
156 LHsDocString ->
155 R ()
157 R ()
156p_hsDocString hstyle needsNewline (L l str) = do
158p_hsDocString hstyle needsNewline (L l str) = do
157− let isCommentSpan = \case
159+ goesAfterComment <- isJust <$> getLastCommentSpan
158− HaddockSpan _ _ -> True
159− CommentSpan _ -> True
160− _ -> False
161− goesAfterComment <- maybe False isCommentSpan <$> getSpanMark
162 -- Make sure the Haddock is separated by a newline from other comments.
160 -- Make sure the Haddock is separated by a newline from other comments.
163 when goesAfterComment newline
161 when goesAfterComment newline
164 forM_ (zip (splitDocString str) (True : repeat False)) $ \(x, isFirst) -> do
162 forM_ (zip (splitDocString str) (True : repeat False)) $ \(x, isFirst) -> do
165 if isFirst
163 if isFirst
166 then case hstyle of
164 then case hstyle of
167− Pipe -> txt "-- |"
165+ Pipe -> txt "-- |" >> space
168− Caret -> txt "-- ^"
166+ Caret -> txt "-- ^" >> space
169− Asterisk n -> txt ("-- " <> T.replicate n "*")
167+ Asterisk n -> txt ("-- " <> T.replicate n "*") >> space
170 Named name -> p_hsDocName name
168 Named name -> p_hsDocName name
171− else newline >> txt "--"
169+ else newline >> txt "--" >> space
172− space
173 unless (T.null x) (txt x)
170 unless (T.null x) (txt x)
174 when needsNewline newline
171 when needsNewline newline
175 case l of
172 case l of
@@ -177,8 +174,8 @@ p_hsDocString hstyle needsNewline (L l str) = do
177 -- It's often the case that the comment itself doesn't have a span
174 -- It's often the case that the comment itself doesn't have a span
178 -- attached to it and instead its location can be obtained from
175 -- attached to it and instead its location can be obtained from
179 -- nearest enclosing span.
176 -- nearest enclosing span.
180− getEnclosingSpan (const True) >>= mapM_ (setSpanMark . HaddockSpan hstyle)
177+ getEnclosingSpan (const True) >>= mapM_ (setLastCommentSpan (Just hstyle))
181− RealSrcSpan spn -> setSpanMark (HaddockSpan hstyle spn)
178+ RealSrcSpan spn -> setLastCommentSpan (Just hstyle) spn
182
179
183-- | Print anchor of named doc section.
180-- | Print anchor of named doc section.
184p_hsDocName :: String -> R ()
181p_hsDocName :: String -> R ()
src/Ormolu/Printer/Meat/Declaration.hs+111−176
@@ -7,14 +7,14 @@
7-- | Rendering of declarations.
7-- | Rendering of declarations.
8module Ormolu.Printer.Meat.Declaration
8module Ormolu.Printer.Meat.Declaration
9 ( p_hsDecls,
9 ( p_hsDecls,
10− p_hsDeclsRespectGrouping,
10+ hasSeparatedDecls,
11 )
11 )
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
17−import GHC hiding (InlinePragma)
17+import GHC
18import OccName (occNameFS)
18import OccName (occNameFS)
19import Ormolu.Printer.Combinators
19import Ormolu.Printer.Combinators
20import Ormolu.Printer.Meat.Common
20import Ormolu.Printer.Meat.Common
@@ -34,57 +34,25 @@ import Ormolu.Printer.Meat.Declaration.Value
34import Ormolu.Printer.Meat.Declaration.Warning
34import Ormolu.Printer.Meat.Declaration.Warning
35import Ormolu.Printer.Meat.Type
35import Ormolu.Printer.Meat.Type
36import Ormolu.Utils
36import Ormolu.Utils
37−
37+import RdrName (rdrNameOcc)
38−data UserGrouping
39− = -- | Always put newlines where we think they should be
40− Disregard
41− | -- | Respect user preferences regarding grouping
42− Respect
43− deriving (Eq, Show)
44
38
45p_hsDecls :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
39p_hsDecls :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
46−p_hsDecls = p_hsDecls' Disregard
47−
48−-- | Like 'p_hsDecls' but respects user choices regarding grouping. If the
49−-- user omits newlines between declarations, we also omit them in most
50−-- cases, except when said declarations have associated Haddocks.
51−--
52−-- Does some normalization (compress subsequent newlines into a single one)
53−p_hsDeclsRespectGrouping :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
54−p_hsDeclsRespectGrouping = p_hsDecls' Respect
55−
56−p_hsDecls' :: UserGrouping -> FamilyStyle -> [LHsDecl GhcPs] -> R ()
57−p_hsDecls' grouping style decls =
58− sepSemi id $
40+p_hsDecls style decls = sepSemi id $
59− -- Return a list of rendered declarations, adding a newline to separate
41+ -- Return a list of rendered declarations, adding a newline to separate
60− -- groups.
42+ -- groups.
61− case groupDecls decls of
43+ case groupDecls decls of
62− [] -> []
44+ [] -> []
63− (x : xs) -> renderGroup x ++ concat (zipWith renderGroupWithPrev (x : xs) xs)
45+ (x : xs) ->
46+ NE.toList (renderGroup x)
47+ ++ concatMap (NE.toList . separateGroup . renderGroup) xs
64 where
48 where
65− renderGroup = NE.toList . fmap (located' $ dontUseBraces . p_hsDecl style)
49+ renderGroup = fmap (located' $ dontUseBraces . p_hsDecl style)
66− renderGroupWithPrev prev curr =
50+ separateGroup (x :| xs) = (breakpoint' >> x) :| xs
67− -- We can omit a blank line when the user didn't add one, but we must
68− -- ensure we always add blank lines around documented declarations
69− case grouping of
70− Disregard ->
71− breakpoint : renderGroup curr
72− Respect ->
73− if separatedByBlankNE getLoc prev curr
74− || isDocumented prev
75− || isDocumented curr
76− then breakpoint : renderGroup curr
77− else renderGroup curr
78−
79−-- | Is a declaration group documented?
80−isDocumented :: NonEmpty (LHsDecl GhcPs) -> Bool
81−isDocumented = any (isHaddock . unLoc)
82− where
83− isHaddock DocNext = True
84− isHaddock DocPrev = True
85− isHaddock _ = False
86
51
87-- | Group relevant declarations together.
52-- | Group relevant declarations together.
53+--
54+-- Add a declaration to a group iff it is relevant to either the first or
55+-- the last declaration of the group.
88groupDecls :: [LHsDecl GhcPs] -> [NonEmpty (LHsDecl GhcPs)]
56groupDecls :: [LHsDecl GhcPs] -> [NonEmpty (LHsDecl GhcPs)]
89groupDecls [] = []
57groupDecls [] = []
90groupDecls (l@(L _ DocNext) : xs) =
58groupDecls (l@(L _ DocNext) : xs) =
@@ -93,40 +61,44 @@ groupDecls (l@(L _ DocNext) : xs) =
93 case groupDecls xs of
61 case groupDecls xs of
94 [] -> [l :| []]
62 [] -> [l :| []]
95 (x : xs') -> (l <| x) : xs'
63 (x : xs') -> (l <| x) : xs'
96−groupDecls (header : xs) =
64+groupDecls (lhdr : xs) =
97− let (grp, rest) = flip span (zip (header : xs) xs) $ \(previous, current) ->
65+ let -- Pick the first decl as the group header
66+ hdr = unLoc lhdr
67+ -- Zip rest of the decls with their previous decl
68+ zipped = zip (lhdr : xs) xs
69+ -- Pick decls from the tail if they are relevant to the group header
70+ -- or the previous decl.
71+ (grp, rest) = flip span zipped $ \(L _ prev, L _ cur) ->
98− let relevantToHdr = groupedDecls header current
72+ let relevantToHdr = groupedDecls hdr cur
99− relevantToPrev = groupedDecls previous current
73+ relevantToPrev = groupedDecls prev cur
100− isDeclSeries = declSeries previous current
101− in isDeclSeries || relevantToHdr || relevantToPrev
74+ in relevantToHdr || relevantToPrev
102− in (header :| map snd grp) : groupDecls (map snd rest)
75+ in (lhdr :| map snd grp) : groupDecls (map snd rest)
103
76
104p_hsDecl :: FamilyStyle -> HsDecl GhcPs -> R ()
77p_hsDecl :: FamilyStyle -> HsDecl GhcPs -> R ()
105p_hsDecl style = \case
78p_hsDecl style = \case
106− TyClD NoExtField x -> p_tyClDecl style x
79+ TyClD NoExt x -> p_tyClDecl style x
107− ValD NoExtField x -> p_valDecl x
80+ ValD NoExt x -> p_valDecl x
108− SigD NoExtField x -> p_sigDecl x
81+ SigD NoExt x -> p_sigDecl x
109− InstD NoExtField x -> p_instDecl style x
82+ InstD NoExt x -> p_instDecl style x
110− DerivD NoExtField x -> p_derivDecl x
83+ DerivD NoExt x -> p_derivDecl x
111− DefD NoExtField x -> p_defaultDecl x
84+ DefD NoExt x -> p_defaultDecl x
112− ForD NoExtField x -> p_foreignDecl x
85+ ForD NoExt x -> p_foreignDecl x
113− WarningD NoExtField x -> p_warnDecls x
86+ WarningD NoExt x -> p_warnDecls x
114− AnnD NoExtField x -> p_annDecl x
87+ AnnD NoExt x -> p_annDecl x
115− RuleD NoExtField x -> p_ruleDecls x
88+ RuleD NoExt x -> p_ruleDecls x
116− SpliceD NoExtField x -> p_spliceDecl x
89+ SpliceD NoExt x -> p_spliceDecl x
117− DocD NoExtField docDecl ->
90+ DocD NoExt docDecl ->
118 case docDecl of
91 case docDecl of
119 DocCommentNext str -> p_hsDocString Pipe False (noLoc str)
92 DocCommentNext str -> p_hsDocString Pipe False (noLoc str)
120 DocCommentPrev str -> p_hsDocString Caret False (noLoc str)
93 DocCommentPrev str -> p_hsDocString Caret False (noLoc str)
121 DocCommentNamed name str -> p_hsDocString (Named name) False (noLoc str)
94 DocCommentNamed name str -> p_hsDocString (Named name) False (noLoc str)
122 DocGroup n str -> p_hsDocString (Asterisk n) False (noLoc str)
95 DocGroup n str -> p_hsDocString (Asterisk n) False (noLoc str)
123− RoleAnnotD NoExtField x -> p_roleAnnot x
96+ RoleAnnotD NoExt x -> p_roleAnnot x
124− KindSigD NoExtField s -> p_standaloneKindSig s
97+ XHsDecl _ -> notImplemented "XHsDecl"
125− XHsDecl x -> noExtCon x
126
98
127p_tyClDecl :: FamilyStyle -> TyClDecl GhcPs -> R ()
99p_tyClDecl :: FamilyStyle -> TyClDecl GhcPs -> R ()
128p_tyClDecl style = \case
100p_tyClDecl style = \case
129− FamDecl NoExtField x -> p_famDecl style x
101+ FamDecl NoExt x -> p_famDecl style x
130 SynDecl {..} -> p_synDecl tcdLName tcdFixity tcdTyVars tcdRhs
102 SynDecl {..} -> p_synDecl tcdLName tcdFixity tcdTyVars tcdRhs
131 DataDecl {..} ->
103 DataDecl {..} ->
132 p_dataDecl
104 p_dataDecl
@@ -147,65 +119,39 @@ p_tyClDecl style = \case
147 tcdATs
119 tcdATs
148 tcdATDefs
120 tcdATDefs
149 tcdDocs
121 tcdDocs
150− XTyClDecl x -> noExtCon x
122+ XTyClDecl {} -> notImplemented "XTyClDecl"
151
123
152p_instDecl :: FamilyStyle -> InstDecl GhcPs -> R ()
124p_instDecl :: FamilyStyle -> InstDecl GhcPs -> R ()
153p_instDecl style = \case
125p_instDecl style = \case
154− ClsInstD NoExtField x -> p_clsInstDecl x
126+ ClsInstD NoExt x -> p_clsInstDecl x
155− TyFamInstD NoExtField x -> p_tyFamInstDecl style x
127+ TyFamInstD NoExt x -> p_tyFamInstDecl style x
156− DataFamInstD NoExtField x -> p_dataFamInstDecl style x
128+ DataFamInstD NoExt x -> p_dataFamInstDecl style x
157− XInstDecl x -> noExtCon x
129+ XInstDecl _ -> notImplemented "XInstDecl"
158
130
159p_derivDecl :: DerivDecl GhcPs -> R ()
131p_derivDecl :: DerivDecl GhcPs -> R ()
160p_derivDecl = \case
132p_derivDecl = \case
161− d@DerivDecl {} -> p_standaloneDerivDecl d
133+ d@DerivDecl {..} -> p_standaloneDerivDecl d
162− XDerivDecl x -> noExtCon x
134+ XDerivDecl _ -> notImplemented "XDerivDecl standalone deriving"
163
135
164-- | Determine if these declarations should be grouped together.
136-- | Determine if these declarations should be grouped together.
165groupedDecls ::
137groupedDecls ::
166− LHsDecl GhcPs ->
138+ HsDecl GhcPs ->
167− LHsDecl GhcPs ->
168− Bool
169−groupedDecls (L l_x x') (L l_y y') =
170− case (x', y') of
171− (TypeSignature ns, FunctionBody ns') -> ns `intersects` ns'
172− (TypeSignature ns, DefaultSignature ns') -> ns `intersects` ns'
173− (DefaultSignature ns, TypeSignature ns') -> ns `intersects` ns'
174− (DefaultSignature ns, FunctionBody ns') -> ns `intersects` ns'
175− (x, FunctionBody ns) | Just ns' <- isPragma x -> ns `intersects` ns'
176− (FunctionBody ns, x) | Just ns' <- isPragma x -> ns `intersects` ns'
177− (x, DataDeclaration n) | Just ns <- isPragma x -> n `elem` ns
178− (DataDeclaration n, x)
179− | Just ns <- isPragma x ->
180− let f = occNameFS . rdrNameOcc in f n `elem` map f ns
181− (x, y)
182− | Just ns <- isPragma x,
183− Just ns' <- isPragma y ->
184− ns `intersects` ns'
185− (x, TypeSignature ns) | Just ns' <- isPragma x -> ns `intersects` ns'
186− (TypeSignature ns, x) | Just ns' <- isPragma x -> ns `intersects` ns'
187− (PatternSignature ns, Pattern n) -> n `elem` ns
188− (KindSignature n, DataDeclaration n') -> n == n'
189− (KindSignature n, ClassDeclaration n') -> n == n'
190− (KindSignature n, FamilyDeclaration n') -> n == n'
191− -- Special case for TH splices, we look at locations
192− (Splice, Splice) -> not (separatedByBlank id l_x l_y)
193− -- This looks only at Haddocks, normal comments are handled elsewhere
194− (DocNext, _) -> True
195− (_, DocPrev) -> True
196− _ -> False
197−
198−-- | Detect declaration series that should not have blanks between them.
199−declSeries ::
200− LHsDecl GhcPs ->
201− LHsDecl GhcPs ->
139+ HsDecl GhcPs ->
202 Bool
140 Bool
203−declSeries (L _ x) (L _ y) =
141+groupedDecls (TypeSignature ns) (FunctionBody ns') = ns `intersects` ns'
204− case (x, y) of
142+groupedDecls x (FunctionBody ns) | Just ns' <- isPragma x = ns `intersects` ns'
205− ( SigD NoExtField (TypeSig NoExtField _ _),
143+groupedDecls (FunctionBody ns) x | Just ns' <- isPragma x = ns `intersects` ns'
206− SigD NoExtField (TypeSig NoExtField _ _)
144+groupedDecls x (DataDeclaration n) | Just ns <- isPragma x = n `elem` ns
207− ) -> True
145+groupedDecls (DataDeclaration n) x
146+ | Just ns <- isPragma x =
147+ let f = occNameFS . rdrNameOcc in f n `elem` map f ns
148+groupedDecls x y | Just ns <- isPragma x, Just ns' <- isPragma y = ns `intersects` ns'
149+groupedDecls x (TypeSignature ns) | Just ns' <- isPragma x = ns `intersects` ns'
150+groupedDecls (TypeSignature ns) x | Just ns' <- isPragma x = ns `intersects` ns'
151+groupedDecls (PatternSignature ns) (Pattern n) = n `elem` ns
152+groupedDecls DocNext _ = True
153+groupedDecls _ DocPrev = True
208− _ -> False
154+groupedDecls _ _ = False
209
155
210intersects :: Ord a => [a] -> [a] -> Bool
156intersects :: Ord a => [a] -> [a] -> Bool
211intersects a b = go (sort a) (sort b)
157intersects a b = go (sort a) (sort b)
@@ -218,6 +164,13 @@ intersects a b = go (sort a) (sort b)
218 | x > y = go (x : xs) ys
164 | x > y = go (x : xs) ys
219 | otherwise = True
165 | otherwise = True
220
166
167+-- | Checks if given list of declarations contain a pair which should
168+-- be separated by a blank line.
169+hasSeparatedDecls :: [LHsDecl GhcPs] -> Bool
170+hasSeparatedDecls xs = case groupDecls xs of
171+ _ : _ : _ -> True
172+ _ -> False
173+
221isPragma ::
174isPragma ::
222 HsDecl GhcPs ->
175 HsDecl GhcPs ->
223 Maybe [RdrName]
176 Maybe [RdrName]
@@ -230,11 +183,6 @@ isPragma = \case
230 WarningPragma n -> Just n
183 WarningPragma n -> Just n
231 _ -> Nothing
184 _ -> Nothing
232
185
233−-- Declarations that do not refer to names
234−
235−pattern Splice :: HsDecl GhcPs
236−pattern Splice <- SpliceD NoExtField (SpliceDecl NoExtField _ _)
237−
238-- Declarations referring to a single name
186-- Declarations referring to a single name
239
187
240pattern
188pattern
@@ -244,84 +192,71 @@ pattern
244 AnnTypePragma,
192 AnnTypePragma,
245 AnnValuePragma,
193 AnnValuePragma,
246 Pattern,
194 Pattern,
247− DataDeclaration,
195+ DataDeclaration ::
248− ClassDeclaration,
249− KindSignature,
250− FamilyDeclaration ::
251 RdrName -> HsDecl GhcPs
196 RdrName -> HsDecl GhcPs
252−pattern InlinePragma n <- SigD NoExtField (InlineSig NoExtField (L _ n) _)
197+pattern InlinePragma n <- SigD NoExt (InlineSig NoExt (L _ n) _)
253−pattern SpecializePragma n <- SigD NoExtField (SpecSig NoExtField (L _ n) _ _)
198+pattern SpecializePragma n <- SigD NoExt (SpecSig NoExt (L _ n) _ _)
254−pattern SCCPragma n <- SigD NoExtField (SCCFunSig NoExtField _ (L _ n) _)
199+pattern SCCPragma n <- SigD NoExt (SCCFunSig NoExt _ (L _ n) _)
255−pattern AnnTypePragma n <- AnnD NoExtField (HsAnnotation NoExtField _ (TypeAnnProvenance (L _ n)) _)
200+pattern AnnTypePragma n <- AnnD NoExt (HsAnnotation NoExt _ (TypeAnnProvenance (L _ n)) _)
256−pattern AnnValuePragma n <- AnnD NoExtField (HsAnnotation NoExtField _ (ValueAnnProvenance (L _ n)) _)
201+pattern AnnValuePragma n <- AnnD NoExt (HsAnnotation NoExt _ (ValueAnnProvenance (L _ n)) _)
257−pattern Pattern n <- ValD NoExtField (PatSynBind NoExtField (PSB _ (L _ n) _ _ _))
202+pattern Pattern n <- ValD NoExt (PatSynBind NoExt (PSB _ (L _ n) _ _ _))
258−pattern DataDeclaration n <- TyClD NoExtField (DataDecl NoExtField (L _ n) _ _ _)
203+pattern DataDeclaration n <- TyClD NoExt (DataDecl NoExt (L _ n) _ _ _)
259−pattern ClassDeclaration n <- TyClD NoExtField (ClassDecl NoExtField _ (L _ n) _ _ _ _ _ _ _ _)
260−pattern KindSignature n <- KindSigD NoExtField (StandaloneKindSig NoExtField (L _ n) _)
261−pattern FamilyDeclaration n <- TyClD NoExtField (FamDecl NoExtField (FamilyDecl NoExtField _ (L _ n) _ _ _ _))
262
204
263-- Declarations which can refer to multiple names
205-- Declarations which can refer to multiple names
264
206
265pattern
207pattern
266 TypeSignature,
208 TypeSignature,
267− DefaultSignature,
268 FunctionBody,
209 FunctionBody,
269 PatternSignature,
210 PatternSignature,
270 WarningPragma ::
211 WarningPragma ::
271 [RdrName] -> HsDecl GhcPs
212 [RdrName] -> HsDecl GhcPs
272pattern TypeSignature n <- (sigRdrNames -> Just n)
213pattern TypeSignature n <- (sigRdrNames -> Just n)
273−pattern DefaultSignature n <- (defSigRdrNames -> Just n)
274pattern FunctionBody n <- (funRdrNames -> Just n)
214pattern FunctionBody n <- (funRdrNames -> Just n)
275pattern PatternSignature n <- (patSigRdrNames -> Just n)
215pattern PatternSignature n <- (patSigRdrNames -> Just n)
276pattern WarningPragma n <- (warnSigRdrNames -> Just n)
216pattern WarningPragma n <- (warnSigRdrNames -> Just n)
277
217
278pattern DocNext, DocPrev :: HsDecl GhcPs
218pattern DocNext, DocPrev :: HsDecl GhcPs
279−pattern DocNext <- (DocD NoExtField (DocCommentNext _))
219+pattern DocNext <- (DocD NoExt (DocCommentNext _))
280−pattern DocPrev <- (DocD NoExtField (DocCommentPrev _))
220+pattern DocPrev <- (DocD NoExt (DocCommentPrev _))
281
221
282sigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
222sigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
283−sigRdrNames (SigD NoExtField (TypeSig NoExtField ns _)) = Just $ map unLoc ns
223+sigRdrNames (SigD NoExt (TypeSig NoExt ns _)) = Just $ map unLoc ns
284−sigRdrNames (SigD NoExtField (ClassOpSig NoExtField _ ns _)) = Just $ map unLoc ns
224+sigRdrNames (SigD NoExt (ClassOpSig NoExt _ ns _)) = Just $ map unLoc ns
285−sigRdrNames (SigD NoExtField (PatSynSig NoExtField ns _)) = Just $ map unLoc ns
225+sigRdrNames (SigD NoExt (PatSynSig NoExt ns _)) = Just $ map unLoc ns
286sigRdrNames _ = Nothing
226sigRdrNames _ = Nothing
287
227
288−defSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
289−defSigRdrNames (SigD NoExtField (ClassOpSig NoExtField True ns _)) = Just $ map unLoc ns
290−defSigRdrNames _ = Nothing
291−
292funRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
228funRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
293−funRdrNames (ValD NoExtField (FunBind NoExtField (L _ n) _ _ _)) = Just [n]
229+funRdrNames (ValD NoExt (FunBind NoExt (L _ n) _ _ _)) = Just [n]
294−funRdrNames (ValD NoExtField (PatBind NoExtField (L _ n) _ _)) = Just $ patBindNames n
230+funRdrNames (ValD NoExt (PatBind NoExt (L _ n) _ _)) = Just $ patBindNames n
295funRdrNames _ = Nothing
231funRdrNames _ = Nothing
296
232
297patSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
233patSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
298−patSigRdrNames (SigD NoExtField (PatSynSig NoExtField ns _)) = Just $ map unLoc ns
234+patSigRdrNames (SigD NoExt (PatSynSig NoExt ns _)) = Just $ map unLoc ns
299patSigRdrNames _ = Nothing
235patSigRdrNames _ = Nothing
300
236
301warnSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
237warnSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
302−warnSigRdrNames (WarningD NoExtField (Warnings NoExtField _ ws)) = Just $
238+warnSigRdrNames (WarningD NoExt (Warnings NoExt _ ws)) = Just $ flip concatMap ws $ \case
303− flip concatMap ws $ \case
304− L _ (Warning NoExtField ns _) -> map unLoc ns
239+ L _ (Warning NoExt ns _) -> map unLoc ns
305− L _ (XWarnDecl x) -> noExtCon x
240+ L _ (XWarnDecl NoExt) -> []
306warnSigRdrNames _ = Nothing
241warnSigRdrNames _ = Nothing
307
242
308patBindNames :: Pat GhcPs -> [RdrName]
243patBindNames :: Pat GhcPs -> [RdrName]
309−patBindNames (TuplePat NoExtField ps _) = concatMap (patBindNames . unLoc) ps
244+patBindNames (TuplePat NoExt ps _) = concatMap (patBindNames . unLoc) ps
310−patBindNames (VarPat NoExtField (L _ n)) = [n]
245+patBindNames (VarPat NoExt (L _ n)) = [n]
311−patBindNames (WildPat NoExtField) = []
246+patBindNames (WildPat NoExt) = []
312−patBindNames (LazyPat NoExtField (L _ p)) = patBindNames p
247+patBindNames (LazyPat NoExt (L _ p)) = patBindNames p
313−patBindNames (BangPat NoExtField (L _ p)) = patBindNames p
248+patBindNames (BangPat NoExt (L _ p)) = patBindNames p
314−patBindNames (ParPat NoExtField (L _ p)) = patBindNames p
249+patBindNames (ParPat NoExt (L _ p)) = patBindNames p
315−patBindNames (ListPat NoExtField ps) = concatMap (patBindNames . unLoc) ps
250+patBindNames (ListPat NoExt ps) = concatMap (patBindNames . unLoc) ps
316−patBindNames (AsPat NoExtField (L _ n) (L _ p)) = n : patBindNames p
251+patBindNames (AsPat NoExt (L _ n) (L _ p)) = n : patBindNames p
317−patBindNames (SumPat NoExtField (L _ p) _ _) = patBindNames p
252+patBindNames (SumPat NoExt (L _ p) _ _) = patBindNames p
318−patBindNames (ViewPat NoExtField _ (L _ p)) = patBindNames p
253+patBindNames (ViewPat NoExt _ (L _ p)) = patBindNames p
319−patBindNames (SplicePat NoExtField _) = []
254+patBindNames (SplicePat NoExt _) = []
320−patBindNames (LitPat NoExtField _) = []
255+patBindNames (LitPat NoExt _) = []
321−patBindNames (SigPat _ (L _ p) _) = patBindNames p
256+patBindNames (SigPat _ (L _ p)) = patBindNames p
322−patBindNames (NPat NoExtField _ _ _) = []
257+patBindNames (NPat NoExt _ _ _) = []
323−patBindNames (NPlusKPat NoExtField (L _ n) _ _ _ _) = [n]
258+patBindNames (NPlusKPat NoExt (L _ n) _ _ _ _) = [n]
324patBindNames (ConPatIn _ d) = concatMap (patBindNames . unLoc) (hsConPatArgs d)
259patBindNames (ConPatIn _ d) = concatMap (patBindNames . unLoc) (hsConPatArgs d)
325−patBindNames ConPatOut {} = notImplemented "ConPatOut" -- created by renamer
260+patBindNames (ConPatOut _ _ _ _ _ _ _) = notImplemented "ConPatOut" -- created by renamer
326−patBindNames (CoPat NoExtField _ p _) = patBindNames p
261+patBindNames (CoPat NoExt _ p _) = patBindNames p
327−patBindNames (XPat x) = noExtCon x
262+patBindNames (XPat NoExt) = notImplemented "XPat"
src/Ormolu/Printer/Meat/Declaration.hs-boot+3−2
@@ -1,6 +1,6 @@
1module Ormolu.Printer.Meat.Declaration
1module Ormolu.Printer.Meat.Declaration
2 ( p_hsDecls,
2 ( p_hsDecls,
3− p_hsDeclsRespectGrouping,
3+ hasSeparatedDecls,
4 )
4 )
5where
5where
6
6
@@ -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−p_hsDeclsRespectGrouping :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
12+
13+hasSeparatedDecls :: [LHsDecl GhcPs] -> Bool
src/Ormolu/Printer/Meat/Declaration/Annotation.hs+3−2
@@ -10,14 +10,15 @@ import GHC
10import Ormolu.Printer.Combinators
10import Ormolu.Printer.Combinators
11import Ormolu.Printer.Meat.Common
11import Ormolu.Printer.Meat.Common
12import Ormolu.Printer.Meat.Declaration.Value
12import Ormolu.Printer.Meat.Declaration.Value
13+import Ormolu.Utils
13
14
14p_annDecl :: AnnDecl GhcPs -> R ()
15p_annDecl :: AnnDecl GhcPs -> R ()
15p_annDecl = \case
16p_annDecl = \case
16− HsAnnotation NoExtField _ annProv expr -> pragma "ANN" . inci $ do
17+ HsAnnotation NoExt _ annProv expr -> pragma "ANN" . inci $ do
17 p_annProv annProv
18 p_annProv annProv
18 breakpoint
19 breakpoint
19 located expr p_hsExpr
20 located expr p_hsExpr
20− XAnnDecl x -> noExtCon x
21+ XAnnDecl {} -> notImplemented "XAnnDecl"
21
22
22p_annProv :: AnnProvenance (IdP GhcPs) -> R ()
23p_annProv :: AnnProvenance (IdP GhcPs) -> R ()
23p_annProv = \case
24p_annProv = \case
src/Ormolu/Printer/Meat/Declaration/Class.hs+38−26
@@ -12,12 +12,15 @@ import Class
12import Control.Arrow
12import Control.Arrow
13import Control.Monad
13import Control.Monad
14import Data.Foldable
14import Data.Foldable
15−import Data.List (sortOn)
15+import Data.List (sortBy)
16+import Data.Ord (comparing)
16import GHC
17import GHC
17import Ormolu.Printer.Combinators
18import Ormolu.Printer.Combinators
18import Ormolu.Printer.Meat.Common
19import Ormolu.Printer.Meat.Common
19import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration
20import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration
20import Ormolu.Printer.Meat.Type
21import Ormolu.Printer.Meat.Type
22+import Ormolu.Utils
23+import RdrName (RdrName (..))
21
24
22p_classDecl ::
25p_classDecl ::
23 LHsContext GhcPs ->
26 LHsContext GhcPs ->
@@ -28,47 +31,49 @@ p_classDecl ::
28 [LSig GhcPs] ->
31 [LSig GhcPs] ->
29 LHsBinds GhcPs ->
32 LHsBinds GhcPs ->
30 [LFamilyDecl GhcPs] ->
33 [LFamilyDecl GhcPs] ->
31− [LTyFamDefltDecl GhcPs] ->
34+ [LTyFamDefltEqn GhcPs] ->
32 [LDocDecl] ->
35 [LDocDecl] ->
33 R ()
36 R ()
34−p_classDecl ctx name HsQTvs {..} fixity fdeps csigs cdefs cats catdefs cdocs = do
37+p_classDecl ctx name tvars fixity fdeps csigs cdefs cats catdefs cdocs = do
38+ let HsQTvs {..} = tvars
35− let variableSpans = getLoc <$> hsq_explicit
39+ variableSpans = getLoc <$> hsq_explicit
36 signatureSpans = getLoc name : variableSpans
40 signatureSpans = getLoc name : variableSpans
37 dependencySpans = getLoc <$> fdeps
41 dependencySpans = getLoc <$> fdeps
38 combinedSpans = getLoc ctx : (signatureSpans ++ dependencySpans)
42 combinedSpans = getLoc ctx : (signatureSpans ++ dependencySpans)
39− -- GHC's AST does not necessarily store each kind of element in source
40− -- location order. This happens because different declarations are stored
41− -- in different lists. Consequently, to get all the declarations in proper
42− -- order, they need to be manually sorted.
43− sigs = (getLoc &&& fmap (SigD NoExtField)) <$> csigs
44− vals = (getLoc &&& fmap (ValD NoExtField)) <$> toList cdefs
45− tyFams = (getLoc &&& fmap (TyClD NoExtField . FamDecl NoExtField)) <$> cats
46− docs = (getLoc &&& fmap (DocD NoExtField)) <$> cdocs
47− tyFamDefs =
48− ( getLoc &&& fmap (InstD NoExtField . TyFamInstD NoExtField)
49− )
50− <$> catdefs
51− allDecls =
52− snd <$> sortOn fst (sigs <> vals <> tyFams <> tyFamDefs <> docs)
53 txt "class"
43 txt "class"
54 switchLayout combinedSpans $ do
44 switchLayout combinedSpans $ do
55 breakpoint
45 breakpoint
56 inci $ do
46 inci $ do
57 p_classContext ctx
47 p_classContext ctx
58− switchLayout signatureSpans $
48+ switchLayout signatureSpans $ do
59 p_infixDefHelper
49 p_infixDefHelper
60 (isInfix fixity)
50 (isInfix fixity)
61− True
51+ inci
62 (p_rdrName name)
52 (p_rdrName name)
63 (located' p_hsTyVarBndr <$> hsq_explicit)
53 (located' p_hsTyVarBndr <$> hsq_explicit)
64 inci (p_classFundeps fdeps)
54 inci (p_classFundeps fdeps)
55+ -- NOTE GHC's AST does not necessarily store each kind of element in
56+ -- source location order. This happens because different declarations are
57+ -- stored in different lists. Consequently, to get all the declarations in
58+ -- proper order, they need to be manually sorted.
59+ let sigs = (getLoc &&& fmap (SigD NoExt)) <$> csigs
60+ vals = (getLoc &&& fmap (ValD NoExt)) <$> toList cdefs
61+ tyFams = (getLoc &&& fmap (TyClD NoExt . FamDecl NoExt)) <$> cats
62+ docs = (getLoc &&& fmap (DocD NoExt)) <$> cdocs
63+ tyFamDefs =
64+ ( getLoc &&& fmap (InstD NoExt . TyFamInstD NoExt . defltEqnToInstDecl)
65+ )
66+ <$> catdefs
65− unless (null allDecls) $ do
67+ allDecls =
66− breakpoint
68+ snd <$> sortBy (comparing fst) (sigs <> vals <> tyFams <> tyFamDefs <> docs)
67− txt "where"
68 unless (null allDecls) $ do
69 unless (null allDecls) $ do
70+ space
71+ txt "where"
69 breakpoint -- Ensure whitespace is added after where clause.
72 breakpoint -- Ensure whitespace is added after where clause.
73+ -- Add newline before first declaration if the body contains separate
74+ -- declarations.
75+ when (hasSeparatedDecls allDecls) breakpoint'
70− inci (p_hsDeclsRespectGrouping Associated allDecls)
76+ inci (p_hsDecls Associated allDecls)
71−p_classDecl _ _ (XLHsQTyVars c) _ _ _ _ _ _ _ = noExtCon c
72
77
73p_classContext :: LHsContext GhcPs -> R ()
78p_classContext :: LHsContext GhcPs -> R ()
74p_classContext ctx = unless (null (unLoc ctx)) $ do
79p_classContext ctx = unless (null (unLoc ctx)) $ do
@@ -82,7 +87,7 @@ p_classFundeps fdeps = unless (null fdeps) $ do
82 breakpoint
87 breakpoint
83 txt "|"
88 txt "|"
84 space
89 space
85− inci $ sep commaDel (sitcc . located' p_funDep) fdeps
90+ sitcc $ sep (comma >> breakpoint) (sitcc . located' p_funDep) fdeps
86
91
87p_funDep :: FunDep (Located RdrName) -> R ()
92p_funDep :: FunDep (Located RdrName) -> R ()
88p_funDep (before, after) = do
93p_funDep (before, after) = do
@@ -95,6 +100,13 @@ p_funDep (before, after) = do
95----------------------------------------------------------------------------
100----------------------------------------------------------------------------
96-- Helpers
101-- Helpers
97
102
103+defltEqnToInstDecl :: TyFamDefltEqn GhcPs -> TyFamInstDecl GhcPs
104+defltEqnToInstDecl FamEqn {..} = TyFamInstDecl {..}
105+ where
106+ eqn = FamEqn {feqn_pats = tyVarsToTypes feqn_pats, ..}
107+ tfid_eqn = HsIB {hsib_ext = NoExt, hsib_body = eqn}
108+defltEqnToInstDecl XFamEqn {} = notImplemented "XFamEqn"
109+
98isInfix :: LexicalFixity -> Bool
110isInfix :: LexicalFixity -> Bool
99isInfix = \case
111isInfix = \case
100 Infix -> True
112 Infix -> True
src/Ormolu/Printer/Meat/Declaration/Data.hs+58−74
@@ -9,12 +9,15 @@ module Ormolu.Printer.Meat.Declaration.Data
9where
9where
10
10
11import Control.Monad
11import Control.Monad
12−import Data.Maybe (isJust, maybeToList)
12+import Data.Maybe (isJust)
13+import Data.Maybe (maybeToList)
13import GHC
14import GHC
14import Ormolu.Printer.Combinators
15import Ormolu.Printer.Combinators
15import Ormolu.Printer.Meat.Common
16import Ormolu.Printer.Meat.Common
16import Ormolu.Printer.Meat.Type
17import Ormolu.Printer.Meat.Type
17import Ormolu.Utils
18import Ormolu.Utils
19+import RdrName (RdrName (..))
20+import SrcLoc (Located)
18
21
19p_dataDecl ::
22p_dataDecl ::
20 -- | Whether to format as data family
23 -- | Whether to format as data family
@@ -35,13 +38,12 @@ p_dataDecl style name tpats fixity HsDataDefn {..} = do
35 txt $ case style of
38 txt $ case style of
36 Associated -> mempty
39 Associated -> mempty
37 Free -> " instance"
40 Free -> " instance"
38− let constructorSpans = getLoc name : fmap getLoc tpats
41+ switchLayout (getLoc name : fmap getLoc tpats) $ do
39− switchLayout constructorSpans $ do
40 breakpoint
42 breakpoint
41 inci $
43 inci $
42 p_infixDefHelper
44 p_infixDefHelper
43 (isInfix fixity)
45 (isInfix fixity)
44− True
46+ inci
45 (p_rdrName name)
47 (p_rdrName name)
46 (located' p_hsType <$> tpats)
48 (located' p_hsType <$> tpats)
47 case dd_kindSig of
49 case dd_kindSig of
@@ -54,42 +56,29 @@ p_dataDecl style name tpats fixity HsDataDefn {..} = do
54 let gadt = isJust dd_kindSig || any (isGadt . unLoc) dd_cons
56 let gadt = isJust dd_kindSig || any (isGadt . unLoc) dd_cons
55 unless (null dd_cons) $
57 unless (null dd_cons) $
56 if gadt
58 if gadt
57− then inci $ do
59+ then do
58− switchLayout constructorSpans $ do
59− breakpoint
60− txt "where"
61− breakpoint
62− sepSemi (located' (p_conDecl False)) dd_cons
63− else switchLayout (getLoc name : (getLoc <$> dd_cons)) . inci $ do
64− let singleConstRec = isSingleConstRec dd_cons
65− if singleConstRec
66− then space
67− else
68− if hasHaddocks dd_cons
69− then newline
70− else breakpoint
71− equals
72 space
60 space
73− layout <- getLayout
61+ txt "where"
62+ breakpoint
63+ inci $ sepSemi (located' p_conDecl) dd_cons
64+ else switchLayout (getLoc name : (getLoc <$> dd_cons))
65+ $ inci
66+ $ do
67+ breakpoint
68+ txt "="
69+ space
74− let s =
70+ let s =
75− if layout == MultiLine || hasHaddocks dd_cons
71+ vlayout
72+ (space >> txt "|" >> space)
76− then newline >> txt "|" >> space
73+ (newline >> txt "|" >> space)
77− else space >> txt "|" >> space
78− sitcc' =
79− if singleConstRec
80− then id
81− else sitcc
82− sep s (sitcc' . located' (p_conDecl singleConstRec)) dd_cons
74+ sep s (sitcc . located' p_conDecl) dd_cons
83 unless (null $ unLoc dd_derivs) breakpoint
75 unless (null $ unLoc dd_derivs) breakpoint
84− inci . located dd_derivs $ \xs ->
76+ inci . located dd_derivs $ \xs -> do
85 sep newline (located' p_hsDerivingClause) xs
77 sep newline (located' p_hsDerivingClause) xs
86−p_dataDecl _ _ _ _ (XHsDataDefn x) = noExtCon x
78+p_dataDecl _ _ _ _ (XHsDataDefn NoExt) = notImplemented "XHsDataDefn"
87
79
88−p_conDecl ::
89− Bool ->
90− ConDecl GhcPs ->
80+p_conDecl :: ConDecl GhcPs -> R ()
91− R ()
92−p_conDecl singleConstRec = \case
81+p_conDecl = \case
93 ConDeclGADT {..} -> do
82 ConDeclGADT {..} -> do
94 mapM_ (p_hsDocString Pipe True) con_doc
83 mapM_ (p_hsDocString Pipe True) con_doc
95 let conDeclSpn =
84 let conDeclSpn =
@@ -104,19 +93,19 @@ p_conDecl singleConstRec = \case
104 (c : cs) -> do
93 (c : cs) -> do
105 p_rdrName c
94 p_rdrName c
106 unless (null cs) . inci $ do
95 unless (null cs) . inci $ do
107− commaDel
96+ comma
97+ breakpoint
108− sep commaDel p_rdrName cs
98+ sitcc $ sep (comma >> breakpoint) p_rdrName cs
99+ space
109 inci $ do
100 inci $ do
110− space
111 txt "::"
101 txt "::"
112 let interArgBreak =
102 let interArgBreak =
113 if hasDocStrings (unLoc con_res_ty)
103 if hasDocStrings (unLoc con_res_ty)
114 then newline
104 then newline
115 else breakpoint
105 else breakpoint
116 interArgBreak
106 interArgBreak
117− when (unLoc con_forall) $ do
107+ p_forallBndrs (hsq_explicit con_qvars)
118− p_forallBndrs ForallInvis p_hsTyVarBndr (hsq_explicit con_qvars)
119− interArgBreak
108+ unless (null $ hsq_explicit con_qvars) interArgBreak
120 forM_ con_mb_cxt p_lhsContext
109 forM_ con_mb_cxt p_lhsContext
121 case con_args of
110 case con_args of
122 PrefixCon xs -> do
111 PrefixCon xs -> do
@@ -135,27 +124,24 @@ p_conDecl singleConstRec = \case
135 p_hsType (unLoc con_res_ty)
124 p_hsType (unLoc con_res_ty)
136 ConDeclH98 {..} -> do
125 ConDeclH98 {..} -> do
137 mapM_ (p_hsDocString Pipe True) con_doc
126 mapM_ (p_hsDocString Pipe True) con_doc
138− let conDeclWithContextSpn =
127+ let conDeclSpn =
139− [getLoc con_forall]
128+ [getLoc con_name]
140 <> fmap getLoc con_ex_tvs
129 <> fmap getLoc con_ex_tvs
141 <> maybeToList (fmap getLoc con_mb_cxt)
130 <> maybeToList (fmap getLoc con_mb_cxt)
142− <> conDeclSpn
143− conDeclSpn =
144− getLoc con_name : conArgsSpans con_args
131+ <> conArgsSpans con_args
145− switchLayout conDeclWithContextSpn $ do
132+ switchLayout conDeclSpn $ do
146− when (unLoc con_forall) $ do
133+ p_forallBndrs con_ex_tvs
147− p_forallBndrs ForallInvis p_hsTyVarBndr con_ex_tvs
148− breakpoint
134+ unless (null con_ex_tvs) breakpoint
149 forM_ con_mb_cxt p_lhsContext
135 forM_ con_mb_cxt p_lhsContext
150− switchLayout conDeclSpn $ case con_args of
136+ case con_args of
151 PrefixCon xs -> do
137 PrefixCon xs -> do
152 p_rdrName con_name
138 p_rdrName con_name
153 unless (null xs) breakpoint
139 unless (null xs) breakpoint
154− inci . sitcc $ sep breakpoint (sitcc . located' p_hsTypePostDoc) xs
140+ inci . sitcc $ sep breakpoint (sitcc . located' p_hsType) xs
155 RecCon l -> do
141 RecCon l -> do
156 p_rdrName con_name
142 p_rdrName con_name
157 breakpoint
143 breakpoint
158− inciIf (not singleConstRec) (located l p_conDeclFields)
144+ inci $ located l p_conDeclFields
159 InfixCon x y -> do
145 InfixCon x y -> do
160 located x p_hsType
146 located x p_hsType
161 breakpoint
147 breakpoint
@@ -163,7 +149,7 @@ p_conDecl singleConstRec = \case
163 p_rdrName con_name
149 p_rdrName con_name
164 space
150 space
165 located y p_hsType
151 located y p_hsType
166− XConDecl x -> noExtCon x
152+ XConDecl NoExt -> notImplemented "XConDecl"
167
153
168conArgsSpans :: HsConDeclDetails GhcPs -> [SrcSpan]
154conArgsSpans :: HsConDeclDetails GhcPs -> [SrcSpan]
169conArgsSpans = \case
155conArgsSpans = \case
@@ -177,7 +163,18 @@ conArgsSpans = \case
177conTyVarsSpans :: LHsQTyVars GhcPs -> [SrcSpan]
163conTyVarsSpans :: LHsQTyVars GhcPs -> [SrcSpan]
178conTyVarsSpans = \case
164conTyVarsSpans = \case
179 HsQTvs {..} -> getLoc <$> hsq_explicit
165 HsQTvs {..} -> getLoc <$> hsq_explicit
180− XLHsQTyVars x -> noExtCon x
166+ XLHsQTyVars NoExt -> []
167+
168+p_forallBndrs ::
169+ [LHsTyVarBndr GhcPs] ->
170+ R ()
171+p_forallBndrs = \case
172+ [] -> return ()
173+ bndrs -> do
174+ txt "forall"
175+ space
176+ sep space (located' p_hsTyVarBndr) bndrs
177+ txt "."
181
178
182p_lhsContext ::
179p_lhsContext ::
183 LHsContext GhcPs ->
180 LHsContext GhcPs ->
@@ -204,9 +201,9 @@ p_hsDerivingClause HsDerivingClause {..} = do
204 let derivingWhat = located deriv_clause_tys $ \case
201 let derivingWhat = located deriv_clause_tys $ \case
205 [] -> txt "()"
202 [] -> txt "()"
206 xs ->
203 xs ->
207− parens N $
204+ parens N . sitcc $
208 sep
205 sep
209− commaDel
206+ (comma >> breakpoint)
210 (sitcc . located' p_hsType . hsib_body)
207 (sitcc . located' p_hsType . hsib_body)
211 xs
208 xs
212 space
209 space
@@ -235,9 +232,9 @@ p_hsDerivingClause HsDerivingClause {..} = do
235 txt "via"
232 txt "via"
236 space
233 space
237 located hsib_body p_hsType
234 located hsib_body p_hsType
238− ViaStrategy (XHsImplicitBndrs x) ->
235+ ViaStrategy (XHsImplicitBndrs NoExt) ->
239− noExtCon x
236+ notImplemented "XHsImplicitBndrs"
240−p_hsDerivingClause (XHsDerivingClause x) = noExtCon x
237+p_hsDerivingClause (XHsDerivingClause NoExt) = notImplemented "XHsDerivingClause"
241
238
242----------------------------------------------------------------------------
239----------------------------------------------------------------------------
243-- Helpers
240-- Helpers
@@ -246,16 +243,3 @@ isInfix :: LexicalFixity -> Bool
246isInfix = \case
243isInfix = \case
247 Infix -> True
244 Infix -> True
248 Prefix -> False
245 Prefix -> False
249−
250−isSingleConstRec :: [LConDecl GhcPs] -> Bool
251−isSingleConstRec [(L _ ConDeclH98 {..})] =
252− case con_args of
253− RecCon _ -> True
254− _ -> False
255−isSingleConstRec _ = 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+5−4
@@ -9,12 +9,13 @@ where
9import GHC
9import GHC
10import Ormolu.Printer.Combinators
10import Ormolu.Printer.Combinators
11import Ormolu.Printer.Meat.Type
11import Ormolu.Printer.Meat.Type
12+import Ormolu.Utils
12
13
13p_defaultDecl :: DefaultDecl GhcPs -> R ()
14p_defaultDecl :: DefaultDecl GhcPs -> R ()
14p_defaultDecl = \case
15p_defaultDecl = \case
15− DefaultDecl NoExtField ts -> do
16+ DefaultDecl NoExt ts -> do
16 txt "default"
17 txt "default"
17 breakpoint
18 breakpoint
18− inci . parens N $
19+ inci . parens N . sitcc $
19− sep commaDel (sitcc . located' p_hsType) ts
20+ sep (comma >> breakpoint) (sitcc . located' p_hsType) ts
20− XDefaultDecl x -> noExtCon x
21+ XDefaultDecl {} -> notImplemented "XDefaultDecl"
src/Ormolu/Printer/Meat/Declaration/Foreign.hs+7−9
@@ -15,6 +15,7 @@ import GHC
15import Ormolu.Printer.Combinators
15import Ormolu.Printer.Combinators
16import Ormolu.Printer.Meat.Common
16import Ormolu.Printer.Meat.Common
17import Ormolu.Printer.Meat.Declaration.Signature
17import Ormolu.Printer.Meat.Declaration.Signature
18+import Ormolu.Utils
18
19
19p_foreignDecl :: ForeignDecl GhcPs -> R ()
20p_foreignDecl :: ForeignDecl GhcPs -> R ()
20p_foreignDecl = \case
21p_foreignDecl = \case
@@ -24,21 +25,18 @@ p_foreignDecl = \case
24 fd@ForeignExport {fd_fe} -> do
25 fd@ForeignExport {fd_fe} -> do
25 p_foreignExport fd_fe
26 p_foreignExport fd_fe
26 p_foreignTypeSig fd
27 p_foreignTypeSig fd
27− XForeignDecl x -> noExtCon x
28+ XForeignDecl {} -> notImplemented "XForeignDecl"
28
29
29-- | Printer for the last part of an import\/export, which is function name
30-- | Printer for the last part of an import\/export, which is function name
30-- and type signature.
31-- and type signature.
31p_foreignTypeSig :: ForeignDecl GhcPs -> R ()
32p_foreignTypeSig :: ForeignDecl GhcPs -> R ()
32p_foreignTypeSig fd = do
33p_foreignTypeSig fd = do
33 breakpoint
34 breakpoint
34− inci
35+ -- Switch into the layout of the signature, to allow us to pull name and
35− . switchLayout
36+ -- signature onto a single line.
36− [ getLoc (fd_name fd),
37− (getLoc . hsib_body . fd_sig_ty) fd
37+ inci . switchLayout [getLoc . hsib_body $ fd_sig_ty fd] $ do
38− ]
39− $ do
40− p_rdrName (fd_name fd)
38+ p_rdrName (fd_name fd)
41− p_typeAscription (HsWC NoExtField (fd_sig_ty fd))
39+ p_typeAscription (HsWC NoExt (fd_sig_ty fd))
42
40
43-- | Printer for 'ForeignImport'.
41-- | Printer for 'ForeignImport'.
44--
42--
src/Ormolu/Printer/Meat/Declaration/Instance.hs+28−22
@@ -15,7 +15,8 @@ import BasicTypes
15import Control.Arrow
15import Control.Arrow
16import Control.Monad
16import Control.Monad
17import Data.Foldable
17import Data.Foldable
18−import Data.List (sortOn)
18+import Data.List (sortBy)
19+import Data.Ord (comparing)
19import GHC
20import GHC
20import Ormolu.Printer.Combinators
21import Ormolu.Printer.Combinators
21import Ormolu.Printer.Meat.Common
22import Ormolu.Printer.Meat.Common
@@ -32,11 +33,13 @@ p_standaloneDerivDecl DerivDecl {..} = do
32 txt "instance"
33 txt "instance"
33 breakpoint
34 breakpoint
34 match_overlap_mode deriv_overlap_mode breakpoint
35 match_overlap_mode deriv_overlap_mode breakpoint
36+ if toIndent
37+ then inci typesAfterInstance
35− inciIf toIndent typesAfterInstance
38+ else typesAfterInstance
36 txt "deriving"
39 txt "deriving"
37 space
40 space
38 case deriv_strategy of
41 case deriv_strategy of
39− Nothing ->
42+ Nothing -> do
40 instTypes False
43 instTypes False
41 Just (L _ a) -> case a of
44 Just (L _ a) -> case a of
42 StockStrategy -> do
45 StockStrategy -> do
@@ -54,8 +57,8 @@ p_standaloneDerivDecl DerivDecl {..} = do
54 inci (located hsib_body p_hsType)
57 inci (located hsib_body p_hsType)
55 breakpoint
58 breakpoint
56 instTypes True
59 instTypes True
57− ViaStrategy (XHsImplicitBndrs x) ->
60+ ViaStrategy (XHsImplicitBndrs NoExt) ->
58− noExtCon x
61+ notImplemented "XHsImplicitBndrs"
59p_standaloneDerivDecl (XDerivDecl _) = notImplemented "XDerivDecl"
62p_standaloneDerivDecl (XDerivDecl _) = notImplemented "XDerivDecl"
60
63
61p_clsInstDecl :: ClsInstDecl GhcPs -> R ()
64p_clsInstDecl :: ClsInstDecl GhcPs -> R ()
@@ -68,18 +71,19 @@ p_clsInstDecl = \case
68 -- location order. This happens because different declarations are stored in
71 -- location order. This happens because different declarations are stored in
69 -- different lists. Consequently, to get all the declarations in proper
72 -- different lists. Consequently, to get all the declarations in proper
70 -- order, they need to be manually sorted.
73 -- order, they need to be manually sorted.
71− let sigs = (getLoc &&& fmap (SigD NoExtField)) <$> cid_sigs
74+ let sigs = (getLoc &&& fmap (SigD NoExt)) <$> cid_sigs
72− vals = (getLoc &&& fmap (ValD NoExtField)) <$> toList cid_binds
75+ vals = (getLoc &&& fmap (ValD NoExt)) <$> toList cid_binds
73 tyFamInsts =
76 tyFamInsts =
74− ( getLoc &&& fmap (InstD NoExtField . TyFamInstD NoExtField)
77+ ( getLoc &&& fmap (InstD NoExt . TyFamInstD NoExt)
75 )
78 )
76 <$> cid_tyfam_insts
79 <$> cid_tyfam_insts
77 dataFamInsts =
80 dataFamInsts =
78− ( getLoc &&& fmap (InstD NoExtField . DataFamInstD NoExtField)
81+ ( getLoc &&& fmap (InstD NoExt . DataFamInstD NoExt)
79 )
82 )
80 <$> cid_datafam_insts
83 <$> cid_datafam_insts
81 allDecls =
84 allDecls =
85+ snd
82− snd <$> sortOn fst (sigs <> vals <> tyFamInsts <> dataFamInsts)
86+ <$> sortBy (comparing fst) (sigs <> vals <> tyFamInsts <> dataFamInsts)
83 located hsib_body $ \x -> do
87 located hsib_body $ \x -> do
84 breakpoint
88 breakpoint
85 inci $ do
89 inci $ do
@@ -88,12 +92,16 @@ p_clsInstDecl = \case
88 unless (null allDecls) $ do
92 unless (null allDecls) $ do
89 breakpoint
93 breakpoint
90 txt "where"
94 txt "where"
91− unless (null allDecls) . inci $ do
95+ unless (null allDecls) $ do
96+ inci $ do
92− -- Ensure whitespace is added after where clause.
97+ -- Ensure whitespace is added after where clause.
98+ breakpoint
99+ -- Add newline before first declaration if the body contains separate
100+ -- declarations
93− breakpoint
101+ when (hasSeparatedDecls allDecls) breakpoint'
94− dontUseBraces $ p_hsDeclsRespectGrouping Associated allDecls
102+ dontUseBraces $ p_hsDecls Associated allDecls
95− XHsImplicitBndrs x -> noExtCon x
103+ XHsImplicitBndrs NoExt -> notImplemented "XHsImplicitBndrs"
96− XClsInstDecl x -> noExtCon x
104+ XClsInstDecl NoExt -> notImplemented "XClsInstDecl"
97
105
98p_tyFamInstDecl :: FamilyStyle -> TyFamInstDecl GhcPs -> R ()
106p_tyFamInstDecl :: FamilyStyle -> TyFamInstDecl GhcPs -> R ()
99p_tyFamInstDecl style = \case
107p_tyFamInstDecl style = \case
@@ -106,12 +114,10 @@ p_tyFamInstDecl style = \case
106
114
107p_dataFamInstDecl :: FamilyStyle -> DataFamInstDecl GhcPs -> R ()
115p_dataFamInstDecl :: FamilyStyle -> DataFamInstDecl GhcPs -> R ()
108p_dataFamInstDecl style = \case
116p_dataFamInstDecl style = \case
109− DataFamInstDecl {dfid_eqn = HsIB {hsib_body = FamEqn {..}}} ->
117+ DataFamInstDecl {..} -> do
118+ let HsIB {..} = dfid_eqn
119+ FamEqn {..} = hsib_body
110− p_dataDecl style feqn_tycon (map typeArgToType feqn_pats) feqn_fixity feqn_rhs
120+ p_dataDecl style feqn_tycon feqn_pats feqn_fixity feqn_rhs
111− DataFamInstDecl {dfid_eqn = HsIB {hsib_body = XFamEqn {}}} ->
112− notImplemented "XFamEqn"
113− DataFamInstDecl {dfid_eqn = XHsImplicitBndrs {}} ->
114− notImplemented "XHsImplicitBndrs"
115
121
116match_overlap_mode :: Maybe (Located OverlapMode) -> R () -> R ()
122match_overlap_mode :: Maybe (Located OverlapMode) -> R () -> R ()
117match_overlap_mode overlap_mode layoutStrategy =
123match_overlap_mode overlap_mode layoutStrategy =
src/Ormolu/Printer/Meat/Declaration/RoleAnnotation.hs+6−2
@@ -1,5 +1,6 @@
1{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE RecordWildCards #-}
3{-# LANGUAGE TypeFamilies #-}
4{-# LANGUAGE TypeFamilies #-}
4
5
5-- | Rendering of Role annotation declarations.
6-- | Rendering of Role annotation declarations.
@@ -12,11 +13,14 @@ import CoAxiom
12import GHC
13import GHC
13import Ormolu.Printer.Combinators
14import Ormolu.Printer.Combinators
14import Ormolu.Printer.Meat.Common
15import Ormolu.Printer.Meat.Common
16+import Ormolu.Utils
17+import RdrName (RdrName (..))
18+import SrcLoc (Located)
15
19
16p_roleAnnot :: RoleAnnotDecl GhcPs -> R ()
20p_roleAnnot :: RoleAnnotDecl GhcPs -> R ()
17p_roleAnnot = \case
21p_roleAnnot = \case
18− RoleAnnotDecl NoExtField l_name anns -> p_roleAnnot' l_name anns
22+ RoleAnnotDecl NoExt l_name anns -> p_roleAnnot' l_name anns
19− XRoleAnnotDecl x -> noExtCon x
23+ XRoleAnnotDecl _ -> notImplemented "XRoleAnnotDecl"
20
24
21p_roleAnnot' :: Located RdrName -> [Located (Maybe Role)] -> R ()
25p_roleAnnot' :: Located RdrName -> [Located (Maybe Role)] -> R ()
22p_roleAnnot' l_name anns = do
26p_roleAnnot' l_name anns = do
src/Ormolu/Printer/Meat/Declaration/Rule.hs+23−22
@@ -1,5 +1,6 @@
1{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE RecordWildCards #-}
3
4
4module Ormolu.Printer.Meat.Declaration.Rule
5module Ormolu.Printer.Meat.Declaration.Rule
5 ( p_ruleDecls,
6 ( p_ruleDecls,
@@ -7,55 +8,55 @@ module Ormolu.Printer.Meat.Declaration.Rule
7where
8where
8
9
9import BasicTypes
10import BasicTypes
10−import Control.Monad (unless)
11import GHC
11import GHC
12import Ormolu.Printer.Combinators
12import Ormolu.Printer.Combinators
13import Ormolu.Printer.Meat.Common
13import Ormolu.Printer.Meat.Common
14import Ormolu.Printer.Meat.Declaration.Signature
14import Ormolu.Printer.Meat.Declaration.Signature
15import Ormolu.Printer.Meat.Declaration.Value
15import Ormolu.Printer.Meat.Declaration.Value
16−import Ormolu.Printer.Meat.Type
16+import Ormolu.Utils
17
17
18p_ruleDecls :: RuleDecls GhcPs -> R ()
18p_ruleDecls :: RuleDecls GhcPs -> R ()
19p_ruleDecls = \case
19p_ruleDecls = \case
20− HsRules NoExtField _ xs ->
20+ HsRules NoExt _ 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 NoExt -> notImplemented "XRuleDecls"
24
24
25p_ruleDecl :: RuleDecl GhcPs -> R ()
25p_ruleDecl :: RuleDecl GhcPs -> R ()
26p_ruleDecl = \case
26p_ruleDecl = \case
27− HsRule NoExtField ruleName activation tyvars ruleBndrs lhs rhs -> do
27+ HsRule NoExt ruleName activation ruleBndrs lhs rhs -> do
28 located ruleName p_ruleName
28 located ruleName p_ruleName
29 space
29 space
30 p_activation activation
30 p_activation activation
31 space
31 space
32− case tyvars of
32+ p_ruleBndrs ruleBndrs
33− Nothing -> return ()
34− Just xs -> do
35− p_forallBndrs ForallInvis p_hsTyVarBndr xs
36− space
37− -- It appears that there is no way to tell if there was an empty forall
38− -- in the input or no forall at all. We do not want to add redundant
39− -- foralls, so let's just skip the empty ones.
40− unless (null ruleBndrs) $
41− p_forallBndrs ForallInvis p_ruleBndr ruleBndrs
42 breakpoint
33 breakpoint
43 inci $ do
34 inci $ do
44 located lhs p_hsExpr
35 located lhs p_hsExpr
45 space
36 space
46− equals
37+ txt "="
47 inci $ do
38 inci $ do
48 breakpoint
39 breakpoint
49 located rhs p_hsExpr
40 located rhs p_hsExpr
50− XRuleDecl x -> noExtCon x
41+ XRuleDecl NoExt -> notImplemented "XRuleDecl"
51
42
52p_ruleName :: (SourceText, RuleName) -> R ()
43p_ruleName :: (SourceText, RuleName) -> R ()
53−p_ruleName (_, name) = atom $ (HsString NoSourceText name :: HsLit GhcPs)
44+p_ruleName (_, name) = atom $ HsString NoSourceText name
45+
46+p_ruleBndrs :: [LRuleBndr GhcPs] -> R ()
47+p_ruleBndrs [] = return ()
48+p_ruleBndrs bndrs =
49+ switchLayout (getLoc <$> bndrs) $ do
50+ txt "forall"
51+ breakpoint
52+ inci $ do
53+ sitcc $ sep breakpoint (sitcc . located' p_ruleBndr) bndrs
54+ txt "."
54
55
55p_ruleBndr :: RuleBndr GhcPs -> R ()
56p_ruleBndr :: RuleBndr GhcPs -> R ()
56p_ruleBndr = \case
57p_ruleBndr = \case
57− RuleBndr NoExtField x -> p_rdrName x
58+ RuleBndr NoExt x -> p_rdrName x
58− RuleBndrSig NoExtField x hswc -> parens N $ do
59+ RuleBndrSig NoExt x hswc -> parens N $ do
59 p_rdrName x
60 p_rdrName x
60 p_typeAscription hswc
61 p_typeAscription hswc
61− XRuleBndr x -> noExtCon x
62+ XRuleBndr NoExt -> notImplemented "XRuleBndr"
src/Ormolu/Printer/Meat/Declaration/Signature.hs+33−49
@@ -7,13 +7,13 @@ module Ormolu.Printer.Meat.Declaration.Signature
7 ( p_sigDecl,
7 ( p_sigDecl,
8 p_typeAscription,
8 p_typeAscription,
9 p_activation,
9 p_activation,
10− p_standaloneKindSig,
11 )
10 )
12where
11where
13
12
14import BasicTypes
13import BasicTypes
15import BooleanFormula
14import BooleanFormula
16import Control.Monad
15import Control.Monad
16+import Data.Bool (bool)
17import GHC
17import GHC
18import Ormolu.Printer.Combinators
18import Ormolu.Printer.Combinators
19import Ormolu.Printer.Meat.Common
19import Ormolu.Printer.Meat.Common
@@ -22,16 +22,16 @@ import Ormolu.Utils
22
22
23p_sigDecl :: Sig GhcPs -> R ()
23p_sigDecl :: Sig GhcPs -> R ()
24p_sigDecl = \case
24p_sigDecl = \case
25− TypeSig NoExtField names hswc -> p_typeSig True names hswc
25+ TypeSig NoExt names hswc -> p_typeSig True names hswc
26− PatSynSig NoExtField names hsib -> p_patSynSig names hsib
26+ PatSynSig NoExt names hsib -> p_patSynSig names hsib
27− ClassOpSig NoExtField def names hsib -> p_classOpSig def names hsib
27+ ClassOpSig NoExt def names hsib -> p_classOpSig def names hsib
28− FixSig NoExtField sig -> p_fixSig sig
28+ FixSig NoExt sig -> p_fixSig sig
29− InlineSig NoExtField name inlinePragma -> p_inlineSig name inlinePragma
29+ InlineSig NoExt name inlinePragma -> p_inlineSig name inlinePragma
30− SpecSig NoExtField name ts inlinePragma -> p_specSig name ts inlinePragma
30+ SpecSig NoExt name ts inlinePragma -> p_specSig name ts inlinePragma
31− SpecInstSig NoExtField _ hsib -> p_specInstSig hsib
31+ SpecInstSig NoExt _ hsib -> p_specInstSig hsib
32− MinimalSig NoExtField _ booleanFormula -> p_minimalSig booleanFormula
32+ MinimalSig NoExt _ booleanFormula -> p_minimalSig booleanFormula
33− CompleteMatchSig NoExtField _sourceText cs ty -> p_completeSig cs ty
33+ CompleteMatchSig NoExt _sourceText cs ty -> p_completeSig cs ty
34− SCCFunSig NoExtField _ name literal -> p_sccSig name literal
34+ SCCFunSig NoExt _ name literal -> p_sccSig name literal
35 _ -> notImplemented "certain types of signature declarations"
35 _ -> notImplemented "certain types of signature declarations"
36
36
37p_typeSig ::
37p_typeSig ::
@@ -47,23 +47,25 @@ p_typeSig indentTail (n : ns) hswc = do
47 p_rdrName n
47 p_rdrName n
48 if null ns
48 if null ns
49 then p_typeAscription hswc
49 then p_typeAscription hswc
50− else inciIf indentTail $ do
50+ else bool id inci indentTail $ do
51− commaDel
51+ comma
52+ breakpoint
52− sep commaDel p_rdrName ns
53+ sep (comma >> breakpoint) p_rdrName ns
53 p_typeAscription hswc
54 p_typeAscription hswc
54
55
55p_typeAscription ::
56p_typeAscription ::
56 LHsSigWcType GhcPs ->
57 LHsSigWcType GhcPs ->
57 R ()
58 R ()
58−p_typeAscription HsWC {..} = inci $ do
59+p_typeAscription HsWC {..} = do
59 space
60 space
61+ inci $ do
60− txt "::"
62+ txt "::"
61− let t = hsib_body hswc_body
63+ let t = hsib_body hswc_body
62− if hasDocStrings (unLoc t)
64+ if hasDocStrings (unLoc t)
63− then newline
65+ then newline
64− else breakpoint
66+ else breakpoint
65− located t p_hsType
67+ located t p_hsType
66−p_typeAscription (XHsWildCardBndrs x) = noExtCon x
68+p_typeAscription (XHsWildCardBndrs NoExt) = notImplemented "XHsWildCardBndrs"
67
69
68p_patSynSig ::
70p_patSynSig ::
69 [Located RdrName] ->
71 [Located RdrName] ->
@@ -71,11 +73,7 @@ p_patSynSig ::
71 R ()
73 R ()
72p_patSynSig names hsib = do
74p_patSynSig names hsib = do
73 txt "pattern"
75 txt "pattern"
74− let body =
75− p_typeSig
76− False
77− names
78− HsWC {hswc_ext = NoExtField, hswc_body = hsib}
76+ let body = p_typeSig False names HsWC {hswc_ext = NoExt, hswc_body = hsib}
79 if length names > 1
77 if length names > 1
80 then breakpoint >> inci body
78 then breakpoint >> inci body
81 else space >> body
79 else space >> body
@@ -90,13 +88,13 @@ p_classOpSig ::
90 R ()
88 R ()
91p_classOpSig def names hsib = do
89p_classOpSig def names hsib = do
92 when def (txt "default" >> space)
90 when def (txt "default" >> space)
93− p_typeSig True names HsWC {hswc_ext = NoExtField, hswc_body = hsib}
91+ p_typeSig True names HsWC {hswc_ext = NoExt, hswc_body = hsib}
94
92
95p_fixSig ::
93p_fixSig ::
96 FixitySig GhcPs ->
94 FixitySig GhcPs ->
97 R ()
95 R ()
98p_fixSig = \case
96p_fixSig = \case
99− FixitySig NoExtField names (Fixity _ n dir) -> do
97+ FixitySig NoExt names (Fixity _ n dir) -> do
100 txt $ case dir of
98 txt $ case dir of
101 InfixL -> "infixl"
99 InfixL -> "infixl"
102 InfixR -> "infixr"
100 InfixR -> "infixr"
@@ -104,8 +102,8 @@ p_fixSig = \case
104 space
102 space
105 atom n
103 atom n
106 space
104 space
107− sitcc $ sep commaDel p_rdrName names
105+ sitcc $ sep (comma >> breakpoint) p_rdrName names
108− XFixitySig x -> noExtCon x
106+ XFixitySig NoExt -> notImplemented "XFixitySig"
109
107
110p_inlineSig ::
108p_inlineSig ::
111 -- | Name
109 -- | Name
@@ -143,7 +141,7 @@ p_specSig name ts InlinePragma {..} = pragmaBraces $ do
143 space
141 space
144 txt "::"
142 txt "::"
145 breakpoint
143 breakpoint
146− inci $ sep commaDel (located' p_hsType . hsib_body) ts
144+ inci $ sep (comma >> breakpoint) (located' p_hsType . hsib_body) ts
147
145
148p_inlineSpec :: InlineSpec -> R ()
146p_inlineSpec :: InlineSpec -> R ()
149p_inlineSpec = \case
147p_inlineSpec = \case
@@ -187,13 +185,13 @@ p_booleanFormula = \case
187 And xs ->
185 And xs ->
188 sitcc $
186 sitcc $
189 sep
187 sep
190− commaDel
188+ (comma >> breakpoint)
191 (located' p_booleanFormula)
189 (located' p_booleanFormula)
192 xs
190 xs
193 Or xs ->
191 Or xs ->
194 sitcc $
192 sitcc $
195 sep
193 sep
196− (breakpoint >> txt "|" >> space)
194+ (breakpoint >> txt "| ")
197 (located' p_booleanFormula)
195 (located' p_booleanFormula)
198 xs
196 xs
199 Parens l -> located l (parens N . p_booleanFormula)
197 Parens l -> located l (parens N . p_booleanFormula)
@@ -207,7 +205,7 @@ p_completeSig ::
207p_completeSig cs' mty =
205p_completeSig cs' mty =
208 located cs' $ \cs ->
206 located cs' $ \cs ->
209 pragma "COMPLETE" . inci $ do
207 pragma "COMPLETE" . inci $ do
210− sep commaDel p_rdrName cs
208+ sitcc $ sep (comma >> breakpoint) p_rdrName cs
211 forM_ mty $ \ty -> do
209 forM_ mty $ \ty -> do
212 space
210 space
213 txt "::"
211 txt "::"
@@ -220,17 +218,3 @@ p_sccSig loc literal = pragma "SCC" . inci $ do
220 forM_ literal $ \x -> do
218 forM_ literal $ \x -> do
221 breakpoint
219 breakpoint
222 atom x
220 atom x
223−
224−p_standaloneKindSig :: StandaloneKindSig GhcPs -> R ()
225−p_standaloneKindSig (StandaloneKindSig NoExtField name bndrs) = do
226− txt "type"
227− inci $ do
228− space
229− p_rdrName name
230− space
231− txt "::"
232− breakpoint
233− case bndrs of
234− HsIB NoExtField sig -> located sig p_hsType
235− XHsImplicitBndrs x -> noExtCon x
236−p_standaloneKindSig (XStandaloneKindSig c) = noExtCon c
src/Ormolu/Printer/Meat/Declaration/Splice.hs+3−2
@@ -8,8 +8,9 @@ where
8import GHC
8import GHC
9import Ormolu.Printer.Combinators
9import Ormolu.Printer.Combinators
10import Ormolu.Printer.Meat.Declaration.Value (p_hsSplice)
10import Ormolu.Printer.Meat.Declaration.Value (p_hsSplice)
11+import Ormolu.Utils
11
12
12p_spliceDecl :: SpliceDecl GhcPs -> R ()
13p_spliceDecl :: SpliceDecl GhcPs -> R ()
13p_spliceDecl = \case
14p_spliceDecl = \case
14− SpliceDecl NoExtField splice _explicit -> located splice p_hsSplice
15+ SpliceDecl NoExt splice _explicit -> located splice p_hsSplice
15− XSpliceDecl x -> noExtCon x
16+ XSpliceDecl {} -> notImplemented "XSpliceDecl"
src/Ormolu/Printer/Meat/Declaration/Type.hs+8−8
@@ -11,6 +11,8 @@ import GHC
11import Ormolu.Printer.Combinators
11import Ormolu.Printer.Combinators
12import Ormolu.Printer.Meat.Common
12import Ormolu.Printer.Meat.Common
13import Ormolu.Printer.Meat.Type
13import Ormolu.Printer.Meat.Type
14+import RdrName (RdrName (..))
15+import SrcLoc (Located)
14
16
15p_synDecl ::
17p_synDecl ::
16 -- | Type constructor
18 -- | Type constructor
@@ -22,19 +24,17 @@ p_synDecl ::
22 -- | RHS of type declaration
24 -- | RHS of type declaration
23 LHsType GhcPs ->
25 LHsType GhcPs ->
24 R ()
26 R ()
25−p_synDecl name fixity HsQTvs {..} t = do
27+p_synDecl name fixity tvars t = do
26 txt "type"
28 txt "type"
27 space
29 space
30+ let HsQTvs {..} = tvars
28− switchLayout (getLoc name : map getLoc hsq_explicit) $
31+ switchLayout (getLoc name : map getLoc hsq_explicit) $ do
29 p_infixDefHelper
32 p_infixDefHelper
30 (case fixity of Infix -> True; _ -> False)
33 (case fixity of Infix -> True; _ -> False)
31− True
34+ inci
32 (p_rdrName name)
35 (p_rdrName name)
33 (map (located' p_hsTyVarBndr) hsq_explicit)
36 (map (located' p_hsTyVarBndr) hsq_explicit)
34 space
37 space
35− equals
38+ txt "="
36− if hasDocStrings (unLoc t)
37− then newline
38− else breakpoint
39+ breakpoint
39 inci (located t p_hsType)
40 inci (located t p_hsType)
40−p_synDecl _ _ (XLHsQTyVars x) _ = noExtCon x
src/Ormolu/Printer/Meat/Declaration/TypeFamily.hs+37−42
@@ -9,16 +9,18 @@ module Ormolu.Printer.Meat.Declaration.TypeFamily
9 )
9 )
10where
10where
11
11
12+import BasicTypes (LexicalFixity (..))
12import Control.Monad
13import Control.Monad
13−import Data.Maybe (isNothing)
14+import Data.Maybe (isJust, isNothing)
14import GHC
15import GHC
15import Ormolu.Printer.Combinators
16import Ormolu.Printer.Combinators
16import Ormolu.Printer.Meat.Common
17import Ormolu.Printer.Meat.Common
17import Ormolu.Printer.Meat.Type
18import Ormolu.Printer.Meat.Type
18import Ormolu.Utils
19import Ormolu.Utils
20+import SrcLoc (GenLocated (..), Located)
19
21
20p_famDecl :: FamilyStyle -> FamilyDecl GhcPs -> R ()
22p_famDecl :: FamilyStyle -> FamilyDecl GhcPs -> R ()
21−p_famDecl style FamilyDecl {fdTyVars = HsQTvs {..}, ..} = do
23+p_famDecl style FamilyDecl {..} = do
22 mmeqs <- case fdInfo of
24 mmeqs <- case fdInfo of
23 DataFamily -> Nothing <$ txt "data"
25 DataFamily -> Nothing <$ txt "data"
24 OpenTypeFamily -> Nothing <$ txt "type"
26 OpenTypeFamily -> Nothing <$ txt "type"
@@ -26,26 +28,27 @@ p_famDecl style FamilyDecl {fdTyVars = HsQTvs {..}, ..} = do
26 txt $ case style of
28 txt $ case style of
27 Associated -> mempty
29 Associated -> mempty
28 Free -> " family"
30 Free -> " family"
31+ let HsQTvs {..} = fdTyVars
29 breakpoint
32 breakpoint
30 inci $ do
33 inci $ do
31− switchLayout (getLoc fdLName : (getLoc <$> hsq_explicit)) $
34+ switchLayout (getLoc fdLName : (getLoc <$> hsq_explicit)) $ do
32 p_infixDefHelper
35 p_infixDefHelper
33 (isInfix fdFixity)
36 (isInfix fdFixity)
34− True
37+ inci
35 (p_rdrName fdLName)
38 (p_rdrName fdLName)
36 (located' p_hsTyVarBndr <$> hsq_explicit)
39 (located' p_hsTyVarBndr <$> hsq_explicit)
37− let resultSig = p_familyResultSigL fdResultSig
40+ let rsig = p_familyResultSigL (isJust fdInjectivityAnn) fdResultSig
38− unless (isNothing resultSig && isNothing fdInjectivityAnn) space
41+ unless (isNothing rsig && isNothing fdInjectivityAnn) $
39− inci $ do
40− sequence_ resultSig
41 space
42 space
43+ inci $ do
44+ sequence_ rsig
45+ when (isJust rsig && isJust fdInjectivityAnn) breakpoint
42 forM_ fdInjectivityAnn (located' p_injectivityAnn)
46 forM_ fdInjectivityAnn (located' p_injectivityAnn)
43 case mmeqs of
47 case mmeqs of
44 Nothing -> return ()
48 Nothing -> return ()
45 Just meqs -> do
49 Just meqs -> do
46− inci $ do
50+ space
47− breakpoint
48− txt "where"
51+ txt "where"
49 case meqs of
52 case meqs of
50 Nothing -> do
53 Nothing -> do
51 space
54 space
@@ -53,27 +56,26 @@ p_famDecl style FamilyDecl {fdTyVars = HsQTvs {..}, ..} = do
53 Just eqs -> do
56 Just eqs -> do
54 newline
57 newline
55 sep newline (located' (inci . p_tyFamInstEqn)) eqs
58 sep newline (located' (inci . p_tyFamInstEqn)) eqs
56−p_famDecl _ FamilyDecl {fdTyVars = XLHsQTyVars {}} =
59+p_famDecl _ (XFamilyDecl NoExt) = notImplemented "XFamilyDecl"
57− notImplemented "XLHsQTyVars"
58−p_famDecl _ (XFamilyDecl x) = noExtCon x
59
60
60p_familyResultSigL ::
61p_familyResultSigL ::
62+ Bool ->
61 Located (FamilyResultSig GhcPs) ->
63 Located (FamilyResultSig GhcPs) ->
62 Maybe (R ())
64 Maybe (R ())
63−p_familyResultSigL l =
65+p_familyResultSigL injAnn l =
64 case l of
66 case l of
65 L _ a -> case a of
67 L _ a -> case a of
66− NoSig NoExtField -> Nothing
68+ NoSig NoExt -> Nothing
67− KindSig NoExtField k -> Just $ do
69+ KindSig NoExt k -> Just $ do
68− txt "::"
70+ if injAnn then txt "=" else txt "::"
69 breakpoint
71 breakpoint
70 located k p_hsType
72 located k p_hsType
71− TyVarSig NoExtField bndr -> Just $ do
73+ TyVarSig NoExt bndr -> Just $ do
72− equals
74+ if injAnn then txt "=" else txt "::"
73 breakpoint
75 breakpoint
74 located bndr p_hsTyVarBndr
76 located bndr p_hsTyVarBndr
75− XFamilyResultSig x ->
77+ XFamilyResultSig NoExt ->
76− noExtCon x
78+ notImplemented "XFamilyResultSig"
77
79
78p_injectivityAnn :: InjectivityAnn GhcPs -> R ()
80p_injectivityAnn :: InjectivityAnn GhcPs -> R ()
79p_injectivityAnn (InjectivityAnn a bs) = do
81p_injectivityAnn (InjectivityAnn a bs) = do
@@ -86,26 +88,19 @@ p_injectivityAnn (InjectivityAnn a bs) = do
86 sep space p_rdrName bs
88 sep space p_rdrName bs
87
89
88p_tyFamInstEqn :: TyFamInstEqn GhcPs -> R ()
90p_tyFamInstEqn :: TyFamInstEqn GhcPs -> R ()
89−p_tyFamInstEqn HsIB {hsib_body = FamEqn {..}} = do
91+p_tyFamInstEqn HsIB {..} = do
90− case feqn_bndrs of
92+ let FamEqn {..} = hsib_body
91− Nothing -> return ()
93+ switchLayout (getLoc feqn_tycon : (getLoc <$> feqn_pats)) $
92− Just bndrs -> do
93− p_forallBndrs ForallInvis p_hsTyVarBndr bndrs
94− breakpoint
95− inciIf (not $ null feqn_bndrs) $ do
96− let famLhsSpn = getLoc feqn_tycon : fmap (getLoc . typeArgToType) feqn_pats
97− switchLayout famLhsSpn $
98− p_infixDefHelper
94+ p_infixDefHelper
99− (isInfix feqn_fixity)
95+ (isInfix feqn_fixity)
100− True
96+ inci
101− (p_rdrName feqn_tycon)
97+ (p_rdrName feqn_tycon)
102− (located' p_hsType . typeArgToType <$> feqn_pats)
98+ (located' p_hsType <$> feqn_pats)
103− space
99+ space
104− equals
100+ txt "="
105− breakpoint
101+ breakpoint
106− inci (located feqn_rhs p_hsType)
102+ inci (located feqn_rhs p_hsType)
107−p_tyFamInstEqn HsIB {hsib_body = XFamEqn x} = noExtCon x
103+p_tyFamInstEqn (XHsImplicitBndrs NoExt) = notImplemented "XHsImplicitBndrs"
108−p_tyFamInstEqn (XHsImplicitBndrs x) = noExtCon x
109
104
110----------------------------------------------------------------------------
105----------------------------------------------------------------------------
111-- Helpers
106-- Helpers
src/Ormolu/Printer/Meat/Declaration/Value.hs+330−419
@@ -1,8 +1,6 @@
1{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE LambdaCase #-}
2−{-# LANGUAGE MultiWayIf #-}
3{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
4{-# LANGUAGE RecordWildCards #-}
3{-# LANGUAGE RecordWildCards #-}
5−{-# LANGUAGE TypeApplications #-}
6
4
7module Ormolu.Printer.Meat.Declaration.Value
5module Ormolu.Printer.Meat.Declaration.Value
8 ( p_valDecl,
6 ( p_valDecl,
@@ -20,22 +18,23 @@ import Ctype (is_space)
20import Data.Bool (bool)
18import Data.Bool (bool)
21import Data.Char (isPunctuation, isSymbol)
19import Data.Char (isPunctuation, isSymbol)
22import Data.Data hiding (Infix, Prefix)
20import Data.Data hiding (Infix, Prefix)
23−import Data.Functor ((<&>))
24import Data.List (intersperse, sortOn)
21import Data.List (intersperse, sortOn)
25−import Data.List.NonEmpty (NonEmpty (..), (<|))
22+import Data.List.NonEmpty ((<|), NonEmpty ((:|)))
26import qualified Data.List.NonEmpty as NE
23import qualified Data.List.NonEmpty as NE
27import Data.Text (Text)
24import Data.Text (Text)
28import qualified Data.Text as Text
25import qualified Data.Text as Text
29import GHC
26import GHC
30−import OccName (occNameString)
27+import OccName (mkVarOcc)
31import Ormolu.Printer.Combinators
28import Ormolu.Printer.Combinators
32−import Ormolu.Printer.Internal
33import Ormolu.Printer.Meat.Common
29import Ormolu.Printer.Meat.Common
34import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration
30import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration
35import Ormolu.Printer.Meat.Declaration.Signature
31import Ormolu.Printer.Meat.Declaration.Signature
36import Ormolu.Printer.Meat.Type
32import Ormolu.Printer.Meat.Type
37import Ormolu.Printer.Operators
33import Ormolu.Printer.Operators
38import Ormolu.Utils
34import Ormolu.Utils
35+import RdrName (RdrName (..))
36+import RdrName (rdrNameOcc)
37+import SrcLoc (combineSrcSpans, isOneLineSpan)
39
38
40-- | Style of a group of equations.
39-- | Style of a group of equations.
41data MatchGroupStyle
40data MatchGroupStyle
@@ -61,16 +60,16 @@ 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
68− FunBind NoExtField funId funMatches _ _ -> p_funBind funId funMatches
67+ FunBind NoExt funId funMatches _ _ -> p_funBind funId funMatches
69− PatBind NoExtField pat grhss _ -> p_match PatternBind False NoSrcStrict [pat] grhss
68+ PatBind NoExt pat grhss _ -> p_match PatternBind False NoSrcStrict [pat] grhss
70 VarBind {} -> notImplemented "VarBinds" -- introduced by the type checker
69 VarBind {} -> notImplemented "VarBinds" -- introduced by the type checker
71 AbsBinds {} -> notImplemented "AbsBinds" -- introduced by the type checker
70 AbsBinds {} -> notImplemented "AbsBinds" -- introduced by the type checker
72− PatSynBind NoExtField psb -> p_patSynBind psb
71+ PatSynBind NoExt psb -> p_patSynBind psb
73− XHsBindsLR x -> noExtCon x
72+ XHsBindsLR NoExt -> notImplemented "XHsBindsLR"
74
73
75p_funBind ::
74p_funBind ::
76 Located RdrName ->
75 Located RdrName ->
@@ -100,7 +99,7 @@ p_matchGroup' placer render style MG {..} = do
100 Case -> id
99 Case -> id
101 LambdaCase -> id
100 LambdaCase -> id
102 _ -> dontUseBraces
101 _ -> dontUseBraces
103− -- Since we are forcing braces on 'sepSemi' based on 'ob', we have to
102+ -- NOTE since we are forcing braces on 'sepSemi' based on 'ob', we have to
104 -- restore the brace state inside the sepsemi.
103 -- restore the brace state inside the sepsemi.
105 ub <- bool dontUseBraces useBraces <$> canUseBraces
104 ub <- bool dontUseBraces useBraces <$> canUseBraces
106 ob $ sepSemi (located' (ub . p_Match)) (unLoc mg_alts)
105 ob $ sepSemi (located' (ub . p_Match)) (unLoc mg_alts)
@@ -114,8 +113,8 @@ p_matchGroup' placer render style MG {..} = do
114 (matchStrictness m)
113 (matchStrictness m)
115 m_pats
114 m_pats
116 m_grhss
115 m_grhss
117− p_Match (XMatch x) = noExtCon x
116+ p_Match _ = notImplemented "XMatch"
118−p_matchGroup' _ _ _ (XMatchGroup x) = noExtCon x
117+p_matchGroup' _ _ _ (XMatchGroup NoExt) = notImplemented "XMatchGroup"
119
118
120-- | Function id obtained through pattern matching on 'FunBind' should not
119-- | Function id obtained through pattern matching on 'FunBind' should not
121-- be used to print the actual equations because the different ‘RdrNames’
120-- be used to print the actual equations because the different ‘RdrNames’
@@ -168,9 +167,9 @@ p_match' ::
168 -- | Equations
167 -- | Equations
169 GRHSs GhcPs (Located body) ->
168 GRHSs GhcPs (Located body) ->
170 R ()
169 R ()
171−p_match' placer render style isInfix strictness m_pats GRHSs {..} = do
170+p_match' placer render style isInfix strictness m_pats m_grhss = do
172− -- Normally, since patterns may be placed in a multi-line layout, it is
171+ -- NOTE Normally, since patterns may be placed in a multi-line layout, it
173− -- necessary to bump indentation for the pattern group so it's more
172+ -- is necessary to bump indentation for the pattern group so it's more
174 -- indented than function name. This in turn means that indentation for
173 -- indented than function name. This in turn means that indentation for
175 -- the body should also be bumped. Normally this would mean that bodies
174 -- the body should also be bumped. Normally this would mean that bodies
176 -- would start with two indentation steps applied, which is ugly, so we
175 -- would start with two indentation steps applied, which is ugly, so we
@@ -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,41 @@ 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+ let GRHSs {..} = m_grhss
227 hasGuards = withGuards grhssGRHSs
228 hasGuards = withGuards grhssGRHSs
229+ unless (length grhssGRHSs > 1) $ do
230+ case style of
231+ Function _ | hasGuards -> return ()
232+ Function _ -> space >> txt "="
233+ PatternBind -> space >> txt "="
234+ s | isCase s && hasGuards -> return ()
235+ _ -> space >> txt "->"
228− grhssSpan =
236+ let grhssSpan =
229 combineSrcSpans' $
237 combineSrcSpans' $
230 getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
238 getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
231 patGrhssSpan =
239 patGrhssSpan =
232 maybe
240 maybe
233 grhssSpan
241 grhssSpan
234− (combineSrcSpans grhssSpan . srcLocSpan . srcSpanEnd)
242+ (combineSrcSpans grhssSpan . srcLocSpan)
235 endOfPats
243 endOfPats
236 placement =
244 placement =
237 case endOfPats of
245 case endOfPats of
238 Nothing -> blockPlacement placer grhssGRHSs
246 Nothing -> blockPlacement placer grhssGRHSs
239 Just spn ->
247 Just spn ->
248+ if isOneLineSpan
240− if onTheSameLine spn grhssSpan
249+ (mkSrcSpan spn (srcSpanStart grhssSpan))
241 then blockPlacement placer grhssGRHSs
250 then blockPlacement placer grhssGRHSs
242 else Normal
251 else Normal
243 p_body = do
252 p_body = do
@@ -253,18 +262,10 @@ p_match' placer render style isInfix strictness m_pats GRHSs {..} = do
253 txt "where"
262 txt "where"
254 unless whereIsEmpty breakpoint
263 unless whereIsEmpty breakpoint
255 inci $ located grhssLocalBinds p_hsLocalBinds
264 inci $ located grhssLocalBinds p_hsLocalBinds
256− inciIf indentBody $ do
265+ 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] $
266 switchLayout [patGrhssSpan] $
265 placeHanging placement p_body
267 placeHanging placement p_body
266 inci p_where
268 inci p_where
267−p_match' _ _ _ _ _ _ (XGRHSs x) = noExtCon x
268
269
269p_grhs :: GroupStyle -> GRHS GhcPs (LHsExpr GhcPs) -> R ()
270p_grhs :: GroupStyle -> GRHS GhcPs (LHsExpr GhcPs) -> R ()
270p_grhs = p_grhs' exprPlacement p_hsExpr
271p_grhs = p_grhs' exprPlacement p_hsExpr
@@ -278,109 +279,79 @@ p_grhs' ::
278 GroupStyle ->
279 GroupStyle ->
279 GRHS GhcPs (Located body) ->
280 GRHS GhcPs (Located body) ->
280 R ()
281 R ()
281−p_grhs' placer render style (GRHS NoExtField guards body) =
282+p_grhs' placer render style (GRHS NoExt guards body) =
282 case guards of
283 case guards of
283 [] -> p_body
284 [] -> p_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
306−p_grhs' _ _ _ (XGRHS x) = noExtCon x
307+p_grhs' _ _ _ (XGRHS NoExt) = notImplemented "XGRHS"
307
308
308p_hsCmd :: HsCmd GhcPs -> R ()
309p_hsCmd :: HsCmd GhcPs -> R ()
309p_hsCmd = \case
310p_hsCmd = \case
310− HsCmdArrApp NoExtField body input arrType _ -> do
311+ HsCmdArrApp NoExt body input arrType _ -> do
311 located body p_hsExpr
312 located body p_hsExpr
312− breakpoint
313+ space
313− inci $ do
314− case arrType of
314+ case arrType of
315− HsFirstOrderApp -> txt "-<"
315+ HsFirstOrderApp -> txt "-<"
316− HsHigherOrderApp -> txt "-<<"
316+ HsHigherOrderApp -> txt "-<<"
317− placeHanging (exprPlacement (unLoc input)) $
317+ placeHanging (exprPlacement (unLoc input)) $
318− located input p_hsExpr
318+ located input p_hsExpr
319− HsCmdArrForm NoExtField form Prefix _ cmds -> banana $ do
319+ HsCmdArrForm NoExt form Prefix _ cmds -> banana $ sitcc $ do
320 located form p_hsExpr
320 located form p_hsExpr
321 unless (null cmds) $ do
321 unless (null cmds) $ do
322 breakpoint
322 breakpoint
323 inci (sequence_ (intersperse breakpoint (located' p_hsCmdTop <$> cmds)))
323 inci (sequence_ (intersperse breakpoint (located' p_hsCmdTop <$> cmds)))
324− HsCmdArrForm NoExtField form Infix _ [left, right] -> do
324+ HsCmdArrForm NoExt form Infix _ [left, right] -> do
325 located left p_hsCmdTop
325 located left p_hsCmdTop
326 space
326 space
327 located form p_hsExpr
327 located form p_hsExpr
328 placeHanging (cmdTopPlacement (unLoc right)) $
328 placeHanging (cmdTopPlacement (unLoc right)) $
329 located right p_hsCmdTop
329 located right p_hsCmdTop
330− HsCmdArrForm NoExtField _ Infix _ _ -> notImplemented "HsCmdArrForm"
330+ HsCmdArrForm NoExt _ Infix _ _ -> notImplemented "HsCmdArrForm"
331 HsCmdApp {} ->
331 HsCmdApp {} ->
332 -- XXX Does this ever occur in the syntax tree? It does not seem like it
332 -- XXX Does this ever occur in the syntax tree? It does not seem like it
333 -- does. Open an issue and ping @yumiova if this ever occurs in output.
333 -- does. Open an issue and ping @yumiova if this ever occurs in output.
334 notImplemented "HsCmdApp"
334 notImplemented "HsCmdApp"
335− HsCmdLam NoExtField mgroup -> p_matchGroup' cmdPlacement p_hsCmd Lambda mgroup
335+ HsCmdLam NoExt mgroup -> p_matchGroup' cmdPlacement p_hsCmd Lambda mgroup
336− HsCmdPar NoExtField c -> parens N (located c p_hsCmd)
336+ HsCmdPar NoExt c -> parens N (located c p_hsCmd)
337− HsCmdCase NoExtField e mgroup ->
337+ HsCmdCase NoExt e mgroup ->
338 p_case cmdPlacement p_hsCmd e mgroup
338 p_case cmdPlacement p_hsCmd e mgroup
339− HsCmdIf NoExtField _ if' then' else' ->
339+ HsCmdIf NoExt _ if' then' else' ->
340 p_if cmdPlacement p_hsCmd if' then' else'
340 p_if cmdPlacement p_hsCmd if' then' else'
341− HsCmdLet NoExtField localBinds c ->
341+ HsCmdLet NoExt localBinds c ->
342 p_let p_hsCmd localBinds c
342 p_let p_hsCmd localBinds c
343− HsCmdDo NoExtField es -> do
343+ HsCmdDo NoExt es -> do
344 txt "do"
344 txt "do"
345 newline
345 newline
346 inci . located es $
346 inci . located es $
347− sitcc . sep newline (sitcc . withSpacing (p_stmt' cmdPlacement p_hsCmd))
347+ sitcc . sep newline (located' (sitcc . p_stmt' cmdPlacement p_hsCmd))
348 HsCmdWrap {} -> notImplemented "HsCmdWrap"
348 HsCmdWrap {} -> notImplemented "HsCmdWrap"
349− XCmd x -> noExtCon x
349+ XCmd {} -> notImplemented "XCmd"
350
350
351p_hsCmdTop :: HsCmdTop GhcPs -> R ()
351p_hsCmdTop :: HsCmdTop GhcPs -> R ()
352p_hsCmdTop = \case
352p_hsCmdTop = \case
353− HsCmdTop NoExtField cmd -> located cmd p_hsCmd
353+ HsCmdTop NoExt cmd -> located cmd p_hsCmd
354− XCmdTop x -> noExtCon x
354+ XCmdTop {} -> notImplemented "XHsCmdTop"
355−
356−-- | Render an expression preserving blank lines between such consecutive
357−-- expressions found in the original source code.
358−withSpacing ::
359− -- | Rendering function
360− (a -> R ()) ->
361− -- | Entity to render
362− Located a ->
363− R ()
364−withSpacing f l = located l $ \x -> do
365− case getLoc l of
366− UnhelpfulSpan _ -> f x
367− RealSrcSpan currentSpn -> do
368− getSpanMark >>= \case
369− -- Spacing before comments will be handled by the code
370− -- that prints comments, so we just have to deal with
371− -- blank lines between statements here.
372− Just (StatementSpan lastSpn) ->
373− if srcSpanStartLine currentSpn > srcSpanEndLine lastSpn + 1
374− then newline
375− else return ()
376− _ -> return ()
377− f x
378− -- In some cases the (f x) expression may insert a new mark. We want
379− -- to be careful not to override comment marks.
380− getSpanMark >>= \case
381− Just (HaddockSpan _ _) -> return ()
382− Just (CommentSpan _) -> return ()
383− _ -> setSpanMark (StatementSpan currentSpn)
384
355
385p_stmt :: Stmt GhcPs (LHsExpr GhcPs) -> R ()
356p_stmt :: Stmt GhcPs (LHsExpr GhcPs) -> R ()
386p_stmt = p_stmt' exprPlacement p_hsExpr
357p_stmt = p_stmt' exprPlacement p_hsExpr
@@ -395,36 +366,35 @@ p_stmt' ::
395 Stmt GhcPs (Located body) ->
366 Stmt GhcPs (Located body) ->
396 R ()
367 R ()
397p_stmt' placer render = \case
368p_stmt' placer render = \case
398− LastStmt NoExtField body _ _ -> located body render
369+ LastStmt NoExt body _ _ -> located body render
399− BindStmt NoExtField p f _ _ -> do
370+ BindStmt NoExt l f _ _ -> do
400− located p p_pat
371+ located l p_pat
401 space
372 space
402 txt "<-"
373 txt "<-"
403− let loc = getLoc p
404− placement =
374+ let placement =
405 case f of
375 case f of
406 L l' x ->
376 L l' x ->
407 if isOneLineSpan
377 if isOneLineSpan
408− (mkSrcSpan (srcSpanEnd loc) (srcSpanStart l'))
378+ (mkSrcSpan (srcSpanEnd (getLoc l)) (srcSpanStart l'))
409 then placer x
379 then placer x
410 else Normal
380 else Normal
411− switchLayout [loc, getLoc f] $
381+ switchLayout [getLoc l, getLoc f] $
412 placeHanging placement (located f render)
382 placeHanging placement (located f render)
413 ApplicativeStmt {} -> notImplemented "ApplicativeStmt" -- generated by renamer
383 ApplicativeStmt {} -> notImplemented "ApplicativeStmt" -- generated by renamer
414− BodyStmt NoExtField body _ _ -> located body render
384+ BodyStmt NoExt body _ _ -> located body render
415− LetStmt NoExtField binds -> do
385+ LetStmt NoExt binds -> do
416 txt "let"
386 txt "let"
417 space
387 space
418 sitcc $ located binds p_hsLocalBinds
388 sitcc $ located binds p_hsLocalBinds
419 ParStmt {} ->
389 ParStmt {} ->
420− -- 'ParStmt' should always be eliminated in 'gatherStmt' already, such
390+ -- NOTE 'ParStmt' should always be eliminated in 'gatherStmt' already,
421− -- that it never occurs in 'p_stmt''. Consequently, handling it here
391+ -- such that it never occurs in 'p_stmt''. Consequently, handling it
422− -- would be redundant.
392+ -- here would be redundant.
423 notImplemented "ParStmt"
393 notImplemented "ParStmt"
424− TransStmt {..} ->
394+ TransStmt {..} -> do
425− -- 'TransStmt' only needs to account for render printing itself, since
395+ -- NOTE 'TransStmt' only needs to account for render printing itself,
426− -- pretty printing of relevant statements (e.g., in 'trS_stmts') is
396+ -- since pretty printing of relevant statements (e.g., in 'trS_stmts')
427− -- handled through 'gatherStmt'.
397+ -- is handled through 'gatherStmt'.
428 case (trS_form, trS_by) of
398 case (trS_form, trS_by) of
429 (ThenForm, Nothing) -> do
399 (ThenForm, Nothing) -> do
430 txt "then"
400 txt "then"
@@ -453,11 +423,11 @@ p_stmt' placer render = \case
453 RecStmt {..} -> do
423 RecStmt {..} -> do
454 txt "rec"
424 txt "rec"
455 space
425 space
456− sitcc $ sepSemi (withSpacing (p_stmt' placer render)) recS_stmts
426+ sitcc $ sepSemi (located' (p_stmt' placer render)) recS_stmts
457− XStmtLR c -> noExtCon c
427+ XStmtLR {} -> notImplemented "XStmtLR"
458
428
459gatherStmt :: ExprLStmt GhcPs -> [[ExprLStmt GhcPs]]
429gatherStmt :: ExprLStmt GhcPs -> [[ExprLStmt GhcPs]]
460−gatherStmt (L _ (ParStmt NoExtField block _ _)) =
430+gatherStmt (L _ (ParStmt NoExt block _ _)) =
461 foldr ((<>) . gatherStmtBlock) [] block
431 foldr ((<>) . gatherStmtBlock) [] block
462gatherStmt (L s stmt@TransStmt {..}) =
432gatherStmt (L s stmt@TransStmt {..}) =
463 foldr liftAppend [] ((gatherStmt <$> trS_stmts) <> pure [[L s stmt]])
433 foldr liftAppend [] ((gatherStmt <$> trS_stmts) <> pure [[L s stmt]])
@@ -466,93 +436,96 @@ gatherStmt stmt = [[stmt]]
466gatherStmtBlock :: ParStmtBlock GhcPs GhcPs -> [[ExprLStmt GhcPs]]
436gatherStmtBlock :: ParStmtBlock GhcPs GhcPs -> [[ExprLStmt GhcPs]]
467gatherStmtBlock (ParStmtBlock _ stmts _ _) =
437gatherStmtBlock (ParStmtBlock _ stmts _ _) =
468 foldr (liftAppend . gatherStmt) [] stmts
438 foldr (liftAppend . gatherStmt) [] stmts
469−gatherStmtBlock (XParStmtBlock x) = noExtCon x
439+gatherStmtBlock XParStmtBlock {} = notImplemented "XParStmtBlock"
470
440
471p_hsLocalBinds :: HsLocalBindsLR GhcPs GhcPs -> R ()
441p_hsLocalBinds :: HsLocalBindsLR GhcPs GhcPs -> R ()
472p_hsLocalBinds = \case
442p_hsLocalBinds = \case
473− HsValBinds NoExtField (ValBinds NoExtField bag lsigs) -> do
443+ HsValBinds NoExt (ValBinds NoExt bag lsigs) -> do
444+ let ssStart =
445+ either
446+ (srcSpanStart . getLoc)
447+ (srcSpanStart . getLoc)
448+ items =
449+ (Left <$> bagToList bag) ++ (Right <$> lsigs)
450+ p_item (Left x) = located x p_valDecl
451+ p_item (Right x) = located x p_sigDecl
452+ -- Assigns 'False' to the last element, 'True' to the rest.
453+ markInit :: [a] -> [(Bool, a)]
454+ markInit [] = []
455+ markInit (x : []) = [(False, x)]
456+ markInit (x : xs) = (True, x) : markInit xs
474− -- When in a single-line layout, there is a chance that the inner
457+ -- NOTE When in a single-line layout, there is a chance that the inner
475 -- elements will also contain semicolons and they will confuse the
458 -- elements will also contain semicolons and they will confuse the
476 -- parser. so we request braces around every element except the last.
459 -- parser. so we request braces around every element except the last.
477 br <- layoutToBraces <$> getLayout
460 br <- layoutToBraces <$> getLayout
478− let items =
461+ sitcc $
479− let injectLeft (L l x) = L l (Left x)
462+ sepSemi
480− injectRight (L l x) = L l (Right x)
463+ (\(m, i) -> (if m then br else id) $ p_item i)
481− in (injectLeft <$> bagToList bag) ++ (injectRight <$> lsigs)
464+ (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"
465+ HsValBinds NoExt _ -> notImplemented "HsValBinds"
493− HsIPBinds NoExtField (IPBinds NoExtField xs) ->
466+ HsIPBinds NoExt (IPBinds NoExt xs) ->
494 -- Second argument of IPBind is always Left before type-checking.
467 -- Second argument of IPBind is always Left before type-checking.
495− let p_ipBind (IPBind NoExtField (Left name) expr) = do
468+ let p_ipBind (IPBind NoExt (Left name) expr) = do
496 atom name
469 atom name
497 space
470 space
498− equals
471+ txt "="
499 breakpoint
472 breakpoint
500 useBraces $ inci $ located expr p_hsExpr
473 useBraces $ inci $ located expr p_hsExpr
501− p_ipBind (IPBind NoExtField (Right _) _) =
502− -- Should only occur after the type checker
503− notImplemented "IPBind _ (Right _) _"
474+ p_ipBind _ = notImplemented "XHsIPBinds"
504− p_ipBind (XIPBind x) = noExtCon x
505 in sepSemi (located' p_ipBind) xs
475 in sepSemi (located' p_ipBind) xs
506− HsIPBinds NoExtField _ -> notImplemented "HsIpBinds"
476+ HsIPBinds NoExt _ -> notImplemented "HsIpBinds"
507− EmptyLocalBinds NoExtField -> return ()
477+ EmptyLocalBinds NoExt -> return ()
508− XHsLocalBindsLR x -> noExtCon x
478+ XHsLocalBindsLR _ -> notImplemented "XHsLocalBindsLR"
509
479
510p_hsRecField ::
480p_hsRecField ::
511 HsRecField' RdrName (LHsExpr GhcPs) ->
481 HsRecField' RdrName (LHsExpr GhcPs) ->
512 R ()
482 R ()
513−p_hsRecField HsRecField {..} = do
483+p_hsRecField = \HsRecField {..} -> do
514 p_rdrName hsRecFieldLbl
484 p_rdrName hsRecFieldLbl
515 unless hsRecPun $ do
485 unless hsRecPun $ do
516 space
486 space
517− equals
487+ txt "="
518− let placement =
519− if onTheSameLine (getLoc hsRecFieldLbl) (getLoc hsRecFieldArg)
520− then exprPlacement (unLoc hsRecFieldArg)
488+ let placement = exprPlacement (unLoc hsRecFieldArg)
521− else Normal
522− placeHanging placement (located hsRecFieldArg p_hsExpr)
489+ placeHanging placement $ located hsRecFieldArg p_hsExpr
490+
491+p_hsTupArg :: HsTupArg GhcPs -> R ()
492+p_hsTupArg = \case
493+ Present NoExt x -> located x p_hsExpr
494+ Missing NoExt -> pure ()
495+ XTupArg {} -> notImplemented "XTupArg"
523
496
524p_hsExpr :: HsExpr GhcPs -> R ()
497p_hsExpr :: HsExpr GhcPs -> R ()
525p_hsExpr = p_hsExpr' N
498p_hsExpr = p_hsExpr' N
526
499
527p_hsExpr' :: BracketStyle -> HsExpr GhcPs -> R ()
500p_hsExpr' :: BracketStyle -> HsExpr GhcPs -> R ()
528p_hsExpr' s = \case
501p_hsExpr' s = \case
529− HsVar NoExtField name -> p_rdrName name
502+ HsVar NoExt name -> p_rdrName name
530− HsUnboundVar NoExtField v -> atom (unboundVarOcc v)
503+ HsUnboundVar NoExt _ -> notImplemented "HsUnboundVar"
531− HsConLikeOut NoExtField _ -> notImplemented "HsConLikeOut"
504+ HsConLikeOut NoExt _ -> notImplemented "HsConLikeOut"
532− HsRecFld NoExtField x ->
505+ HsRecFld NoExt x ->
533 case x of
506 case x of
534− Unambiguous NoExtField name -> p_rdrName name
507+ Unambiguous NoExt name -> p_rdrName name
535− Ambiguous NoExtField name -> p_rdrName name
508+ Ambiguous NoExt name -> p_rdrName name
536− XAmbiguousFieldOcc xx -> noExtCon xx
509+ XAmbiguousFieldOcc NoExt -> notImplemented "XAmbiguousFieldOcc"
537− HsOverLabel NoExtField _ v -> do
510+ HsOverLabel NoExt _ v -> do
538 txt "#"
511 txt "#"
539 atom v
512 atom v
540− HsIPVar NoExtField (HsIPName name) -> do
513+ HsIPVar NoExt (HsIPName name) -> do
541 txt "?"
514 txt "?"
542 atom name
515 atom name
543− HsOverLit NoExtField v -> atom (ol_val v)
516+ HsOverLit NoExt v -> atom (ol_val v)
544− HsLit NoExtField lit ->
517+ HsLit NoExt lit ->
545 case lit of
518 case lit of
546 HsString (SourceText stxt) _ -> p_stringLit stxt
519 HsString (SourceText stxt) _ -> p_stringLit stxt
547 HsStringPrim (SourceText stxt) _ -> p_stringLit stxt
520 HsStringPrim (SourceText stxt) _ -> p_stringLit stxt
548 r -> atom r
521 r -> atom r
549− HsLam NoExtField mgroup ->
522+ HsLam NoExt mgroup ->
550 p_matchGroup Lambda mgroup
523 p_matchGroup Lambda mgroup
551− HsLamCase NoExtField mgroup -> do
524+ HsLamCase NoExt mgroup -> do
552 txt "\\case"
525 txt "\\case"
553 breakpoint
526 breakpoint
554 inci (p_matchGroup LambdaCase mgroup)
527 inci (p_matchGroup LambdaCase mgroup)
555− HsApp NoExtField f x -> do
528+ HsApp NoExt f x -> do
556 let -- In order to format function applications with multiple parameters
529 let -- In order to format function applications with multiple parameters
557 -- nicer, traverse the AST to gather the function and all the
530 -- nicer, traverse the AST to gather the function and all the
558 -- parameters together.
531 -- parameters together.
@@ -564,10 +537,8 @@ p_hsExpr' s = \case
564 -- We need to handle the last argument specially if it is a
537 -- We need to handle the last argument specially if it is a
565 -- hanging construct, so separate it from the rest.
538 -- hanging construct, so separate it from the rest.
566 (initp, lastp) = (NE.init args, NE.last args)
539 (initp, lastp) = (NE.init args, NE.last args)
567− initSpan =
568− combineSrcSpans' $
540+ initSpan = combineSrcSpans' $ getLoc f :| map getLoc initp
569− getLoc f :| [(srcLocSpan . srcSpanStart . getLoc) lastp]
570− -- Hang the last argument only if the initial arguments span one
541+ -- Hang the last argument only if the initial arguments spans one
571 -- line.
542 -- line.
572 placement =
543 placement =
573 if isOneLineSpan initSpan
544 if isOneLineSpan initSpan
@@ -579,26 +550,11 @@ p_hsExpr' s = \case
579 -- one.
550 -- one.
580 case placement of
551 case placement of
581 Normal -> do
552 Normal -> do
582− let -- Usually we want to bump indentation for arguments for the
583− -- sake of readability. However, when the function itself is a
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
586− -- expression is parenthesised.
587− doIndent =
588− case func of
589− L _ (HsPar NoExtField _) -> True
590− L _ (HsAppType NoExtField _ _) -> True
591− L _ (HsMultiIf NoExtField _) -> True
592− L spn _ -> isOneLineSpan spn
593− ub <-
594− getLayout <&> \case
595− SingleLine -> useBraces
553+ useBraces $ do
596− MultiLine -> id
597− ub $ do
598 located func (p_hsExpr' s)
554 located func (p_hsExpr' s)
599 breakpoint
555 breakpoint
600− inciIf doIndent $ sep breakpoint (located' p_hsExpr) initp
556+ inci $ sep breakpoint (located' p_hsExpr) initp
601− inciIf doIndent $ do
557+ inci $ do
602 unless (null initp) breakpoint
558 unless (null initp) breakpoint
603 located lastp p_hsExpr
559 located lastp p_hsExpr
604 Hanging -> do
560 Hanging -> do
@@ -608,87 +564,75 @@ p_hsExpr' s = \case
608 sep breakpoint (located' p_hsExpr) initp
564 sep breakpoint (located' p_hsExpr) initp
609 placeHanging placement $
565 placeHanging placement $
610 located lastp p_hsExpr
566 located lastp p_hsExpr
611− HsAppType NoExtField e a -> do
567+ HsAppType a e -> do
612 located e p_hsExpr
568 located e p_hsExpr
613 breakpoint
569 breakpoint
614 inci $ do
570 inci $ do
615 txt "@"
571 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
572 located (hswc_body a) p_hsType
622− OpApp NoExtField x op y -> do
573+ OpApp NoExt x op y -> do
623 let opTree = OpBranch (exprOpTree x) op (exprOpTree y)
574 let opTree = OpBranch (exprOpTree x) op (exprOpTree y)
624− p_exprOpTree s (reassociateOpTree getOpName opTree)
575+ p_exprOpTree True s (reassociateOpTree getOpName opTree)
625− NegApp NoExtField e _ -> do
576+ NegApp NoExt e _ -> do
626 txt "-"
577 txt "-"
627 space
578 space
628 located e p_hsExpr
579 located e p_hsExpr
629− HsPar NoExtField e ->
580+ HsPar NoExt e ->
630 parens s (located e (dontUseBraces . p_hsExpr))
581 parens s (located e (dontUseBraces . p_hsExpr))
631− SectionL NoExtField x op -> do
582+ SectionL NoExt x op -> do
632 located x p_hsExpr
583 located x p_hsExpr
633 breakpoint
584 breakpoint
634 inci (located op p_hsExpr)
585 inci (located op p_hsExpr)
635− SectionR NoExtField op x -> do
586+ SectionR NoExt op x -> do
636 located op p_hsExpr
587 located op p_hsExpr
637− useRecordDot' <- useRecordDot
638− let isRecordDot' = isRecordDot (unLoc op) (getLoc x)
639− unless (useRecordDot' && isRecordDot') breakpoint
588+ breakpoint
640 inci (located x p_hsExpr)
589 inci (located x p_hsExpr)
641− ExplicitTuple NoExtField args boxity ->
590+ ExplicitTuple NoExt args boxity -> do
642 let isSection = any (isMissing . unLoc) args
591 let isSection = any (isMissing . unLoc) args
643 isMissing = \case
592 isMissing = \case
644− Missing NoExtField -> True
593+ Missing NoExt -> True
645 _ -> False
594 _ -> 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' =
595+ let parens' =
652 case boxity of
596 case boxity of
653 Boxed -> parens
597 Boxed -> parens
654 Unboxed -> parensHash
598 Unboxed -> parensHash
655− in if isSection
599+ if isSection
656− then
600+ then
657− switchLayout [] . parens' s $
601+ switchLayout [] . parens' s $
658− sep comma p_larg args
602+ sep comma (located' p_hsTupArg) args
659− else
603+ else
660− switchLayout (getLoc <$> args) . parens' s $
604+ switchLayout (getLoc <$> args) . parens' s . sitcc $
661− sep commaDel p_larg args
605+ sep (comma >> breakpoint) (sitcc . located' p_hsTupArg) args
662− ExplicitSum NoExtField tag arity e ->
606+ ExplicitSum NoExt tag arity e ->
663 p_unboxedSum N tag arity (located e p_hsExpr)
607 p_unboxedSum N tag arity (located e p_hsExpr)
664− HsCase NoExtField e mgroup ->
608+ HsCase NoExt e mgroup ->
665 p_case exprPlacement p_hsExpr e mgroup
609 p_case exprPlacement p_hsExpr e mgroup
666− HsIf NoExtField _ if' then' else' ->
610+ HsIf NoExt _ if' then' else' ->
667 p_if exprPlacement p_hsExpr if' then' else'
611 p_if exprPlacement p_hsExpr if' then' else'
668− HsMultiIf NoExtField guards -> do
612+ HsMultiIf NoExt guards -> do
669 txt "if"
613 txt "if"
670 breakpoint
614 breakpoint
671− inci . inci $ sep newline (located' (p_grhs RightArrow)) guards
615+ inci . sitcc $ sep newline (located' (p_grhs RightArrow)) guards
672− HsLet NoExtField localBinds e ->
616+ HsLet NoExt localBinds e ->
673 p_let p_hsExpr localBinds e
617 p_let p_hsExpr localBinds e
674− HsDo NoExtField ctx es -> do
618+ HsDo NoExt ctx es -> do
675 let doBody header = do
619 let doBody header = do
676 txt header
620 txt header
677 breakpoint
621 breakpoint
678 ub <- layoutToBraces <$> getLayout
622 ub <- layoutToBraces <$> getLayout
679 inci $
623 inci $
680 sepSemi
624 sepSemi
681− (ub . withSpacing (p_stmt' exprPlacement (p_hsExpr' S)))
625+ (located' (ub . p_stmt' exprPlacement (p_hsExpr' S)))
682 (unLoc es)
626 (unLoc es)
683− compBody = brackets N . located es $ \xs -> do
627+ compBody = brackets N $ located es $ \xs -> do
684 let p_parBody =
628 let p_parBody =
685 sep
629 sep
686− (breakpoint >> txt "|" >> space)
630+ (breakpoint >> txt "| ")
687 p_seqBody
631 p_seqBody
688 p_seqBody =
632 p_seqBody =
689 sitcc
633 sitcc
690 . sep
634 . sep
691− commaDel
635+ (comma >> breakpoint)
692 (located' (sitcc . p_stmt))
636 (located' (sitcc . p_stmt))
693 stmts = init xs
637 stmts = init xs
694 yield = last xs
638 yield = last xs
@@ -709,94 +653,88 @@ p_hsExpr' s = \case
709 ParStmtCtxt _ -> notImplemented "ParStmtCtxt"
653 ParStmtCtxt _ -> notImplemented "ParStmtCtxt"
710 TransStmtCtxt _ -> notImplemented "TransStmtCtxt"
654 TransStmtCtxt _ -> notImplemented "TransStmtCtxt"
711 ExplicitList _ _ xs ->
655 ExplicitList _ _ xs ->
712− brackets s $
656+ brackets s . sitcc $
713− sep commaDel (sitcc . located' p_hsExpr) xs
657+ sep (comma >> breakpoint) (sitcc . located' p_hsExpr) xs
714 RecordCon {..} -> do
658 RecordCon {..} -> do
715 located rcon_con_name atom
659 located rcon_con_name atom
716 breakpoint
660 breakpoint
717 let HsRecFields {..} = rcon_flds
661 let HsRecFields {..} = rcon_flds
718 updName f =
662 updName f =
719− (f :: HsRecField GhcPs (LHsExpr GhcPs))
663+ f
720 { hsRecFieldLbl = case unLoc $ hsRecFieldLbl f of
664 { hsRecFieldLbl = case unLoc $ hsRecFieldLbl f of
721 FieldOcc _ n -> n
665 FieldOcc _ n -> n
722− XFieldOcc x -> noExtCon x
666+ XFieldOcc _ -> notImplemented "XFieldOcc"
723 }
667 }
724 fields = located' (p_hsRecField . updName) <$> rec_flds
668 fields = located' (p_hsRecField . updName) <$> rec_flds
725 dotdot =
669 dotdot =
726 case rec_dotdot of
670 case rec_dotdot of
727 Just {} -> [txt ".."]
671 Just {} -> [txt ".."]
728 Nothing -> []
672 Nothing -> []
729− inci . braces N $
673+ inci . braces N . sitcc $
730− sep commaDel sitcc (fields <> dotdot)
674+ sep (comma >> breakpoint) sitcc (fields <> dotdot)
731 RecordUpd {..} -> do
675 RecordUpd {..} -> do
732 located rupd_expr p_hsExpr
676 located rupd_expr p_hsExpr
733− useRecordDot' <- useRecordDot
734− let mrs sp = case getLoc sp of
735− RealSrcSpan r -> Just r
736− _ -> Nothing
737− let isPluginForm =
738− ((1 +) . srcSpanEndCol <$> mrs rupd_expr)
739− == (srcSpanStartCol <$> mrs (head rupd_flds))
740− unless (useRecordDot' && isPluginForm) breakpoint
677+ breakpoint
741 let updName f =
678 let updName f =
742− (f :: HsRecUpdField GhcPs)
679+ f
743 { hsRecFieldLbl = case unLoc $ hsRecFieldLbl f of
680 { hsRecFieldLbl = case unLoc $ hsRecFieldLbl f of
744 Ambiguous _ n -> n
681 Ambiguous _ n -> n
745 Unambiguous _ n -> n
682 Unambiguous _ n -> n
746− XAmbiguousFieldOcc x -> noExtCon x
683+ XAmbiguousFieldOcc _ -> notImplemented "XAmbiguousFieldOcc"
747 }
684 }
748− inci . braces N $
685+ inci . braces N . sitcc $
749 sep
686 sep
750− commaDel
687+ (comma >> breakpoint)
751 (sitcc . located' (p_hsRecField . updName))
688 (sitcc . located' (p_hsRecField . updName))
752 rupd_flds
689 rupd_flds
753− ExprWithTySig NoExtField x HsWC {hswc_body = HsIB {..}} -> sitcc $ do
690+ ExprWithTySig affix x -> sitcc $ do
754 located x p_hsExpr
691 located x p_hsExpr
755 space
692 space
756 txt "::"
693 txt "::"
757 breakpoint
694 breakpoint
695+ inci $ do
696+ let HsWC {..} = affix
697+ HsIB {..} = hswc_body
758− inci $ located hsib_body p_hsType
698+ located hsib_body p_hsType
759− ExprWithTySig NoExtField _ HsWC {hswc_body = XHsImplicitBndrs x} -> noExtCon x
760− ExprWithTySig NoExtField _ (XHsWildCardBndrs x) -> noExtCon x
761− ArithSeq NoExtField _ x ->
699+ ArithSeq NoExt _ x -> do
762 case x of
700 case x of
763− From from -> brackets s $ do
701+ From from -> brackets s . sitcc $ do
764 located from p_hsExpr
702 located from p_hsExpr
765 breakpoint
703 breakpoint
766 txt ".."
704 txt ".."
767− FromThen from next -> brackets s $ do
705+ FromThen from next -> brackets s . sitcc $ do
768− sep commaDel (located' p_hsExpr) [from, next]
706+ sitcc $ sep (comma >> breakpoint) (located' p_hsExpr) [from, next]
769 breakpoint
707 breakpoint
770 txt ".."
708 txt ".."
771− FromTo from to -> brackets s $ do
709+ FromTo from to -> brackets s . sitcc $ do
772 located from p_hsExpr
710 located from p_hsExpr
773 breakpoint
711 breakpoint
774 txt ".."
712 txt ".."
775 space
713 space
776 located to p_hsExpr
714 located to p_hsExpr
777− FromThenTo from next to -> brackets s $ do
715+ FromThenTo from next to -> brackets s . sitcc $ do
778− sep commaDel (located' p_hsExpr) [from, next]
716+ sitcc $ sep (comma >> breakpoint) (located' p_hsExpr) [from, next]
779 breakpoint
717 breakpoint
780 txt ".."
718 txt ".."
781 space
719 space
782 located to p_hsExpr
720 located to p_hsExpr
783− HsSCC NoExtField _ name x -> do
721+ HsSCC NoExt _ name x -> do
784 txt "{-# SCC "
722 txt "{-# SCC "
785 atom name
723 atom name
786 txt " #-}"
724 txt " #-}"
787 breakpoint
725 breakpoint
788 located x p_hsExpr
726 located x p_hsExpr
789− HsCoreAnn NoExtField _ value x -> do
727+ HsCoreAnn NoExt _ value x -> do
790 txt "{-# CORE "
728 txt "{-# CORE "
791 atom value
729 atom value
792 txt " #-}"
730 txt " #-}"
793 breakpoint
731 breakpoint
794 located x p_hsExpr
732 located x p_hsExpr
795− HsBracket NoExtField x -> p_hsBracket x
733+ HsBracket NoExt x -> p_hsBracket x
796 HsRnBracketOut {} -> notImplemented "HsRnBracketOut"
734 HsRnBracketOut {} -> notImplemented "HsRnBracketOut"
797 HsTcBracketOut {} -> notImplemented "HsTcBracketOut"
735 HsTcBracketOut {} -> notImplemented "HsTcBracketOut"
798− HsSpliceE NoExtField splice -> p_hsSplice splice
736+ HsSpliceE NoExt splice -> p_hsSplice splice
799− HsProc NoExtField p e -> do
737+ HsProc NoExt p e -> do
800 txt "proc"
738 txt "proc"
801 located p $ \x -> do
739 located p $ \x -> do
802 breakpoint
740 breakpoint
@@ -809,11 +747,31 @@ p_hsExpr' s = \case
809 txt "static"
747 txt "static"
810 breakpoint
748 breakpoint
811 inci (located e p_hsExpr)
749 inci (located e p_hsExpr)
750+ HsArrApp NoExt body input arrType cond ->
751+ p_hsCmd (HsCmdArrApp NoExt body input arrType cond)
752+ HsArrForm NoExt form mfixity cmds ->
753+ p_hsCmd (HsCmdArrForm NoExt form Prefix mfixity cmds)
812 HsTick {} -> notImplemented "HsTick"
754 HsTick {} -> notImplemented "HsTick"
813 HsBinTick {} -> notImplemented "HsBinTick"
755 HsBinTick {} -> notImplemented "HsBinTick"
814 HsTickPragma {} -> notImplemented "HsTickPragma"
756 HsTickPragma {} -> notImplemented "HsTickPragma"
757+ -- These four constructs should never appear in correct programs.
758+ -- See: https://github.com/tweag/ormolu/issues/343
759+ EWildPat NoExt -> txt "_"
760+ EAsPat NoExt n p -> do
761+ p_rdrName n
762+ txt "@"
763+ located p p_hsExpr
764+ EViewPat NoExt p e -> do
765+ located p p_hsExpr
766+ space
767+ txt "->"
768+ breakpoint
769+ inci (located e p_hsExpr)
770+ ELazyPat NoExt p -> do
771+ txt "~"
772+ located p p_hsExpr
815 HsWrap {} -> notImplemented "HsWrap"
773 HsWrap {} -> notImplemented "HsWrap"
816− XExpr x -> noExtCon x
774+ XExpr {} -> notImplemented "XExpr"
817
775
818p_patSynBind :: PatSynBind GhcPs GhcPs -> R ()
776p_patSynBind :: PatSynBind GhcPs GhcPs -> R ()
819p_patSynBind PSB {..} = do
777p_patSynBind PSB {..} = do
@@ -825,7 +783,7 @@ p_patSynBind PSB {..} = do
825 breakpoint
783 breakpoint
826 located psb_def p_pat
784 located psb_def p_pat
827 ImplicitBidirectional -> do
785 ImplicitBidirectional -> do
828− equals
786+ txt "="
829 breakpoint
787 breakpoint
830 located psb_def p_pat
788 located psb_def p_pat
831 ExplicitBidirectional mgroup -> do
789 ExplicitBidirectional mgroup -> do
@@ -852,8 +810,8 @@ p_patSynBind PSB {..} = do
852 inci $ do
810 inci $ do
853 switchLayout (getLoc . recordPatSynPatVar <$> xs) $ do
811 switchLayout (getLoc . recordPatSynPatVar <$> xs) $ do
854 unless (null xs) breakpoint
812 unless (null xs) breakpoint
855− braces N $
813+ braces N . sitcc $
856− sep commaDel (p_rdrName . recordPatSynPatVar) xs
814+ sep (comma >> breakpoint) (p_rdrName . recordPatSynPatVar) xs
857 rhs
815 rhs
858 InfixCon l r -> do
816 InfixCon l r -> do
859 switchLayout [getLoc l, getLoc r] $ do
817 switchLayout [getLoc l, getLoc r] $ do
@@ -865,7 +823,7 @@ p_patSynBind PSB {..} = do
865 space
823 space
866 p_rdrName r
824 p_rdrName r
867 inci rhs
825 inci rhs
868−p_patSynBind (XPatSynBind x) = noExtCon x
826+p_patSynBind (XPatSynBind NoExt) = notImplemented "XPatSynBind"
869
827
870p_case ::
828p_case ::
871 Data body =>
829 Data body =>
@@ -876,7 +834,7 @@ p_case ::
876 -- | Expression
834 -- | Expression
877 LHsExpr GhcPs ->
835 LHsExpr GhcPs ->
878 -- | Match group
836 -- | Match group
879− MatchGroup GhcPs (Located body) ->
837+ (MatchGroup GhcPs (Located body)) ->
880 R ()
838 R ()
881p_case placer render e mgroup = do
839p_case placer render e mgroup = do
882 txt "case"
840 txt "case"
@@ -907,12 +865,10 @@ p_if placer render if' then' else' = do
907 breakpoint
865 breakpoint
908 inci $ do
866 inci $ do
909 txt "then"
867 txt "then"
910− space
911 located then' $ \x ->
868 located then' $ \x ->
912 placeHanging (placer x) (render x)
869 placeHanging (placer x) (render x)
913 breakpoint
870 breakpoint
914 txt "else"
871 txt "else"
915− space
916 located else' $ \x ->
872 located else' $ \x ->
917 placeHanging (placer x) (render x)
873 placeHanging (placer x) (render x)
918
874
@@ -934,29 +890,29 @@ p_let render localBinds e = sitcc $ do
934
890
935p_pat :: Pat GhcPs -> R ()
891p_pat :: Pat GhcPs -> R ()
936p_pat = \case
892p_pat = \case
937− WildPat NoExtField -> txt "_"
893+ WildPat NoExt -> txt "_"
938− VarPat NoExtField name -> p_rdrName name
894+ VarPat NoExt name -> p_rdrName name
939− LazyPat NoExtField pat -> do
895+ LazyPat NoExt pat -> do
940 txt "~"
896 txt "~"
941 located pat p_pat
897 located pat p_pat
942− AsPat NoExtField name pat -> do
898+ AsPat NoExt name pat -> do
943 p_rdrName name
899 p_rdrName name
944 txt "@"
900 txt "@"
945 located pat p_pat
901 located pat p_pat
946− ParPat NoExtField pat ->
902+ ParPat NoExt pat ->
947 located pat (parens S . p_pat)
903 located pat (parens S . p_pat)
948− BangPat NoExtField pat -> do
904+ BangPat NoExt pat -> do
949 txt "!"
905 txt "!"
950 located pat p_pat
906 located pat p_pat
951− ListPat NoExtField pats ->
907+ ListPat NoExt pats -> do
952− brackets S $ sep commaDel (located' p_pat) pats
908+ brackets S . sitcc $ sep (comma >> breakpoint) (located' p_pat) pats
953− TuplePat NoExtField pats boxing -> do
909+ TuplePat NoExt pats boxing -> do
954− let parens' =
910+ let f =
955 case boxing of
911 case boxing of
956 Boxed -> parens S
912 Boxed -> parens S
957 Unboxed -> parensHash S
913 Unboxed -> parensHash S
958− parens' $ sep commaDel (sitcc . located' p_pat) pats
914+ f . sitcc $ sep (comma >> breakpoint) (sitcc . located' p_pat) pats
959− SumPat NoExtField pat tag arity ->
915+ SumPat NoExt pat tag arity ->
960 p_unboxedSum S tag arity (located pat p_pat)
916 p_unboxedSum S tag arity (located pat p_pat)
961 ConPatIn pat details ->
917 ConPatIn pat details ->
962 case details of
918 case details of
@@ -971,40 +927,38 @@ p_pat = \case
971 let f = \case
927 let f = \case
972 Nothing -> txt ".."
928 Nothing -> txt ".."
973 Just x -> located x p_pat_hsRecField
929 Just x -> located x p_pat_hsRecField
974− inci . braces N . sep commaDel f $
930+ inci . braces N . sitcc . sep (comma >> breakpoint) f $
975 case dotdot of
931 case dotdot of
976 Nothing -> Just <$> fields
932 Nothing -> Just <$> fields
977− Just (L _ n) -> (Just <$> take n fields) ++ [Nothing]
933+ Just n -> (Just <$> take n fields) ++ [Nothing]
978− InfixCon l r -> do
934+ InfixCon x y -> do
979− switchLayout [getLoc l, getLoc r] $ do
935+ located x p_pat
980− located l p_pat
936+ space
937+ p_rdrName pat
981− breakpoint
938+ breakpoint
982− inci $ do
983− p_rdrName pat
984− space
985− located r p_pat
939+ inci (located y p_pat)
986 ConPatOut {} -> notImplemented "ConPatOut" -- presumably created by renamer?
940 ConPatOut {} -> notImplemented "ConPatOut" -- presumably created by renamer?
987− ViewPat NoExtField expr pat -> sitcc $ do
941+ ViewPat NoExt expr pat -> sitcc $ do
988 located expr p_hsExpr
942 located expr p_hsExpr
989 space
943 space
990 txt "->"
944 txt "->"
991 breakpoint
945 breakpoint
992 inci (located pat p_pat)
946 inci (located pat p_pat)
993− SplicePat NoExtField splice -> p_hsSplice splice
947+ SplicePat NoExt splice -> p_hsSplice splice
994− LitPat NoExtField p -> atom p
948+ LitPat NoExt p -> atom p
995− NPat NoExtField v _ _ -> located v (atom . ol_val)
949+ NPat NoExt v _ _ -> located v (atom . ol_val)
996− NPlusKPat NoExtField n k _ _ _ -> sitcc $ do
950+ NPlusKPat NoExt n k _ _ _ -> sitcc $ do
997 p_rdrName n
951 p_rdrName n
998 breakpoint
952 breakpoint
999 inci $ do
953 inci $ do
1000 txt "+"
954 txt "+"
1001 space
955 space
1002 located k (atom . ol_val)
956 located k (atom . ol_val)
1003− SigPat NoExtField pat hswc -> do
957+ SigPat hswc pat -> do
1004 located pat p_pat
958 located pat p_pat
1005 p_typeAscription hswc
959 p_typeAscription hswc
1006 CoPat {} -> notImplemented "CoPat" -- apparently created at some later stage
960 CoPat {} -> notImplemented "CoPat" -- apparently created at some later stage
1007− XPat x -> noExtCon x
961+ XPat NoExt -> notImplemented "XPat"
1008
962
1009p_pat_hsRecField :: HsRecField' (FieldOcc GhcPs) (LPat GhcPs) -> R ()
963p_pat_hsRecField :: HsRecField' (FieldOcc GhcPs) (LPat GhcPs) -> R ()
1010p_pat_hsRecField HsRecField {..} = do
964p_pat_hsRecField HsRecField {..} = do
@@ -1012,7 +966,7 @@ p_pat_hsRecField HsRecField {..} = do
1012 p_rdrName (rdrNameFieldOcc x)
966 p_rdrName (rdrNameFieldOcc x)
1013 unless hsRecPun $ do
967 unless hsRecPun $ do
1014 space
968 space
1015− equals
969+ txt "="
1016 breakpoint
970 breakpoint
1017 inci (located hsRecFieldArg p_pat)
971 inci (located hsRecFieldArg p_pat)
1018
972
@@ -1021,31 +975,32 @@ p_unboxedSum s tag arity m = do
1021 let before = tag - 1
975 let before = tag - 1
1022 after = arity - before - 1
976 after = arity - before - 1
1023 args = replicate before Nothing <> [Just m] <> replicate after Nothing
977 args = replicate before Nothing <> [Just m] <> replicate after Nothing
1024− f x =
978+ f (x, i) = do
979+ let isFirst = i == 0
980+ isLast = i == arity - 1
1025 case x :: Maybe (R ()) of
981 case x :: Maybe (R ()) of
1026 Nothing ->
982 Nothing ->
1027− space
983+ unless (isFirst || isLast) space
1028 Just m' -> do
984 Just m' -> do
1029− space
985+ unless isFirst space
1030 m'
986 m'
1031− space
987+ unless isLast space
1032− parensHash s $ sep (txt "|") f args
988+ parensHash s $ sep (txt "|") f (zip args [0 ..])
1033
989
1034p_hsSplice :: HsSplice GhcPs -> R ()
990p_hsSplice :: HsSplice GhcPs -> R ()
1035p_hsSplice = \case
991p_hsSplice = \case
1036− HsTypedSplice NoExtField deco _ expr -> p_hsSpliceTH True expr deco
992+ HsTypedSplice NoExt deco _ expr -> p_hsSpliceTH True expr deco
1037− HsUntypedSplice NoExtField deco _ expr -> p_hsSpliceTH False expr deco
993+ HsUntypedSplice NoExt deco _ expr -> p_hsSpliceTH False expr deco
1038− HsQuasiQuote NoExtField _ quoterName srcSpan str -> do
994+ HsQuasiQuote NoExt _ quoterName srcSpan str -> do
1039 txt "["
995 txt "["
1040 p_rdrName (L srcSpan quoterName)
996 p_rdrName (L srcSpan quoterName)
1041 txt "|"
997 txt "|"
1042− -- QuasiQuoters often rely on precise custom strings. We cannot do any
998+ -- NOTE QuasiQuoters often rely on precise custom strings. We cannot do
1043− -- formatting here without potentially breaking someone's code.
999+ -- any formatting here without potentially breaking someone's code.
1044 atom str
1000 atom str
1045 txt "|]"
1001 txt "|]"
1046 HsSpliced {} -> notImplemented "HsSpliced"
1002 HsSpliced {} -> notImplemented "HsSpliced"
1047− HsSplicedT {} -> notImplemented "HsSplicedT"
1003+ XSplice {} -> notImplemented "XSplice"
1048− XSplice x -> noExtCon x
1049
1004
1050p_hsSpliceTH ::
1005p_hsSpliceTH ::
1051 -- | Typed splice?
1006 -- | Typed splice?
@@ -1069,17 +1024,17 @@ p_hsSpliceTH isTyped expr = \case
1069
1024
1070p_hsBracket :: HsBracket GhcPs -> R ()
1025p_hsBracket :: HsBracket GhcPs -> R ()
1071p_hsBracket = \case
1026p_hsBracket = \case
1072− ExpBr NoExtField expr -> do
1027+ ExpBr NoExt expr -> do
1073 anns <- getEnclosingAnns
1028 anns <- getEnclosingAnns
1074 let name = case anns of
1029 let name = case anns of
1075 AnnOpenEQ : _ -> ""
1030 AnnOpenEQ : _ -> ""
1076 _ -> "e"
1031 _ -> "e"
1077 quote name (located expr p_hsExpr)
1032 quote name (located expr p_hsExpr)
1078− PatBr NoExtField pat -> located pat (quote "p" . p_pat)
1033+ PatBr NoExt pat -> quote "p" (located pat p_pat)
1079− DecBrL NoExtField decls -> quote "d" (p_hsDecls Free decls)
1034+ DecBrL NoExt decls -> quote "d" (p_hsDecls Free decls)
1080− DecBrG NoExtField _ -> notImplemented "DecBrG" -- result of renamer
1035+ DecBrG NoExt _ -> notImplemented "DecBrG" -- result of renamer
1081− TypBr NoExtField ty -> quote "t" (located ty p_hsType)
1036+ TypBr NoExt ty -> quote "t" (located ty p_hsType)
1082− VarBr NoExtField isSingleQuote name -> do
1037+ VarBr NoExt isSingleQuote name -> do
1083 txt (bool "''" "'" isSingleQuote)
1038 txt (bool "''" "'" isSingleQuote)
1084 -- HACK As you can see we use 'noLoc' here to be able to pass name into
1039 -- HACK As you can see we use 'noLoc' here to be able to pass name into
1085 -- 'p_rdrName' since the latter expects a "located" thing. The problem
1040 -- 'p_rdrName' since the latter expects a "located" thing. The problem
@@ -1094,13 +1049,13 @@ p_hsBracket = \case
1094 && not (doesNotNeedExtraParens name)
1049 && not (doesNotNeedExtraParens name)
1095 wrapper = if isOperator then parens N else id
1050 wrapper = if isOperator then parens N else id
1096 wrapper $ p_rdrName (noLoc name)
1051 wrapper $ p_rdrName (noLoc name)
1097− TExpBr NoExtField expr -> do
1052+ TExpBr NoExt expr -> do
1098 txt "[||"
1053 txt "[||"
1099 breakpoint'
1054 breakpoint'
1100 located expr p_hsExpr
1055 located expr p_hsExpr
1101 breakpoint'
1056 breakpoint'
1102 txt "||]"
1057 txt "||]"
1103− XBracket x -> noExtCon x
1058+ XBracket {} -> notImplemented "XBracket"
1104 where
1059 where
1105 quote :: Text -> R () -> R ()
1060 quote :: Text -> R () -> R ()
1106 quote name body = do
1061 quote name body = do
@@ -1179,9 +1134,9 @@ liftAppend (x : xs) [] = x : xs
1179liftAppend (x : xs) (y : ys) = x <> y : liftAppend xs ys
1134liftAppend (x : xs) (y : ys) = x <> y : liftAppend xs ys
1180
1135
1181getGRHSSpan :: GRHS GhcPs (Located body) -> SrcSpan
1136getGRHSSpan :: GRHS GhcPs (Located body) -> SrcSpan
1182−getGRHSSpan (GRHS NoExtField guards body) =
1137+getGRHSSpan (GRHS NoExt guards body) =
1183 combineSrcSpans' $ getLoc body :| map getLoc guards
1138 combineSrcSpans' $ getLoc body :| map getLoc guards
1184−getGRHSSpan (XGRHS x) = noExtCon x
1139+getGRHSSpan (XGRHS NoExt) = notImplemented "XGRHS"
1185
1140
1186-- | Place a thing that may have a hanging form. This function handles how
1141-- | Place a thing that may have a hanging form. This function handles how
1187-- to separate it from preceding expressions and whether to bump indentation
1142-- to separate it from preceding expressions and whether to bump indentation
@@ -1202,44 +1157,46 @@ blockPlacement ::
1202 (body -> Placement) ->
1157 (body -> Placement) ->
1203 [LGRHS GhcPs (Located body)] ->
1158 [LGRHS GhcPs (Located body)] ->
1204 Placement
1159 Placement
1205−blockPlacement placer [L _ (GRHS NoExtField _ (L _ x))] = placer x
1160+blockPlacement placer [(L _ (GRHS NoExt _ (L _ x)))] = placer x
1206blockPlacement _ _ = Normal
1161blockPlacement _ _ = Normal
1207
1162
1208-- | Check if given command has a hanging form.
1163-- | Check if given command has a hanging form.
1209cmdPlacement :: HsCmd GhcPs -> Placement
1164cmdPlacement :: HsCmd GhcPs -> Placement
1210cmdPlacement = \case
1165cmdPlacement = \case
1211− HsCmdLam NoExtField _ -> Hanging
1166+ HsCmdLam NoExt _ -> Hanging
1212− HsCmdCase NoExtField _ _ -> Hanging
1167+ HsCmdCase NoExt _ _ -> Hanging
1213− HsCmdDo NoExtField _ -> Hanging
1168+ HsCmdDo NoExt _ -> Hanging
1214 _ -> Normal
1169 _ -> Normal
1215
1170
1216cmdTopPlacement :: HsCmdTop GhcPs -> Placement
1171cmdTopPlacement :: HsCmdTop GhcPs -> Placement
1217cmdTopPlacement = \case
1172cmdTopPlacement = \case
1218− HsCmdTop NoExtField (L _ x) -> cmdPlacement x
1173+ HsCmdTop NoExt (L _ x) -> cmdPlacement x
1219− XCmdTop x -> noExtCon x
1174+ XCmdTop {} -> notImplemented "XCmdTop"
1220
1175
1221-- | Check if given expression has a hanging form.
1176-- | Check if given expression has a hanging form.
1222exprPlacement :: HsExpr GhcPs -> Placement
1177exprPlacement :: HsExpr GhcPs -> Placement
1223exprPlacement = \case
1178exprPlacement = \case
1224 -- Only hang lambdas with single line parameter lists
1179 -- Only hang lambdas with single line parameter lists
1225− HsLam NoExtField mg -> case mg of
1180+ HsLam NoExt mg -> case mg of
1226− MG _ (L _ [L _ (Match NoExtField _ (x : xs) _)]) _
1181+ MG _ (L _ [L _ (Match NoExt _ (x : xs) _)]) _
1227 | isOneLineSpan (combineSrcSpans' $ fmap getLoc (x :| xs)) ->
1182 | isOneLineSpan (combineSrcSpans' $ fmap getLoc (x :| xs)) ->
1228 Hanging
1183 Hanging
1229 _ -> Normal
1184 _ -> Normal
1230− HsLamCase NoExtField _ -> Hanging
1185+ HsLamCase NoExt _ -> Hanging
1231− HsCase NoExtField _ _ -> Hanging
1186+ HsCase NoExt _ _ -> Hanging
1232− HsDo NoExtField DoExpr _ -> Hanging
1187+ HsDo NoExt DoExpr _ -> Hanging
1233− HsDo NoExtField MDoExpr _ -> Hanging
1188+ HsDo NoExt MDoExpr _ -> Hanging
1234− OpApp NoExtField _ op y ->
1189+ RecordCon NoExt _ _ -> Hanging
1235− case (fmap getOpNameStr . getOpName . unLoc) op of
1190+ -- If the rightmost expression in an operator chain is hanging, make the
1236− Just "$" -> exprPlacement (unLoc y)
1191+ -- whole block hanging; so that we can use the common @f = foo $ do@
1237− _ -> Normal
1192+ -- style.
1193+ OpApp NoExt _ _ y -> exprPlacement (unLoc y)
1194+ -- Same thing for function applications (usually with -XBlockArguments)
1238− HsApp NoExtField _ y -> exprPlacement (unLoc y)
1195+ HsApp NoExt _ y -> exprPlacement (unLoc y)
1239− HsProc NoExtField p _ ->
1196+ HsProc NoExt (L s _) _ ->
1240 -- Indentation breaks if pattern is longer than one line and left
1197 -- Indentation breaks if pattern is longer than one line and left
1241 -- hanging. Consequently, only apply hanging when it is safe.
1198 -- hanging. Consequently, only apply hanging when it is safe.
1242− if isOneLineSpan (getLoc p)
1199+ if isOneLineSpan s
1243 then Hanging
1200 then Hanging
1244 else Normal
1201 else Normal
1245 _ -> Normal
1202 _ -> Normal
@@ -1248,31 +1205,30 @@ withGuards :: [LGRHS GhcPs (Located body)] -> Bool
1248withGuards = any (checkOne . unLoc)
1205withGuards = any (checkOne . unLoc)
1249 where
1206 where
1250 checkOne :: GRHS GhcPs (Located body) -> Bool
1207 checkOne :: GRHS GhcPs (Located body) -> Bool
1251− checkOne (GRHS NoExtField [] _) = False
1208+ checkOne (GRHS NoExt [] _) = False
1252 checkOne _ = True
1209 checkOne _ = True
1253
1210
1254exprOpTree :: LHsExpr GhcPs -> OpTree (LHsExpr GhcPs) (LHsExpr GhcPs)
1211exprOpTree :: LHsExpr GhcPs -> OpTree (LHsExpr GhcPs) (LHsExpr GhcPs)
1255−exprOpTree (L _ (OpApp NoExtField x op y)) = OpBranch (exprOpTree x) op (exprOpTree y)
1212+exprOpTree (L _ (OpApp NoExt x op y)) = OpBranch (exprOpTree x) op (exprOpTree y)
1256exprOpTree n = OpNode n
1213exprOpTree n = OpNode n
1257
1214
1258getOpName :: HsExpr GhcPs -> Maybe RdrName
1215getOpName :: HsExpr GhcPs -> Maybe RdrName
1259getOpName = \case
1216getOpName = \case
1260− HsVar NoExtField (L _ a) -> Just a
1217+ HsVar NoExt (L _ a) -> Just a
1261 _ -> Nothing
1218 _ -> Nothing
1262
1219
1263−getOpNameStr :: RdrName -> String
1264−getOpNameStr = occNameString . rdrNameOcc
1265−
1266p_exprOpTree ::
1220p_exprOpTree ::
1221+ -- | Can use special handling of dollar?
1222+ Bool ->
1267 -- | Bracket style to use
1223 -- | Bracket style to use
1268 BracketStyle ->
1224 BracketStyle ->
1269 OpTree (LHsExpr GhcPs) (LHsExpr GhcPs) ->
1225 OpTree (LHsExpr GhcPs) (LHsExpr GhcPs) ->
1270 R ()
1226 R ()
1271−p_exprOpTree s (OpNode x) = located x (p_hsExpr' s)
1227+p_exprOpTree _ s (OpNode x) = located x (p_hsExpr' s)
1272−p_exprOpTree s (OpBranch x op y) = do
1228+p_exprOpTree isDollarSpecial s (OpBranch x op y) = do
1273− -- If the beginning of the first argument and the second argument are on
1229+ -- NOTE If the beginning of the first argument and the second argument
1274− -- the same line, and the second argument has a hanging form, use hanging
1230+ -- are on the same line, and the second argument has a hanging form, use
1275− -- placement.
1231+ -- hanging placement.
1276 let placement =
1232 let placement =
1277 if isOneLineSpan
1233 if isOneLineSpan
1278 (mkSrcSpan (srcSpanStart (opTreeLoc x)) (srcSpanStart (opTreeLoc y)))
1234 (mkSrcSpan (srcSpanStart (opTreeLoc x)) (srcSpanStart (opTreeLoc y)))
@@ -1280,10 +1236,8 @@ p_exprOpTree s (OpBranch x op y) = do
1280 OpNode (L _ n) -> exprPlacement n
1236 OpNode (L _ n) -> exprPlacement n
1281 _ -> Normal
1237 _ -> Normal
1282 else Normal
1238 else Normal
1283− -- Distinguish holes used in infix notation.
1284− -- eg. '1 _foo 2' and '1 `_foo` 2'
1285 opWrapper = case unLoc op of
1239 opWrapper = case unLoc op of
1286− HsUnboundVar NoExtField _ -> backticks
1240+ EWildPat NoExt -> backticks
1287 _ -> id
1241 _ -> id
1288 layout <- getLayout
1242 layout <- getLayout
1289 let ub = case layout of
1243 let ub = case layout of
@@ -1291,67 +1245,24 @@ p_exprOpTree s (OpBranch x op y) = do
1291 MultiLine -> case placement of
1245 MultiLine -> case placement of
1292 Hanging -> useBraces
1246 Hanging -> useBraces
1293 Normal -> dontUseBraces
1247 Normal -> dontUseBraces
1294− opNameStr = (fmap getOpNameStr . getOpName . unLoc) op
1248+ gotDollar = case getOpName (unLoc op) of
1295− gotDollar = opNameStr == Just "$"
1249+ Just rname -> mkVarOcc "$" == (rdrNameOcc rname)
1296− gotColon = opNameStr == Just ":"
1297− gotRecordDot = isRecordDot (unLoc op) (opTreeLoc y)
1298− lhs =
1299− switchLayout [opTreeLoc x] $
1300− p_exprOpTree s x
1301− p_op = located op (opWrapper . p_hsExpr)
1302− p_y = switchLayout [opTreeLoc y] (p_exprOpTree N y)
1303− isSection = case (opTreeLoc x, getLoc op) of
1304− (RealSrcSpan treeSpan, RealSrcSpan opSpan) ->
1305− srcSpanEndCol treeSpan /= srcSpanStartCol opSpan
1306 _ -> False
1250 _ -> False
1307− isDoBlock = \case
1251+ switchLayout [opTreeLoc x]
1308− OpNode (L _ HsDo {}) -> True
1252+ $ ub
1309− _ -> False
1253+ $ p_exprOpTree (not gotDollar) s x
1310− useRecordDot' <- useRecordDot
1254+ let p_op = located op (opWrapper . p_hsExpr)
1311− if
1255+ p_y = switchLayout [opTreeLoc y] (p_exprOpTree True N y)
1312− | gotColon -> do
1313− lhs
1314− space
1315− p_op
1316− case placement of
1317− Hanging -> do
1318− space
1319− p_y
1320− Normal -> do
1321− breakpoint
1322− inciIf (isDoBlock y) p_y
1323− | gotDollar
1324− && isOneLineSpan (opTreeLoc x)
1256+ if isDollarSpecial && gotDollar && placement == Normal && isOneLineSpan (opTreeLoc x)
1325− && placement == Normal -> do
1257+ then do
1326− useBraces lhs
1327− space
1258+ space
1328− p_op
1259+ p_op
1329− breakpoint
1260+ breakpoint
1330− inci p_y
1261+ 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
1262+ else placeHanging placement $ do
1339− p_op
1263+ p_op
1340− space
1264+ space
1341− p_y
1265+ p_y
1342−
1343−-- | Return 'True' if given expression is a record-dot operator expression.
1344−isRecordDot ::
1345− -- | Operator expression
1346− HsExpr GhcPs ->
1347− -- | Span of the expression on the right-hand side of the operator
1348− SrcSpan ->
1349− Bool
1350−isRecordDot op (RealSrcSpan ySpan) = case op of
1351− HsVar NoExtField (L (RealSrcSpan opSpan) opName) ->
1352− (getOpNameStr opName == ".") && (srcSpanEndCol opSpan == srcSpanStartCol ySpan)
1353− _ -> False
1354−isRecordDot _ _ = False
1355
1266
1356-- | Get annotations for the enclosing element.
1267-- | Get annotations for the enclosing element.
1357getEnclosingAnns :: R [AnnKeywordId]
1268getEnclosingAnns :: R [AnnKeywordId]
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+10−8
@@ -13,28 +13,30 @@ import Data.Text (Text)
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
16
17
17p_warnDecls :: WarnDecls GhcPs -> R ()
18p_warnDecls :: WarnDecls GhcPs -> R ()
18−p_warnDecls (Warnings NoExtField _ warnings) =
19+p_warnDecls (Warnings NoExt _ warnings) =
19 traverse_ (located' p_warnDecl) warnings
20 traverse_ (located' p_warnDecl) warnings
20−p_warnDecls (XWarnDecls x) = noExtCon x
21+p_warnDecls XWarnDecls {} = notImplemented "XWarnDecls"
21
22
22p_warnDecl :: WarnDecl GhcPs -> R ()
23p_warnDecl :: WarnDecl GhcPs -> R ()
23−p_warnDecl (Warning NoExtField functions warningTxt) =
24+p_warnDecl (Warning NoExt functions warningTxt) =
24 p_topLevelWarning functions warningTxt
25 p_topLevelWarning functions warningTxt
25−p_warnDecl (XWarnDecl x) = noExtCon x
26+p_warnDecl XWarnDecl {} = notImplemented "XWarnDecl"
26
27
27p_moduleWarning :: WarningTxt -> R ()
28p_moduleWarning :: WarningTxt -> R ()
28p_moduleWarning wtxt = do
29p_moduleWarning wtxt = do
29 let (pragmaText, lits) = warningText wtxt
30 let (pragmaText, lits) = warningText wtxt
31+ switchLayout (getLoc <$> lits) $ do
30− inci $ pragma pragmaText $ inci $ p_lits lits
32+ inci $ 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) $ do
36 pragma pragmaText . inci $ do
38 pragma pragmaText . inci $ do
37− sep commaDel p_rdrName fnames
39+ sitcc $ sep (comma >> breakpoint) p_rdrName fnames
38 breakpoint
40 breakpoint
39 p_lits lits
41 p_lits lits
40
42
@@ -46,4 +48,4 @@ warningText = \case
46p_lits :: [Located StringLiteral] -> R ()
48p_lits :: [Located StringLiteral] -> R ()
47p_lits = \case
49p_lits = \case
48 [l] -> atom l
50 [l] -> atom l
49− ls -> brackets N $ sep commaDel atom ls
51+ ls -> brackets N . sitcc $ sep (comma >> breakpoint) atom ls
src/Ormolu/Printer/Meat/ImportExport.hs+36−45
@@ -11,9 +11,10 @@ where
11
11
12import Control.Monad
12import Control.Monad
13import GHC
13import GHC
14+import HsImpExp (IE (..))
14import Ormolu.Printer.Combinators
15import Ormolu.Printer.Combinators
15import Ormolu.Printer.Meat.Common
16import Ormolu.Printer.Meat.Common
16−import Ormolu.Utils (RelativePos (..), attachRelativePos)
17+import Ormolu.Utils
17
18
18p_hsmodExports :: [LIE GhcPs] -> R ()
19p_hsmodExports :: [LIE GhcPs] -> R ()
19p_hsmodExports [] = do
20p_hsmodExports [] = do
@@ -21,24 +22,19 @@ p_hsmodExports [] = do
21 breakpoint'
22 breakpoint'
22 txt ")"
23 txt ")"
23p_hsmodExports xs =
24p_hsmodExports xs =
24− parens N $ do
25+ parens N . sitcc $ do
25 layout <- getLayout
26 layout <- getLayout
26− sep
27− breakpoint
28− (\(p, l) -> sitcc (located l (p_lie layout p)))
27+ sep breakpoint (sitcc . located' (uncurry (p_lie layout))) (attachPositions xs)
29− (attachRelativePos xs)
30
28
31−p_hsmodImport :: Bool -> ImportDecl GhcPs -> R ()
29+p_hsmodImport :: ImportDecl GhcPs -> R ()
32−p_hsmodImport useQualifiedPost ImportDecl {..} = do
30+p_hsmodImport ImportDecl {..} = do
33 txt "import"
31 txt "import"
34 space
32 space
35 when ideclSource (txt "{-# SOURCE #-}")
33 when ideclSource (txt "{-# SOURCE #-}")
36 space
34 space
37 when ideclSafe (txt "safe")
35 when ideclSafe (txt "safe")
38 space
36 space
39− when
40− (isImportDeclQualified ideclQualified && not useQualifiedPost)
41− (txt "qualified")
37+ when ideclQualified (txt "qualified")
42 space
38 space
43 case ideclPkgQual of
39 case ideclPkgQual of
44 Nothing -> return ()
40 Nothing -> return ()
@@ -46,9 +42,6 @@ p_hsmodImport useQualifiedPost ImportDecl {..} = do
46 space
42 space
47 inci $ do
43 inci $ do
48 located ideclName atom
44 located ideclName atom
49− when
50− (isImportDeclQualified ideclQualified && useQualifiedPost)
51− (space >> txt "qualified")
52 case ideclAs of
45 case ideclAs of
53 Nothing -> return ()
46 Nothing -> return ()
54 Just l -> do
47 Just l -> do
@@ -63,64 +56,62 @@ p_hsmodImport useQualifiedPost ImportDecl {..} = do
63 when hiding (txt "hiding")
56 when hiding (txt "hiding")
64 case ideclHiding of
57 case ideclHiding of
65 Nothing -> return ()
58 Nothing -> return ()
66− Just (_, L _ xs) -> do
59+ Just (_, (L _ xs)) -> do
67 breakpoint
60 breakpoint
68− parens N $ do
61+ parens N . sitcc $ do
69 layout <- getLayout
62 layout <- getLayout
70− sep
71− breakpoint
72− (\(p, l) -> sitcc (located l (p_lie layout p)))
63+ sep breakpoint (sitcc . located' (uncurry (p_lie layout))) (attachPositions xs)
73− (attachRelativePos xs)
74 newline
64 newline
75−p_hsmodImport _ (XImportDecl x) = noExtCon x
65+p_hsmodImport (XImportDecl NoExt) = notImplemented "XImportDecl"
76
66
77−p_lie :: Layout -> RelativePos -> IE GhcPs -> R ()
67+p_lie :: Layout -> (Int, Int) -> IE GhcPs -> R ()
78−p_lie encLayout relativePos = \case
68+p_lie encLayout (i, totalItems) = \case
79− IEVar NoExtField l1 -> do
69+ IEVar NoExt l1 -> do
80 located l1 p_ieWrappedName
70 located l1 p_ieWrappedName
81 p_comma
71 p_comma
82− IEThingAbs NoExtField l1 -> do
72+ IEThingAbs NoExt l1 -> do
83 located l1 p_ieWrappedName
73 located l1 p_ieWrappedName
84 p_comma
74 p_comma
85− IEThingAll NoExtField l1 -> do
75+ IEThingAll NoExt l1 -> do
86 located l1 p_ieWrappedName
76 located l1 p_ieWrappedName
87 space
77 space
88 txt "(..)"
78 txt "(..)"
89 p_comma
79 p_comma
90− IEThingWith NoExtField l1 w xs _ -> sitcc $ do
80+ IEThingWith NoExt l1 w xs _ -> sitcc $ do
91 located l1 p_ieWrappedName
81 located l1 p_ieWrappedName
92 breakpoint
82 breakpoint
93 inci $ do
83 inci $ do
94 let names :: [R ()]
84 let names :: [R ()]
95 names = located' p_ieWrappedName <$> xs
85 names = located' p_ieWrappedName <$> xs
96− parens N . sep commaDel sitcc $
86+ parens N . sitcc
87+ $ sep (comma >> breakpoint) sitcc
97− case w of
88+ $ case w of
98 NoIEWildcard -> names
89 NoIEWildcard -> names
99 IEWildcard n ->
90 IEWildcard n ->
100 let (before, after) = splitAt n names
91 let (before, after) = splitAt n names
101 in before ++ [txt ".."] ++ after
92 in before ++ [txt ".."] ++ after
102 p_comma
93 p_comma
103− IEModuleContents NoExtField l1 -> do
94+ IEModuleContents NoExt l1 -> do
104 located l1 p_hsmodName
95 located l1 p_hsmodName
105 p_comma
96 p_comma
106− IEGroup NoExtField n str -> do
97+ IEGroup NoExt n str -> do
107− case relativePos of
108− SinglePos -> return ()
109− FirstPos -> return ()
110− MiddlePos -> newline
111− LastPos -> newline
98+ unless (i == 0) newline
112 p_hsDocString (Asterisk n) False (noLoc str)
99 p_hsDocString (Asterisk n) False (noLoc str)
113− IEDoc NoExtField str ->
100+ IEDoc NoExt str ->
114 p_hsDocString Pipe False (noLoc str)
101 p_hsDocString Pipe False (noLoc str)
115− IEDocNamed NoExtField str -> p_hsDocName str
102+ IEDocNamed NoExt str -> p_hsDocName str
116− XIE x -> noExtCon x
103+ XIE NoExt -> notImplemented "XIE"
117 where
104 where
118 p_comma =
105 p_comma =
119 case encLayout of
106 case encLayout of
120− SingleLine ->
107+ 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
108 MultiLine -> comma
109+
110+-- | Attach positions to 'Located' things in a list.
111+attachPositions ::
112+ [Located a] ->
113+ [Located ((Int, Int), a)]
114+attachPositions xs =
115+ let f i (L l x) = L l ((i, n), x)
116+ n = length xs
117+ in zipWith f [0 ..] xs
src/Ormolu/Printer/Meat/Module.hs+17−38
@@ -9,12 +9,9 @@ module Ormolu.Printer.Meat.Module
9where
9where
10
10
11import Control.Monad
11import Control.Monad
12−import qualified Data.Text as T
13import GHC
12import GHC
14−import Ormolu.Imports (normalizeImports)
13+import Ormolu.Imports
15−import Ormolu.Parser.CommentStream
16import Ormolu.Parser.Pragma
14import Ormolu.Parser.Pragma
17−import Ormolu.Parser.Shebang
18import Ormolu.Printer.Combinators
15import Ormolu.Printer.Combinators
19import Ormolu.Printer.Comments
16import Ormolu.Printer.Comments
20import Ormolu.Printer.Meat.Common
17import Ormolu.Printer.Meat.Common
@@ -23,53 +20,35 @@ import Ormolu.Printer.Meat.Declaration.Warning
23import Ormolu.Printer.Meat.ImportExport
20import Ormolu.Printer.Meat.ImportExport
24import Ormolu.Printer.Meat.Pragma
21import Ormolu.Printer.Meat.Pragma
25
22
26−-- | Render a module.
27−p_hsModule ::
23+p_hsModule :: [Pragma] -> ParsedSource -> R ()
28− -- | Stack header
29− Maybe (RealLocated Comment) ->
30− -- | Shebangs
31− [Shebang] ->
32− -- | Pragmas and the associated comments
33− [([RealLocated Comment], Pragma)] ->
34− -- | Whether to use postfix qualified imports
35− Bool ->
36− -- | AST to print
37− HsModule GhcPs ->
38− R ()
39−p_hsModule mstackHeader shebangs pragmas qualifiedPost HsModule {..} = do
24+p_hsModule pragmas (L moduleSpan HsModule {..}) = do
25+ -- NOTE If span of exports in multiline, the whole thing is multiline.
26+ -- This is especially important because span of module itself always seems
27+ -- to have length zero, so it's not reliable for layout selection.
28+ let exportSpans = maybe [] (\(L s _) -> [s]) hsmodExports
40− let deprecSpan = maybe [] (\(L s _) -> [s]) hsmodDeprecMessage
29+ deprecSpan = maybe [] (\(L s _) -> [s]) hsmodDeprecMessage
41− exportSpans = maybe [] (\(L s _) -> [s]) hsmodExports
30+ spans' = exportSpans ++ deprecSpan ++ [moduleSpan]
42− switchLayout (deprecSpan <> exportSpans) $ do
31+ switchLayout spans' $ do
43− forM_ shebangs $ \(Shebang x) ->
44− located x $ \shebang -> do
45− txt (T.pack shebang)
46− newline
47− forM_ mstackHeader $ \(L spn comment) -> do
48− spitCommentNow spn comment
49− newline
50− newline
51 p_pragmas pragmas
32 p_pragmas pragmas
52 newline
33 newline
34+ forM_ hsmodHaddockModHeader (p_hsDocString Pipe True)
53 case hsmodName of
35 case hsmodName of
54 Nothing -> return ()
36 Nothing -> return ()
55 Just hsmodName' -> do
37 Just hsmodName' -> do
56− located hsmodName' $ \name -> do
38+ located hsmodName' p_hsmodName
57− forM_ hsmodHaddockModHeader (p_hsDocString Pipe True)
58− p_hsmodName name
59− breakpoint
60 forM_ hsmodDeprecMessage $ \w -> do
39 forM_ hsmodDeprecMessage $ \w -> do
61− located' p_moduleWarning w
62 breakpoint
40 breakpoint
41+ located' p_moduleWarning w
63 case hsmodExports of
42 case hsmodExports of
64 Nothing -> return ()
43 Nothing -> return ()
65− Just l -> do
44+ Just hsmodExports' -> do
66− located l $ \exports -> do
67− inci (p_hsmodExports exports)
68 breakpoint
45 breakpoint
46+ inci (p_hsmodExports (unLoc hsmodExports'))
47+ breakpoint
69 txt "where"
48 txt "where"
70 newline
49 newline
71 newline
50 newline
72− forM_ (normalizeImports hsmodImports) (located' (p_hsmodImport qualifiedPost))
51+ forM_ (sortImports hsmodImports) (located' p_hsmodImport)
73 newline
52 newline
74 switchLayout (getLoc <$> hsmodDecls) $ do
53 switchLayout (getLoc <$> hsmodDecls) $ do
75 p_hsDecls Free hsmodDecls
54 p_hsDecls Free hsmodDecls
src/Ormolu/Printer/Meat/Pragma.hs+13−67
@@ -8,84 +8,30 @@ module Ormolu.Printer.Meat.Pragma
8 )
8 )
9where
9where
10
10
11−import Control.Monad
12−import Data.Char (isUpper)
13−import qualified Data.List as L
11+import qualified Data.Set as S
14−import Data.Maybe (listToMaybe)
15import qualified Data.Text as T
12import qualified Data.Text as T
16−import Ormolu.Parser.CommentStream
17import Ormolu.Parser.Pragma (Pragma (..))
13import Ormolu.Parser.Pragma (Pragma (..))
18import Ormolu.Printer.Combinators
14import Ormolu.Printer.Combinators
19−import Ormolu.Printer.Comments
20−import SrcLoc
21
15
22−-- | Pragma classification.
23−data PragmaTy
24− = Language LanguagePragmaClass
25− | OptionsGHC
26− | OptionsHaddock
16+data PragmaTy = Language | OptionsGHC | OptionsHaddock
27 deriving (Eq, Ord)
17 deriving (Eq, Ord)
28
18
29−-- | Language pragma classification.
30−--
31−-- The order in which language pragmas are put in the input sometimes
32−-- matters. This is because some language extensions can enable other
33−-- extensions, yet the extensions coming later in the list have the ability
34−-- to change it. So here we classify all extensions by assigning one of the
35−-- four groups to them. Then we only sort inside of the groups.
36−--
37−-- 'Ord' instance of this data type is what affects the sorting.
38−--
39−-- See also: <https://github.com/tweag/ormolu/issues/404>
40−data LanguagePragmaClass
41− = -- | All other extensions
42− Normal
43− | -- | Extensions starting with "No"
44− Disabling
45− | -- | Extensions that should go after everything else
46− Final
47− deriving (Eq, Ord)
48−
49−-- | Print a collection of 'Pragma's with their associated comments.
50−p_pragmas :: [([RealLocated Comment], Pragma)] -> R ()
19+p_pragmas :: [Pragma] -> R ()
51−p_pragmas ps = do
20+p_pragmas ps =
52− let prepare = L.sortOn snd . L.nub . concatMap analyze
21+ let prepare = concatMap $ \case
53− analyze = \case
54− (cs, PragmaLanguage xs) ->
22+ PragmaLanguage xs -> (Language,) <$> xs
55− let f x = (cs, (Language (classifyLanguagePragma x), x))
56− in f <$> xs
57− (cs, PragmaOptionsGHC x) -> [(cs, (OptionsGHC, x))]
23+ PragmaOptionsGHC x -> [(OptionsGHC, x)]
58− (cs, PragmaOptionsHaddock x) -> [(cs, (OptionsHaddock, x))]
24+ PragmaOptionsHaddock x -> [(OptionsHaddock, x)]
59− forM_ (prepare ps) $ \(cs, (pragmaTy, x)) ->
25+ in mapM_ (uncurry p_pragma) (S.toAscList . S.fromList . prepare $ ps)
60− p_pragma cs pragmaTy x
61
26
62−p_pragma :: [RealLocated Comment] -> PragmaTy -> String -> R ()
27+p_pragma :: PragmaTy -> String -> R ()
63−p_pragma comments ty x = do
28+p_pragma ty c = do
64− forM_ comments $ \(L l comment) -> do
65− spitCommentNow l comment
66− newline
67 txt "{-# "
29 txt "{-# "
68 txt $ case ty of
30 txt $ case ty of
69− Language _ -> "LANGUAGE"
31+ Language -> "LANGUAGE"
70 OptionsGHC -> "OPTIONS_GHC"
32 OptionsGHC -> "OPTIONS_GHC"
71 OptionsHaddock -> "OPTIONS_HADDOCK"
33 OptionsHaddock -> "OPTIONS_HADDOCK"
72 space
34 space
73− txt (T.pack x)
35+ txt (T.pack c)
74 txt " #-}"
36 txt " #-}"
75 newline
37 newline
76−
77−-- | Classify a 'LanguagePragma'.
78−classifyLanguagePragma :: String -> LanguagePragmaClass
79−classifyLanguagePragma = \case
80− "ImplicitPrelude" -> Final
81− "CUSKs" -> Final
82− str ->
83− case splitAt 2 str of
84− ("No", rest) ->
85− case listToMaybe rest of
86− Nothing -> Normal
87− Just x ->
88− if isUpper x
89− then Disabling
90− else Normal
91− _ -> Normal
src/Ormolu/Printer/Meat/Type.hs+81−122
@@ -5,18 +5,16 @@
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,
12− p_forallBndrs,
13 p_conDeclFields,
11 p_conDeclFields,
14 tyVarsToTypes,
12 tyVarsToTypes,
15 )
13 )
16where
14where
17
15
18−import Data.Data (Data)
16+import BasicTypes
19−import GHC hiding (isPromoted)
17+import GHC
20import Ormolu.Printer.Combinators
18import Ormolu.Printer.Combinators
21import Ormolu.Printer.Meat.Common
19import Ormolu.Printer.Meat.Common
22import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration.Value (p_hsSplice, p_stringLit)
20import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration.Value (p_hsSplice, p_stringLit)
@@ -24,23 +22,17 @@ import Ormolu.Printer.Operators
24import Ormolu.Utils
22import Ormolu.Utils
25
23
26p_hsType :: HsType GhcPs -> R ()
24p_hsType :: HsType GhcPs -> R ()
27−p_hsType t = p_hsType' (hasDocStrings t) PipeStyle t
25+p_hsType t = p_hsType' (hasDocStrings t) t
28−
26+
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 ()
27+p_hsType' :: Bool -> HsType GhcPs -> R ()
38−p_hsType' multilineArgs docStyle = \case
28+p_hsType' multilineArgs = \case
39− HsForAllTy NoExtField visibility bndrs t -> do
29+ HsForAllTy NoExt bndrs t -> do
30+ txt "forall "
40− p_forallBndrs visibility p_hsTyVarBndr bndrs
31+ sep space (located' p_hsTyVarBndr) bndrs
32+ txt "."
41 interArgBreak
33 interArgBreak
42− p_hsTypeR (unLoc t)
34+ p_hsType' multilineArgs (unLoc t)
43− HsQualTy NoExtField qs t -> do
35+ HsQualTy NoExt qs t -> do
44 located qs p_hsContext
36 located qs p_hsContext
45 space
37 space
46 txt "=>"
38 txt "=>"
@@ -49,39 +41,20 @@ p_hsType' multilineArgs docStyle = \case
49 HsQualTy {} -> p_hsTypeR (unLoc t)
41 HsQualTy {} -> p_hsTypeR (unLoc t)
50 HsFunTy {} -> p_hsTypeR (unLoc t)
42 HsFunTy {} -> p_hsTypeR (unLoc t)
51 _ -> located t p_hsTypeR
43 _ -> located t p_hsTypeR
52− HsTyVar NoExtField p n -> do
44+ HsTyVar NoExt p n -> do
53 case p of
45 case p of
54− IsPromoted -> do
46+ Promoted -> do
55 txt "'"
47 txt "'"
56 case showOutputable (unLoc n) of
48 case showOutputable (unLoc n) of
57 _ : '\'' : _ -> space
49 _ : '\'' : _ -> space
58 _ -> return ()
50 _ -> return ()
59 NotPromoted -> return ()
51 NotPromoted -> return ()
60 p_rdrName n
52 p_rdrName n
61− HsAppTy NoExtField f x -> do
53+ HsAppTy NoExt f x -> sitcc $ do
62− let -- In order to format type applications with multiple parameters
63− -- nicer, traverse the AST to gather the function and all the
64− -- parameters together.
65− gatherArgs f' knownArgs =
66− case f' of
67− L _ (HsAppTy _ l r) -> gatherArgs l (r : knownArgs)
68− _ -> (f', knownArgs)
69− (func, args) = gatherArgs f [x]
70− switchLayout (getLoc f : fmap getLoc args) . sitcc $ do
71− located func p_hsType
72− breakpoint
73− inci $
74− sep breakpoint (located' p_hsType) args
75− HsAppKindTy _ ty kd -> sitcc $ do
76− -- The first argument is the location of the "@..." part. Not 100% sure,
77− -- but I think we can ignore it as long as we use 'located' on both the
78− -- type and the kind.
79− located ty p_hsType
54+ located f p_hsType
80 breakpoint
55 breakpoint
81− inci $ do
82− txt "@"
83− located kd p_hsType
56+ inci (located x p_hsType)
84− HsFunTy NoExtField x y@(L _ y') -> do
57+ HsFunTy NoExt x y@(L _ y') -> do
85 located x p_hsType
58 located x p_hsType
86 space
59 space
87 txt "->"
60 txt "->"
@@ -89,49 +62,51 @@ p_hsType' multilineArgs docStyle = \case
89 case y' of
62 case y' of
90 HsFunTy {} -> p_hsTypeR y'
63 HsFunTy {} -> p_hsTypeR y'
91 _ -> located y p_hsTypeR
64 _ -> located y p_hsTypeR
92− HsListTy NoExtField t ->
65+ HsListTy NoExt t ->
93 located t (brackets N . p_hsType)
66 located t (brackets N . p_hsType)
94− HsTupleTy NoExtField tsort xs ->
67+ HsTupleTy NoExt tsort xs ->
95 let parens' =
68 let parens' =
96 case tsort of
69 case tsort of
97 HsUnboxedTuple -> parensHash N
70 HsUnboxedTuple -> parensHash N
98 HsBoxedTuple -> parens N
71 HsBoxedTuple -> parens N
99 HsConstraintTuple -> parens N
72 HsConstraintTuple -> parens N
100 HsBoxedOrConstraintTuple -> parens N
73 HsBoxedOrConstraintTuple -> parens N
74+ in parens' . sitcc $
101− in parens' $ sep commaDel (sitcc . located' p_hsType) xs
75+ sep (comma >> breakpoint) (sitcc . located' p_hsType) xs
102− HsSumTy NoExtField xs ->
76+ HsSumTy NoExt xs ->
103− parensHash N $
77+ parensHash N . sitcc $
104 sep (txt "|" >> breakpoint) (sitcc . located' p_hsType) xs
78 sep (txt "|" >> breakpoint) (sitcc . located' p_hsType) xs
105− HsOpTy NoExtField x op y ->
79+ HsOpTy NoExt x op y -> sitcc $ do
106− sitcc $
107− let opTree = OpBranch (tyOpTree x) op (tyOpTree y)
80+ let opTree = OpBranch (tyOpTree x) op (tyOpTree y)
108− in p_tyOpTree (reassociateOpTree Just opTree)
81+ in p_tyOpTree (reassociateOpTree Just opTree)
109− HsParTy NoExtField t ->
82+ HsParTy NoExt (L _ t@HsKindSig {}) ->
83+ -- NOTE Kind signatures already put parentheses around in all cases, so
84+ -- skip this layer of parentheses. The reason for this behavior is that
85+ -- parentheses are not always encoded with 'HsParTy', but seem to be
86+ -- always necessary when we have kind signatures in place.
87+ p_hsType t
88+ HsParTy NoExt t ->
110 parens N (located t p_hsType)
89 parens N (located t p_hsType)
111− HsIParamTy NoExtField n t -> sitcc $ do
90+ HsIParamTy NoExt n t -> sitcc $ do
112 located n atom
91 located n atom
113 space
92 space
114 txt "::"
93 txt "::"
115 breakpoint
94 breakpoint
116 inci (located t p_hsType)
95 inci (located t p_hsType)
117− HsStarTy NoExtField _ -> txt "*"
96+ HsStarTy NoExt _ -> txt "*"
118− HsKindSig NoExtField t k -> sitcc $ do
97+ HsKindSig NoExt t k ->
98+ -- NOTE Also see the comment for 'HsParTy'.
99+ parens N . sitcc $ do
100+ located t p_hsType
101+ space -- FIXME
102+ txt "::"
103+ space
104+ inci (located k p_hsType)
105+ HsSpliceTy NoExt splice -> p_hsSplice splice
106+ HsDocTy NoExt t str -> do
107+ p_hsDocString Pipe True str
119 located t p_hsType
108 located t p_hsType
120− space
121− txt "::"
122− breakpoint
123− inci (located k p_hsType)
124− HsSpliceTy NoExtField splice -> p_hsSplice splice
125− HsDocTy NoExtField t str ->
126− case docStyle of
127− PipeStyle -> do
128− p_hsDocString Pipe True str
129− located t p_hsType
130− CaretStyle -> do
131− located t p_hsType
132− newline
133− p_hsDocString Caret False str
134− HsBangTy NoExtField (HsSrcBang _ u s) t -> do
109+ HsBangTy NoExt (HsSrcBang _ u s) t -> do
135 case u of
110 case u of
136 SrcUnpack -> txt "{-# UNPACK #-}" >> space
111 SrcUnpack -> txt "{-# UNPACK #-}" >> space
137 SrcNoUnpack -> txt "{-# NOUNPACK #-}" >> space
112 SrcNoUnpack -> txt "{-# NOUNPACK #-}" >> space
@@ -141,49 +116,49 @@ p_hsType' multilineArgs docStyle = \case
141 SrcStrict -> txt "!"
116 SrcStrict -> txt "!"
142 NoSrcStrict -> return ()
117 NoSrcStrict -> return ()
143 located t p_hsType
118 located t p_hsType
144− HsRecTy NoExtField fields ->
119+ HsRecTy NoExt fields ->
145 p_conDeclFields fields
120 p_conDeclFields fields
146− HsExplicitListTy NoExtField p xs -> do
121+ HsExplicitListTy NoExt p xs -> do
147 case p of
122 case p of
148− IsPromoted -> txt "'"
123+ Promoted -> txt "'"
149 NotPromoted -> return ()
124 NotPromoted -> return ()
150 brackets N $ do
125 brackets N $ do
151 -- If both this list itself and the first element is promoted,
126 -- If both this list itself and the first element is promoted,
152 -- we need to put a space in between or it fails to parse.
127 -- we need to put a space in between or it fails to parse.
153 case (p, xs) of
128 case (p, xs) of
154− (IsPromoted, L _ t : _) | isPromoted t -> space
129+ (Promoted, ((L _ t) : _)) | isPromoted t -> space
155 _ -> return ()
130 _ -> return ()
156− sep commaDel (sitcc . located' p_hsType) xs
131+ sitcc $ sep (comma >> breakpoint) (sitcc . located' p_hsType) xs
157− HsExplicitTupleTy NoExtField xs -> do
132+ HsExplicitTupleTy NoExt xs -> do
158 txt "'"
133 txt "'"
159 parens N $ do
134 parens N $ do
160 case xs of
135 case xs of
161− L _ t : _ | isPromoted t -> space
136+ ((L _ t) : _) | isPromoted t -> space
162 _ -> return ()
137 _ -> return ()
163− sep commaDel (located' p_hsType) xs
138+ sep (comma >> breakpoint) (located' p_hsType) xs
164− HsTyLit NoExtField t ->
139+ HsTyLit NoExt t ->
165 case t of
140 case t of
166 HsStrTy (SourceText s) _ -> p_stringLit s
141 HsStrTy (SourceText s) _ -> p_stringLit s
167 a -> atom a
142 a -> atom a
168− HsWildCardTy NoExtField -> txt "_"
143+ HsWildCardTy NoExt -> txt "_"
169 XHsType (NHsCoreTy t) -> atom t
144 XHsType (NHsCoreTy t) -> atom t
170 where
145 where
171 isPromoted = \case
146 isPromoted = \case
172− HsTyVar _ IsPromoted _ -> True
147+ HsTyVar _ Promoted _ -> True
148+ HsExplicitListTy _ _ _ -> True
173− HsExplicitTupleTy {} -> True
149+ HsExplicitTupleTy _ _ -> True
174− HsExplicitListTy {} -> True
175 _ -> False
150 _ -> False
176 interArgBreak =
151 interArgBreak =
177 if multilineArgs
152 if multilineArgs
178 then newline
153 then newline
179 else breakpoint
154 else breakpoint
180− p_hsTypeR = p_hsType' multilineArgs docStyle
155+ p_hsTypeR = p_hsType' multilineArgs
181
156
182-- | Return 'True' if at least one argument in 'HsType' has a doc string
157-- | Return 'True' if at least one argument in 'HsType' has a doc string
183-- attached to it.
158-- attached to it.
184hasDocStrings :: HsType GhcPs -> Bool
159hasDocStrings :: HsType GhcPs -> Bool
185hasDocStrings = \case
160hasDocStrings = \case
186− HsDocTy {} -> True
161+ HsDocTy _ _ _ -> True
187 HsFunTy _ (L _ x) (L _ y) -> hasDocStrings x || hasDocStrings y
162 HsFunTy _ (L _ x) (L _ y) -> hasDocStrings x || hasDocStrings y
188 _ -> False
163 _ -> False
189
164
@@ -191,61 +166,50 @@ p_hsContext :: HsContext GhcPs -> R ()
191p_hsContext = \case
166p_hsContext = \case
192 [] -> txt "()"
167 [] -> txt "()"
193 [x] -> located x p_hsType
168 [x] -> located x p_hsType
169+ xs ->
170+ parens N . sitcc $
194− xs -> parens N $ sep commaDel (sitcc . located' p_hsType) xs
171+ sep (comma >> breakpoint) (sitcc . located' p_hsType) xs
195
172
196p_hsTyVarBndr :: HsTyVarBndr GhcPs -> R ()
173p_hsTyVarBndr :: HsTyVarBndr GhcPs -> R ()
197p_hsTyVarBndr = \case
174p_hsTyVarBndr = \case
198− UserTyVar NoExtField x ->
175+ UserTyVar NoExt x ->
199 p_rdrName x
176 p_rdrName x
200− KindedTyVar NoExtField l k -> parens N $ do
177+ KindedTyVar NoExt l k -> parens N $ do
201 located l atom
178 located l atom
202 space
179 space
203 txt "::"
180 txt "::"
204 breakpoint
181 breakpoint
205 inci (located k p_hsType)
182 inci (located k p_hsType)
206− XTyVarBndr x -> noExtCon x
183+ XTyVarBndr NoExt -> notImplemented "XTyVarBndr"
207−
208−-- | Render several @forall@-ed variables.
209−p_forallBndrs :: Data a => ForallVisFlag -> (a -> R ()) -> [Located a] -> R ()
210−p_forallBndrs ForallInvis _ [] = txt "forall."
211−p_forallBndrs ForallVis _ [] = txt "forall ->"
212−p_forallBndrs vis p tyvars =
213− switchLayout (getLoc <$> tyvars) $ do
214− txt "forall"
215− breakpoint
216− inci $ do
217− sitcc $ sep breakpoint (sitcc . located' p) tyvars
218− case vis of
219− ForallInvis -> txt "."
220− ForallVis -> space >> txt "->"
221
184
222p_conDeclFields :: [LConDeclField GhcPs] -> R ()
185p_conDeclFields :: [LConDeclField GhcPs] -> R ()
223p_conDeclFields xs =
186p_conDeclFields xs =
187+ braces N . sitcc $
224− braces N $ sep commaDel (sitcc . located' p_conDeclField) xs
188+ sep (comma >> breakpoint) (sitcc . located' p_conDeclField) xs
225
189
226p_conDeclField :: ConDeclField GhcPs -> R ()
190p_conDeclField :: ConDeclField GhcPs -> R ()
227p_conDeclField ConDeclField {..} = do
191p_conDeclField ConDeclField {..} = do
228 mapM_ (p_hsDocString Pipe True) cd_fld_doc
192 mapM_ (p_hsDocString Pipe True) cd_fld_doc
229 sitcc $
193 sitcc $
230 sep
194 sep
231− commaDel
195+ (comma >> breakpoint)
232 (located' (p_rdrName . rdrNameFieldOcc))
196 (located' (p_rdrName . rdrNameFieldOcc))
233 cd_fld_names
197 cd_fld_names
234 space
198 space
235 txt "::"
199 txt "::"
236 breakpoint
200 breakpoint
237 sitcc . inci $ p_hsType (unLoc cd_fld_type)
201 sitcc . inci $ p_hsType (unLoc cd_fld_type)
238−p_conDeclField (XConDeclField x) = noExtCon x
202+p_conDeclField (XConDeclField NoExt) = notImplemented "XConDeclField"
239
203
240tyOpTree :: LHsType GhcPs -> OpTree (LHsType GhcPs) (Located RdrName)
204tyOpTree :: LHsType GhcPs -> OpTree (LHsType GhcPs) (Located RdrName)
241−tyOpTree (L _ (HsOpTy NoExtField l op r)) =
205+tyOpTree (L _ (HsOpTy NoExt l op r)) =
242 OpBranch (tyOpTree l) op (tyOpTree r)
206 OpBranch (tyOpTree l) op (tyOpTree r)
243tyOpTree n = OpNode n
207tyOpTree n = OpNode n
244
208
245p_tyOpTree :: OpTree (LHsType GhcPs) (Located RdrName) -> R ()
209p_tyOpTree :: OpTree (LHsType GhcPs) (Located RdrName) -> R ()
246p_tyOpTree (OpNode n) = located n p_hsType
210p_tyOpTree (OpNode n) = located n p_hsType
247p_tyOpTree (OpBranch l op r) = do
211p_tyOpTree (OpBranch l op r) = do
248− switchLayout [opTreeLoc l] $
212+ switchLayout [opTreeLoc l] $ do
249 p_tyOpTree l
213 p_tyOpTree l
250 breakpoint
214 breakpoint
251 inci . switchLayout [opTreeLoc r] $ do
215 inci . switchLayout [opTreeLoc r] $ do
@@ -259,17 +223,12 @@ p_tyOpTree (OpBranch l op r) = do
259tyVarsToTypes :: LHsQTyVars GhcPs -> [LHsType GhcPs]
223tyVarsToTypes :: LHsQTyVars GhcPs -> [LHsType GhcPs]
260tyVarsToTypes = \case
224tyVarsToTypes = \case
261 HsQTvs {..} -> fmap tyVarToType <$> hsq_explicit
225 HsQTvs {..} -> fmap tyVarToType <$> hsq_explicit
262− XLHsQTyVars x -> noExtCon x
226+ XLHsQTyVars {} -> notImplemented "XLHsQTyVars"
263
227
264tyVarToType :: HsTyVarBndr GhcPs -> HsType GhcPs
228tyVarToType :: HsTyVarBndr GhcPs -> HsType GhcPs
265tyVarToType = \case
229tyVarToType = \case
266− UserTyVar NoExtField tvar -> HsTyVar NoExtField NotPromoted tvar
230+ UserTyVar NoExt tvar -> HsTyVar NoExt NotPromoted tvar
267− KindedTyVar NoExtField tvar kind ->
231+ KindedTyVar NoExt tvar kind ->
268− -- Note: we always add parentheses because for whatever reason GHC does
232+ HsParTy NoExt $ noLoc $
269− -- not use HsParTy for left-hand sides of declarations. Please see
270− -- <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
272− -- declarations.
273− HsParTy NoExtField . noLoc $
274− HsKindSig NoExtField (noLoc (HsTyVar NoExtField NotPromoted tvar)) kind
233+ HsKindSig NoExt (noLoc (HsTyVar NoExt NotPromoted tvar)) kind
275− XTyVarBndr x -> noExtCon x
234+ XTyVarBndr {} -> notImplemented "XTyVarBndr"
src/Ormolu/Printer/Operators.hs+62−57
@@ -10,14 +10,14 @@ module Ormolu.Printer.Operators
10 )
10 )
11where
11where
12
12
13+import BasicTypes (Fixity (..), SourceText (NoSourceText), compareFixity, defaultFixity)
13import Data.Function (on)
14import Data.Function (on)
14−import qualified Data.List as L
15+import Data.List
15−import Data.Map.Strict (Map)
16−import qualified Data.Map.Strict as M
17−import Data.Maybe (fromMaybe, mapMaybe)
16+import Data.Maybe (fromMaybe)
18import GHC
17import GHC
19−import OccName (occNameString)
18+import OccName (mkVarOcc)
20−import Ormolu.Utils (unSrcSpan)
19+import RdrName (mkRdrUnqual)
20+import SrcLoc (combineSrcSpans)
21
21
22-- | Intermediate representation of operator trees. It has two type
22-- | Intermediate representation of operator trees. It has two type
23-- parameters: @ty@ is the type of sub-expressions, while @op@ is the type
23-- parameters: @ty@ is the type of sub-expressions, while @op@ is the type
@@ -57,7 +57,7 @@ reassociateOpTree getOpName opTree =
57reassociateOpTreeWith ::
57reassociateOpTreeWith ::
58 forall ty op.
58 forall ty op.
59 -- | Fixity map for operators
59 -- | Fixity map for operators
60− Map String Fixity ->
60+ [(RdrName, Fixity)] ->
61 -- | How to get the name of an operator
61 -- | How to get the name of an operator
62 (op -> Maybe RdrName) ->
62 (op -> Maybe RdrName) ->
63 -- | Original 'OpTree'
63 -- | Original 'OpTree'
@@ -68,13 +68,13 @@ reassociateOpTreeWith fixityMap getOpName = go
68 where
68 where
69 fixityOf :: op -> Fixity
69 fixityOf :: op -> Fixity
70 fixityOf op = fromMaybe defaultFixity $ do
70 fixityOf op = fromMaybe defaultFixity $ do
71− s <- occNameString . rdrNameOcc <$> getOpName op
71+ opName <- getOpName op
72− M.lookup s fixityMap
72+ lookup opName fixityMap
73 -- Here, left branch is already associated and the root alongside with
73 -- Here, left branch is already associated and the root alongside with
74 -- the right branch is right-associated. This function picks up one item
74 -- the right branch is right-associated. This function picks up one item
75 -- from the right and inserts it correctly to the left.
75 -- from the right and inserts it correctly to the left.
76 --
76 --
77− -- Also, we are using the 'compareFixity' function which tells if the
77+ -- Also, we are using the 'compareFixity' function which returns if the
78 -- expression should associate to right.
78 -- expression should associate to right.
79 go :: OpTree ty op -> OpTree ty op
79 go :: OpTree ty op -> OpTree ty op
80 -- base cases
80 -- base cases
@@ -94,16 +94,6 @@ reassociateOpTreeWith fixityMap getOpName = go
94 then go $ OpBranch (OpBranch l op (go $ OpBranch r op' l')) op'' r'
94 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'
95 else go $ OpBranch (OpBranch (OpBranch l op r) op' l') op'' r'
96
96
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'.
97-- | Build a map of inferred 'Fixity's from an 'OpTree'.
108buildFixityMap ::
98buildFixityMap ::
109 forall ty op.
99 forall ty op.
@@ -112,26 +102,23 @@ buildFixityMap ::
112 -- | Operator tree
102 -- | Operator tree
113 OpTree (Located ty) (Located op) ->
103 OpTree (Located ty) (Located op) ->
114 -- | Fixity map
104 -- | Fixity map
115− Map String Fixity
105+ [(RdrName, Fixity)]
116buildFixityMap getOpName opTree =
106buildFixityMap getOpName opTree =
117− addOverrides
118− . M.fromList
119− . concatMap (\(i, ns) -> map (\(n, _) -> (n, fixity i InfixL)) ns)
107+ concatMap (\(i, ns) -> map (\(n, _) -> (n, fixity i InfixL)) ns)
120− . zip [2 ..]
108+ . zip [0 ..]
121− . L.groupBy ((==) `on` snd)
109+ . groupBy (doubleWithinEps 0.00001 `on` snd)
122− . selectScores
110+ . (overrides ++)
111+ . avgScores
123 $ score opTree
112 $ score opTree
124 where
113 where
125− addOverrides :: Map String Fixity -> Map String Fixity
114+ -- Add a special case for ($), since it is pretty unlikely for someone
126− addOverrides m =
115+ -- to override it.
127− M.fromList
116+ overrides :: [(RdrName, Double)]
128− [ ("$", fixity 0 InfixR),
117+ overrides =
129− (":", fixity 1 InfixR),
118+ [ (mkRdrUnqual $ mkVarOcc "$", -1)
130− (".", fixity 100 InfixL)
119+ ]
131− ]
120+ -- 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)]
121+ score :: OpTree (Located ty) (Located op) -> [(RdrName, Double)]
135 score (OpNode _) = []
122 score (OpNode _) = []
136 score (OpBranch l o r) = fromMaybe (score r) $ do
123 score (OpBranch l o r) = fromMaybe (score r) $ do
137 -- If we fail to get any of these, 'defaultFixity' will be used by
124 -- If we fail to get any of these, 'defaultFixity' will be used by
@@ -141,27 +128,39 @@ buildFixityMap getOpName opTree =
141 oe <- srcSpanEndLine <$> unSrcSpan (getLoc o) -- operator end
128 oe <- srcSpanEndLine <$> unSrcSpan (getLoc o) -- operator end
142 rb <- srcSpanStartLine <$> unSrcSpan (opTreeLoc r) -- right begin
129 rb <- srcSpanStartLine <$> unSrcSpan (opTreeLoc r) -- right begin
143 oc <- srcSpanStartCol <$> unSrcSpan (getLoc o) -- operator column
130 oc <- srcSpanStartCol <$> unSrcSpan (getLoc o) -- operator column
144− opName <- occNameString . rdrNameOcc <$> getOpName (unLoc o)
131+ opName <- getOpName (unLoc o)
145− let s
132+ let s =
146− | le < ob = AtBeginning oc
133+ if le < ob
134+ then-- if the operator is in the beginning of a line, assign
135+ -- a score relative to its column within range [0, 1).
136+ fromIntegral oc / fromIntegral (maxCol + 1)
137+ else-- if the operator is in the end of the line, assign the
138+ -- score 1.
139+
147− | oe < rb = AtEnd
140+ if oe < rb
148− | otherwise = InBetween
141+ then 1
142+ else 2 -- otherwise, assign a high score.
149 return $ (opName, s) : score r
143 return $ (opName, s) : score r
150− selectScores :: [(String, Score)] -> [(String, Score)]
144+ avgScores :: [(RdrName, Double)] -> [(RdrName, Double)]
151− selectScores =
145+ avgScores =
152− L.sortOn snd
146+ sortOn snd
153− . mapMaybe
154− ( \case
155− [] -> Nothing
156− xs@((n, _) : _) -> Just (n, selectScore $ map snd xs)
147+ . map (\xs@((n, _) : _) -> (n, avg $ map snd xs))
157− )
158− . L.groupBy ((==) `on` fst)
148+ . groupBy ((==) `on` fst)
159− . L.sort
149+ . sort
160− selectScore :: [Score] -> Score
150+ avg :: [Double] -> Double
161− selectScore xs =
151+ avg i = sum i / fromIntegral (length i)
162− case filter (/= InBetween) xs of
152+ -- The start column of the rightmost operator.
163− [] -> InBetween
153+ maxCol = go opTree
154+ where
155+ go (OpNode (L _ _)) = 0
156+ go (OpBranch l (L o _) r) =
164− xs' -> maximum xs'
157+ maximum
158+ [ go l,
159+ maybe 0 srcSpanStartCol (unSrcSpan o),
160+ go r
161+ ]
162+ unSrcSpan (RealSrcSpan r) = Just r
163+ unSrcSpan (UnhelpfulSpan _) = Nothing
165
164
166----------------------------------------------------------------------------
165----------------------------------------------------------------------------
167-- Helpers
166-- Helpers
@@ -175,3 +174,9 @@ normalizeOpTree (OpBranch (OpNode l) lop r) =
175 OpBranch (OpNode l) lop (normalizeOpTree r)
174 OpBranch (OpNode l) lop (normalizeOpTree r)
176normalizeOpTree (OpBranch (OpBranch l' lop' r') lop r) =
175normalizeOpTree (OpBranch (OpBranch l' lop' r') lop r) =
177 normalizeOpTree (OpBranch l' lop' (OpBranch r' lop r))
176 normalizeOpTree (OpBranch l' lop' (OpBranch r' lop r))
177+
178+fixity :: Int -> FixityDirection -> Fixity
179+fixity = Fixity NoSourceText
180+
181+doubleWithinEps :: Double -> Double -> Double -> Bool
182+doubleWithinEps eps a b = abs (a - b) < eps
src/Ormolu/Printer/SpanStream.hs+1−1
@@ -36,7 +36,7 @@ mkSpanStream a =
36 $ everything mappend (const mempty `ext2Q` queryLocated) a
36 $ everything mappend (const mempty `ext2Q` queryLocated) a
37 where
37 where
38 queryLocated ::
38 queryLocated ::
39− (Data e0) =>
39+ (Data e0, Data e1) =>
40 GenLocated e0 e1 ->
40 GenLocated e0 e1 ->
41 DList RealSrcSpan
41 DList RealSrcSpan
42 queryLocated (L mspn _) =
42 queryLocated (L mspn _) =
src/Ormolu/Processing/Common.hsdeleted−27
@@ -1,27 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−
3−-- | Common definitions for pre- and post- processing.
4−module Ormolu.Processing.Common
5− ( OrmoluState (..),
6− startDisabling,
7− endDisabling,
8− )
9−where
10−
11−import Data.String (IsString (..))
12−
13−-- | Ormolu state.
14−data OrmoluState
15− = -- | Enabled
16− OrmoluEnabled
17− | -- | Disabled
18− OrmoluDisabled
19− deriving (Eq, Show)
20−
21−-- | Marker for the beginning of the region where Ormolu should be disabled.
22−startDisabling :: IsString s => s
23−startDisabling = "{- ORMOLU_DISABLE_START"
24−
25−-- | Marker for the end of the region where Ormolu should be disabled.
26−endDisabling :: IsString s => s
27−endDisabling = "ORMOLU_DISABLE_END -}"
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.hsdeleted−31
@@ -1,31 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE ViewPatterns #-}
3−
4−-- | Postprocessing for the results of printing.
5−module Ormolu.Processing.Postprocess
6− ( postprocess,
7− )
8−where
9−
10−import Data.Text (Text)
11−import qualified Data.Text as T
12−import Ormolu.Processing.Common
13−import qualified Ormolu.Processing.Cpp as Cpp
14−
15−-- | Postprocess output of the formatter.
16−postprocess ::
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)
27− . T.lines
28− where
29− magicComment (T.stripStart -> x) =
30− x == startDisabling || x == endDisabling
31− indentLine x = T.replicate indent " " <> x
src/Ormolu/Processing/Preprocess.hsdeleted−149
@@ -1,149 +0,0 @@
1−{-# LANGUAGE BangPatterns #-}
2−{-# LANGUAGE LambdaCase #-}
3−{-# LANGUAGE RecordWildCards #-}
4−
5−-- | Preprocessing for input source code.
6−module Ormolu.Processing.Preprocess
7− ( preprocess,
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, maybeToList)
15−import FastString
16−import Ormolu.Config (RegionDeltas (..))
17−import Ormolu.Parser.Shebang (isShebang)
18−import Ormolu.Processing.Common
19−import qualified Ormolu.Processing.Cpp as Cpp
20−import SrcLoc
21−
22−-- | Transform given input possibly returning comments extracted from it.
23−-- This handles LINE pragmas, CPP, shebangs, and the magic comments for
24−-- enabling\/disabling of Ormolu.
25−preprocess ::
26− -- | File name, just to use in the spans
27− FilePath ->
28− -- | Input to process
29− String ->
30− -- | Region deltas
31− RegionDeltas ->
32− -- | Literal prefix, pre-processed input, literal suffix, extra comments
33− (String, String, String, [Located String])
34−preprocess path input RegionDeltas {..} =
35− go 1 OrmoluEnabled Cpp.Outside id id regionLines
36− 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
42− [] ->
43− let input' = unlines (inputSoFar [])
44− in ( unlines prefixLines,
45− case ormoluState of
46− OrmoluEnabled -> input'
47− OrmoluDisabled -> input' ++ endDisabling,
48− unlines suffixLines,
49− csSoFar []
50− )
51− (x : xs) ->
52− let (x', ormoluState', cppState', cs) =
53− processLine path n ormoluState cppState x
54− in go
55− (n + 1)
56− ormoluState'
57− cppState'
58− (inputSoFar . (x' :))
59− (csSoFar . (maybeToList cs ++))
60− xs
61−
62−-- | Transform a given line possibly returning a comment extracted from it.
63−processLine ::
64− -- | File name, just to use in the spans
65− FilePath ->
66− -- | Line number of this line
67− Int ->
68− -- | Whether Ormolu is currently enabled
69− OrmoluState ->
70− -- | CPP state
71− Cpp.State ->
72− -- | The actual line
73− String ->
74− -- | Adjusted line and possibly a comment extracted from it
75− (String, OrmoluState, Cpp.State, Maybe (Located String))
76−processLine path n ormoluState Cpp.Outside line
77− | "{-# LINE" `L.isPrefixOf` line =
78− let (pragma, res) = getPragma line
79− size = length pragma
80− ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (size + 1))
81− in (res, ormoluState, Cpp.Outside, Just (L ss pragma))
82− | isOrmoluEnable line =
83− case ormoluState of
84− OrmoluEnabled ->
85− (enableMarker, OrmoluEnabled, Cpp.Outside, Nothing)
86− OrmoluDisabled ->
87− (endDisabling ++ enableMarker, OrmoluEnabled, Cpp.Outside, Nothing)
88− | isOrmoluDisable line =
89− case ormoluState of
90− OrmoluEnabled ->
91− (disableMarker ++ startDisabling, OrmoluDisabled, Cpp.Outside, Nothing)
92− OrmoluDisabled ->
93− (disableMarker, OrmoluDisabled, Cpp.Outside, Nothing)
94− | isShebang line =
95− let ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (length line))
96− in ("", ormoluState, Cpp.Outside, Just (L ss line))
97− | otherwise =
98− let (line', cppState') = Cpp.processLine line Cpp.Outside
99− in (line', ormoluState, cppState', Nothing)
100− where
101− 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−
106−-- | Take a line pragma and output its replacement (where line pragma is
107−-- replaced with spaces) and the contents of the pragma itself.
108−getPragma ::
109− -- | Pragma line to analyze
110− String ->
111− -- | Contents of the pragma and its replacement line
112− (String, String)
113−getPragma [] = error "Ormolu.Preprocess.getPragma: input must not be empty"
114−getPragma s@(x : xs)
115− | "#-}" `L.isPrefixOf` s = ("#-}", " " ++ drop 3 s)
116− | otherwise =
117− let (prag, remline) = getPragma xs
118− in (x : prag, ' ' : remline)
119−
120−-- | Canonical enable marker.
121−enableMarker :: String
122−enableMarker = "{- ORMOLU_ENABLE -}"
123−
124−-- | Canonical disable marker.
125−disableMarker :: String
126−disableMarker = "{- ORMOLU_DISABLE -}"
127−
128−-- | Return 'True' if the given string is an enabling marker.
129−isOrmoluEnable :: String -> Bool
130−isOrmoluEnable = magicComment "ORMOLU_ENABLE"
131−
132−-- | Return 'True' if the given string is a disabling marker.
133−isOrmoluDisable :: String -> Bool
134−isOrmoluDisable = magicComment "ORMOLU_DISABLE"
135−
136−-- | Construct a function for whitespace-insensitive matching of string.
137−magicComment ::
138− -- | What to expect
139− String ->
140− -- | String to test
141− String ->
142− -- | Whether or not the two strings watch
143− Bool
144−magicComment expected s0 = isJust $ do
145− let trim = dropWhile isSpace
146− s1 <- trim <$> L.stripPrefix "{-" (trim s0)
147− s2 <- trim <$> L.stripPrefix expected s1
148− s3 <- L.stripPrefix "-}" s2
149− guard (all isSpace s3)
src/Ormolu/Utils.hs+10−91
@@ -1,66 +1,40 @@
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,
14− unSrcSpan,
15− incSpanLine,
16− separatedByBlank,
17− separatedByBlankNE,
18− onTheSameLine,
19− removeIndentation,
20 )
11 )
21where
12where
22
13
23−import Data.Char (isSpace)
14+import Data.Data (Data, showConstr, toConstr)
24import Data.List (dropWhileEnd)
15import Data.List (dropWhileEnd)
25import Data.List.NonEmpty (NonEmpty (..))
16import Data.List.NonEmpty (NonEmpty (..))
26−import qualified Data.List.NonEmpty as NE
27−import Data.Maybe (fromMaybe)
28import Data.Text (Text)
17import Data.Text (Text)
29import qualified Data.Text as T
18import qualified Data.Text as T
30−import GHC
19+import HsDoc (HsDocString, unpackHDS)
31−import GHC.DynFlags (baseDynFlags)
32import qualified Outputable as GHC
20import qualified Outputable as GHC
33−
21+import SrcLoc
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
22
53-- | Combine all source spans from the given list.
23-- | Combine all source spans from the given list.
54combineSrcSpans' :: NonEmpty SrcSpan -> SrcSpan
24combineSrcSpans' :: NonEmpty SrcSpan -> SrcSpan
55combineSrcSpans' (x :| xs) = foldr combineSrcSpans x xs
25combineSrcSpans' (x :| xs) = foldr combineSrcSpans x xs
56
26
27+-- | Return 'True' if given element of AST is module.
28+isModule :: Data a => a -> Bool
29+isModule x = showConstr (toConstr x) == "HsModule"
30+
57-- | Placeholder for things that are not yet implemented.
31-- | Placeholder for things that are not yet implemented.
58notImplemented :: String -> a
32notImplemented :: String -> a
59notImplemented msg = error $ "not implemented yet: " ++ msg
33notImplemented msg = error $ "not implemented yet: " ++ msg
60
34
61-- | Pretty-print an 'GHC.Outputable' thing.
35-- | Pretty-print an 'GHC.Outputable' thing.
62showOutputable :: GHC.Outputable o => o -> String
36showOutputable :: GHC.Outputable o => o -> String
63−showOutputable = GHC.showSDoc baseDynFlags . GHC.ppr
37+showOutputable = GHC.showSDocUnsafe . GHC.ppr
64
38
65-- | Split and normalize a doc string. The result is a list of lines that
39-- | Split and normalize a doc string. The result is a list of lines that
66-- make up the comment.
40-- make up the comment.
@@ -98,58 +72,3 @@ splitDocString docStr =
98 in if leadingSpace x
72 in if leadingSpace x
99 then dropSpace <$> xs
73 then dropSpace <$> xs
100 else xs
74 else xs
101−
102−-- | Get 'LHsType' out of 'LHsTypeArg'.
103−typeArgToType :: LHsTypeArg p -> LHsType p
104−typeArgToType = \case
105− HsValArg tm -> tm
106− HsTypeArg _ ty -> ty
107− HsArgPar _ -> notImplemented "HsArgPar"
108−
109−-- | Get 'RealSrcSpan' out of 'SrcSpan' if the span is “helpful”.
110−unSrcSpan :: SrcSpan -> Maybe RealSrcSpan
111−unSrcSpan = \case
112− RealSrcSpan r -> Just r
113− 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−
129−-- | Do two declarations have a blank between them?
130−separatedByBlank :: (a -> SrcSpan) -> a -> a -> Bool
131−separatedByBlank loc a b =
132− fromMaybe False $ do
133− endA <- srcSpanEndLine <$> unSrcSpan (loc a)
134− startB <- srcSpanStartLine <$> unSrcSpan (loc b)
135− pure (startB - endA >= 2)
136−
137−-- | Do two declaration groups have a blank between them?
138−separatedByBlankNE :: (a -> SrcSpan) -> NonEmpty a -> NonEmpty a -> Bool
139−separatedByBlankNE 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/Parser/PragmaSpec.hs+1−1
@@ -4,7 +4,7 @@ import Ormolu.Parser.Pragma
4import Test.Hspec
4import Test.Hspec
5
5
6spec :: Spec
6spec :: Spec
7−spec =
7+spec = do
8 describe "parsePragma" $ do
8 describe "parsePragma" $ do
9 stdTest "{-# LANGUAGE Foo #-}" (Just (PragmaLanguage ["Foo"]))
9 stdTest "{-# LANGUAGE Foo #-}" (Just (PragmaLanguage ["Foo"]))
10 stdTest "{-# language Foo #-}" (Just (PragmaLanguage ["Foo"]))
10 stdTest "{-# language Foo #-}" (Just (PragmaLanguage ["Foo"]))
tests/Ormolu/PrinterSpec.hs+10−7
@@ -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
@@ -12,7 +15,7 @@ import qualified Data.Text.IO as T
12import Ormolu
15import Ormolu
13import Path
16import Path
14import Path.IO
17import Path.IO
15−import qualified System.FilePath as F
18+import System.FilePath (addExtension, dropExtensions, splitExtensions)
16import Test.Hspec
19import Test.Hspec
17
20
18spec :: Spec
21spec :: Spec
@@ -50,19 +53,19 @@ locateExamples =
50isInput :: Path Rel File -> Bool
53isInput :: Path Rel File -> Bool
51isInput path =
54isInput path =
52 let s = fromRelFile path
55 let s = fromRelFile path
53− (s', exts) = F.splitExtensions s
56+ (s', exts) = splitExtensions s
54 in exts == ".hs" && not ("-out" `isSuffixOf` s')
57 in exts == ".hs" && not ("-out" `isSuffixOf` s')
55
58
56-- | For given path of input file return expected name of output.
59-- | For given path of input file return expected name of output.
57deriveOutput :: Path Rel File -> IO (Path Rel File)
60deriveOutput :: Path Rel File -> IO (Path Rel File)
58deriveOutput path =
61deriveOutput path =
59 parseRelFile $
62 parseRelFile $
60− F.addExtension (F.dropExtensions (fromRelFile path) ++ "-out") "hs"
63+ addExtension (dropExtensions (fromRelFile path) ++ "-out") "hs"
61
64
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