on master help sign in
.buildkite/pipeline.ymlnew file+18
since splitsnapshots
unifiedsplit
@@ -0,0 +1,18 @@
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.ymldeleted−44
@@ -1,44 +0,0 @@
1−version: 2
2−
3−jobs:
4− build_ghc864:
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 -f nix/nixpkgs/ -iA cachix
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
32− - run:
33− name: Generate Haddocks
34− command: nix-build --attr ormolu.doc
35− - store_artifacts:
36− path: result-doc/share/doc
37− destination: haddock
38−
39−workflows:
40− version: 2
41− build:
42− jobs:
43− - build_ghc864:
44− context: org-global
.github/workflows/binaries.ymlnew file+39
@@ -0,0 +1,39 @@
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.shnew file+7
@@ -0,0 +1,7 @@
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,4 +26,5 @@ cabal.sandbox.config
26dist-*/
26dist-*/
27dist/
27dist/
28stack.yaml
28stack.yaml
29+stack.yaml.lock
29result*
30result*
CHANGELOG.md+231
@@ -1,3 +1,234 @@
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+
1## Ormolu 0.0.1.0
232## Ormolu 0.0.1.0
2
233
3* Initial release.
234* Initial release.
CONTRIBUTING.md+28−34
@@ -1,8 +1,7 @@
1# Contributing
1# Contributing
2
2
3Issues (bugs, feature requests or otherwise feedback) may be reported in
3Issues (bugs, feature requests or otherwise feedback) may be reported in
4−[the GitHub issue tracker for this
4+[the GitHub issue tracker for this project][issues]. Pull requests are also
5−project](https://github.com/tweag/ormolu/issues). Pull requests are also
6welcome.
5welcome.
7
6
8When contributing to this repository, please first discuss the change you
7When contributing to this repository, please first discuss the change you
@@ -16,36 +15,7 @@ messages and PR descriptions.
16
15
17## What to hack on?
16## What to hack on?
18
17
19−Right now there are two options for people who want to contribute:
20−
21−* [Implementing rendering of AST][cover-ast]. This is the main focus right
18+* [Fixing bugs][bugs]. This is the main focus right now.
22− now because we want to have a MVP which can render all syntactical
23− constructions found in Haskell source code. Once that is achieved we'll
24− polish the tool iteratively.
25−* [Fixing bugs][bugs]. If this seems more interesting than implementing
26− rendering of AST, you are welcome to do this as well.
27−
28−## Implementing rendering of AST
29−
30−The `Ormolu.Printer.Combinators` module provides a DSL for rendering of GHC
31−AST. You'll probably only need this one module for writing new rendering
32−functions. The module documents how to use the printing combinators it
33−provides. Consult the Haddocks to learn more about them.
34−
35−Create new modules corresponding to the things you want to render under
36−`Ormolu.Printer.Meat`. For example, there are `Ormolu.Printer.Meat.Type` and
37−`Ormolu.Printer.Meat.Declaration.Data`.
38−
39−Concrete rendering functions get their names by appending `p_` to the name
40−of the type which describes a particular part of AST. For example, the
41−function for rendering types is correspondingly:
42−
43−```haskell
44−p_hsType :: HsType GhcPs -> R ()
45−```
46−
47−In general rendering functions like this take 1 or more arguments and
48−produce `R ()` which is a rendering action.
49
19
50### Testing
20### Testing
51
21
@@ -60,11 +30,35 @@ Testing is performed as following:
60* 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
61 AST obtained from the original file. They should match.
31 AST obtained from the original file. They should match.
62* The output of printer is checked against the expected output.
32* The output of printer is checked against the expected output.
63−* Idempotency property is verified: formatting already formatted code
33+* Idempotence property is verified: formatting already formatted code
64 results in exactly the same output.
34 results in exactly the same output.
65
35
66Examples can be organized in sub-directories, see the existing ones for
36Examples can be organized in sub-directories, see the existing ones for
67inspiration.
37inspiration.
68
38
39+Please note that we try to keep individual files at most 25 lines long
40+because otherwise it's hard to figure out want went wrong when a test fails.
41+
42+## CI
43+
44+We use Circle CI. Some outside contributors may have problems, as in, CI
45+won't run for PRs opened from forks with “unauthorized” errors. In that case
46+the best we can do is to add you as a contributor or to restart your build
47+manually.
48+
49+If you have been added as a contributor but the builds still do not start,
50+try clicking
51+
52+```
53+User settings -> Account integrations -> Refresh permissions
54+```
55+
56+in Circle CI app.
57+
58+## Formatting
59+
60+Use `format.sh` script to format Ormolu with current version of Ormolu. If
61+Ormolu is not formatted like this, the CI will fail.
62+
69−[cover-ast]: https://github.com/tweag/ormolu/issues?q=is%3Aissue+is%3Aopen+label%3Acovering-ghc-ast
63+[issues]: https://github.com/tweag/ormolu/issues
70[bugs]: https://github.com/tweag/ormolu/issues?q=is%3Aissue+is%3Aopen+label%3Abug
64[bugs]: https://github.com/tweag/ormolu/issues?q=is%3Aissue+is%3Aopen+label%3Abug
DESIGN.md+26−50
@@ -1,5 +1,8 @@
1# Ormolu
1# Ormolu
2
2
3+*This document represents our discussions and plans at early stages of
4+development, it is no longer being updated.*
5+
3* [Analysis of the existing solutions](#analysis-of-the-existing-solutions)
6* [Analysis of the existing solutions](#analysis-of-the-existing-solutions)
4 * [Brittany](#brittany)
7 * [Brittany](#brittany)
5 * [Hindent](#hindent)
8 * [Hindent](#hindent)
@@ -14,14 +17,14 @@
14 * [Testing](#testing)
17 * [Testing](#testing)
15 * [Functionality of executable](#functionality-of-executable)
18 * [Functionality of executable](#functionality-of-executable)
16 * [Why not contribute to/fork Hindent or Brittany?](#why-not-contribute-tofork-hindent-or-brittany)
19 * [Why not contribute to/fork Hindent or Brittany?](#why-not-contribute-tofork-hindent-or-brittany)
17−* [Roadmap](#roadmap)
20+* [Examples](#examples)
18
21
19This document describes design of a new formatter for Haskell source code.
22This document describes design of a new formatter for Haskell source code.
20It also includes recommendations for future implementers.
23It also includes recommendations for future implementers.
21
24
22We set for the following goals (mostly taken from
25We set for the following goals (mostly taken from
23[brittany](https://github.com/lspitzner/brittany)):
26[brittany](https://github.com/lspitzner/brittany)):
24−* Preserve the meaning of the formatted functions;
27+* Preserve the meaning of the formatted functions when no CPP is used;
25* Make reasonable use of screen space;
28* Make reasonable use of screen space;
26* 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;
27* Preserve comments;
30* Preserve comments;
@@ -137,8 +140,10 @@ impossible to guess what they'll be called on.
137
140
138### CPP
141### CPP
139
142
140−Formatting a module which uses CPP directives won't be supported. Instead,
143+We allow CPP directives in the input, but we forgo the goal to preserve the
144+meaning of the formatted functions in that case.
145+Instead of supporting CPP better, we hope for a solution to replace CPP to
141−we hope for a solution to replace CPP to do conditional compilation.
146+do conditional compilation.
142
147
143There are the following challenges when formatting a module with CPP:
148There are the following challenges when formatting a module with CPP:
144
149
@@ -177,14 +182,15 @@ True
177```
182```
178
183
179At the time of this writing, formatting this program with Hindent
184At the time of this writing, formatting this program with Hindent
180−produces the same output we would get if the CPP directives were
185+or Ormolu produces the same output we would get if the CPP directives
181−considered comments:
186+were considered comments:
182
187
183```
188```
184−$ hindent --version
189+$ ormolu --version
185−hindent 5.2.7
190+ormolu 0.0.5.0 HEAD fc64eada5c4da7a5b07d2872e253671b48aec115
191+using ghc-lib-parser 8.10.1.20200412
186
192
187−$ hindent test.hs
193+$ ormolu --mode inplace test.hs
188
194
189$ cat test.hs
195$ cat test.hs
190{-# LANGUAGE CPP #-}
196{-# LANGUAGE CPP #-}
@@ -224,9 +230,6 @@ to parse Haskell modules. If CPP is replaced with some language
224extension or mechanism to do conditional compilation, all tools
230extension or mechanism to do conditional compilation, all tools
225will benefit from it.
231will benefit from it.
226
232
227−Therefore, CPP won't be supported. If the CPP extension
228−is enabled, we should signal an error right away.
229−
230### Printing
233### Printing
231
234
232Just pretty-printing code (following the approach of Hindent) seems sane. It
235Just pretty-printing code (following the approach of Hindent) seems sane. It
@@ -282,22 +285,22 @@ map :: (a -> b) -> [a] -> [b]
282foldr :: (a -> b -> b) ->
285foldr :: (a -> b -> b) ->
283 b -> [a] -> [b]
286 b -> [a] -> [b]
284-- Is reformatted to:
287-- Is reformatted to:
285−foldr
288+foldr ::
286− :: (a -> b -> b)
289+ (a -> b -> b) ->
287− -> b
290+ b ->
288− -> [a]
291+ [a] ->
289− -> [b]
292+ [b]
290
293
291t = let x = foo bar
294t = let x = foo bar
292 baz
295 baz
293 in foo bar baz
296 in foo bar baz
294-- Is reformatted to:
297-- Is reformatted to:
295t =
298t =
296− let x =
299+ let x =
297− foo
300+ foo
298− bar
301+ bar
299− baz
302+ baz
300− in foo far baz
303+ in foo far baz
301```
304```
302
305
303Crucially, no effort is made to fit within reasonable line lengths. That's
306Crucially, no effort is made to fit within reasonable line lengths. That's
@@ -388,34 +391,7 @@ also possible that we'll find a nicer way to write pretty-printer.
388
391
389## Examples
392## Examples
390
393
391−A list of formatting examples can be found [here](EXAMPLES.md).
394+A list of formatting examples can be found [here](data/examples).
392−
393−## Roadmap
394−
395−Proposed roadmap (for a single person, about 39 full-time work days):
396−
397−* ~~Create and setup a repo, setup CI (less than 1 day).~~
398−* ~~Implement parsing (2 days).~~
399−* ~~Implement basis for pretty-printing of code. We could take
400− [this][hindent-printer] as inspiration, although AST from the `ghc`
401− package may be slightly different. Also, don't forget about annotations
402− and comments (1 week).~~
403−* Implement executable program so we can easier fool around. Try it on
404− simple code samples (2 days).
405−* Implement location and reading of configuration file in YAML format (2
406− days).
407−* Continue writing the pretty-printing code till we cover everything. Start
408− adding tests, see [the section about testing](#testing). Fix bugs. At this
409− point just repeat this till we cover everything that Brittany and Hindent
410− can do maybe by stealing their tests (at least 2 weeks).
411−* Start checking how our formatter works on real-world code from Hackage.
412− Fix bugs that we find that way (2 weeks).
413−* Write a good readme explaining why the project was created and how it is
414− better, etc (2 days).
415−* Switch CI to Travis and test with multiple GHC versions (1 day).
416−* Make and announce the first public release on Twitter/Reddit (1 day).
417−* Figure out how to use the formatter application with major text editors
418− and add the info to the readme (no estimate).
419
395
420[brittany]: https://hackage.haskell.org/package/brittany
396[brittany]: https://hackage.haskell.org/package/brittany
421[hindent]: https://hackage.haskell.org/package/hindent
397[hindent]: https://hackage.haskell.org/package/hindent
README.md+117−26
@@ -1,26 +1,29 @@
1# Ormolu
1# Ormolu
2
2
3−[![CircleCI](https://circleci.com/gh/tweag/ormolu/tree/master.svg?style=svg&circle-token=cfd37a39265561eb44e608f97cf953cb2a394c03)](https://circleci.com/gh/tweag/ormolu/tree/master)
3+[![License BSD3](https://img.shields.io/badge/license-BSD3-brightgreen.svg)](http://opensource.org/licenses/BSD-3-Clause)
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)
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)
4
8
5Ormolu 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
6−the following features in mind:
10+the following goals in mind:
7
11
8* Using GHC's own parser to avoid parsing problems caused by
12* Using GHC's own parser to avoid parsing problems caused by
9 [`haskell-src-exts`][haskell-src-exts].
13 [`haskell-src-exts`][haskell-src-exts].
10−* Let some whitespace be programmable. The layout of the input
14+* Let some whitespace be programmable. The layout of the input influences
11− influence the layout choices in the output. This means that the
15+ the layout choices in the output. This means that the choices between
12− choices between single-line/multi-line layouts in each particular
16+ single-line/multi-line layouts in each particular situation are made by
13− situation are made by the user, not by an algorithm. This makes the
17+ the user, not by an algorithm. This makes the implementation simpler and
14− implementation simpler and leaves some control to the user while
18+ leaves some control to the user while still guaranteeing that the
15− still guaranteeing that the formatted code is stylistically
19+ formatted code is stylistically consistent.
16− consistent.
17−* Writing code in such a way so it's easy to modify and maintain. Roughly,
20+* Writing code in such a way so it's easy to modify and maintain.
18− it means that the project follows the path of [`hindent`][hindent] and is
19− very much about printing AST in a particular way.
20* Implementing one “true” formatting style which admits no configuration.
21* Implementing one “true” formatting style which admits no configuration.
21* That formatting style aims to result in minimal diffs while still
22* That formatting style aims to result in minimal diffs while still
22 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
25+ extensions enter broad use, we may change the style to accommodate them.
23−* Idempotency: formatting already formatted code doesn't change it.
26+* Idempotence: formatting already formatted code doesn't change it.
24* 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
25 projects without exposing unfortunate, disappointing bugs here and there.
28 projects without exposing unfortunate, disappointing bugs here and there.
26
29
@@ -29,7 +32,7 @@ the following features in mind:
29The easiest way to build the project is with Nix:
32The easiest way to build the project is with Nix:
30
33
31```console
34```console
32−$ nix-build
35+$ nix-build -A ormolu
33```
36```
34
37
35Or with `cabal-install` from the Nix shell:
38Or with `cabal-install` from the Nix shell:
@@ -42,11 +45,36 @@ Alternatively, `stack` could be used with a `stack.yaml` file as follows.
42
45
43```console
46```console
44$ cat stack.yaml
47$ cat stack.yaml
45−resolver: lts-13.19
48+resolver: lts-16.0
46packages:
49packages:
47- '.'
50- '.'
48
51
49−$ stack build
52+$ stack build # to build
53+$ stack install # to install
54+```
55+
56+To use Ormolu directly from GitHub with Nix, this snippet may come in handy:
57+
58+```nix
59+# This overlay adds Ormolu straight from GitHub.
60+self: super:
61+
62+let source = super.fetchFromGitHub {
63+ owner = "tweag";
64+ repo = "ormolu";
65+ rev = "de279d80122b287374d4ed87c7b630db1f157642"; # update as necessary
66+ sha256 = "0qrxfk62ww6b60ha9sqcgl4nb2n5fhf66a65wszjngwkybwlzmrv"; # as well
67+ };
68+ ormolu = import source { pkgs = self; };
69+in {
70+ haskell = super.haskell // {
71+ packages = super.haskell.packages // {
72+ "${ormolu.ormoluCompiler}" = super.haskell.packages.${ormolu.ormoluCompiler}.override {
73+ overrides = ormolu.ormoluOverlay;
74+ };
75+ };
76+ };
77+}
50```
78```
51
79
52## Usage
80## Usage
@@ -64,27 +92,90 @@ formatted output.
64$ ormolu --mode inplace Module.hs
92$ ormolu --mode inplace Module.hs
65```
93```
66
94
67−A configuration file can specify the language extensions to use by default.
95+Use `find` to format a tree recursively:
68
96
69```console
97```console
70−$ cat ormolu.yaml
98+$ ormolu --mode inplace $(find . -name '*.hs')
71−ghc-opts:
99+```
72− - -XLambdaCase
100+
73−unsafe: False
101+## Magic comments
74−debug: False
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
123+
124+* CPP support is experimental. CPP is virtually impossible to handle
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
130+ criterion than just being valid Haskell modules.
131+* Various minor idempotence issues, most of them are related to comments.
75
132
76−$ ormolu -c ormolu.yaml Module.hs
133+## Running on Hackage
134+
135+It's possible to try Ormolu on arbitrary packages from Hackage. For that
136+execute (from the root of the cloned repo):
137+
138+```console
139+$ nix-build -A hackage.<package>
140+```
141+
142+Then inspect `result/log.txt` for possible problems. The derivation will
143+also contain formatted `.hs` files for inspection and original inputs with
144+`.hs-original` extension (those are with CPP dropped, exactly what is fed
145+into Ormolu).
146+
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
77```
161```
78
162
79## Contributing
163## Contributing
80
164
81−See [CONTRIBUTING.md](./CONTRIBUTING.md).
165+See [CONTRIBUTING.md][contributing].
82
166
83## License
167## License
84
168
85−See [LICENSE.md](./LICENSE.md).
169+See [LICENSE.md][license].
86
170
87Copyright © 2018–present Tweag I/O
171Copyright © 2018–present Tweag I/O
88
172
173+[design-cpp]: https://github.com/tweag/ormolu/blob/master/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
89[haskell-src-exts]: https://hackage.haskell.org/package/haskell-src-exts
176[haskell-src-exts]: https://hackage.haskell.org/package/haskell-src-exts
90−[hindent]: https://hackage.haskell.org/package/hindent
177+[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+159−91
@@ -1,135 +1,203 @@
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 #-}
5
6
6module Main (main) where
7module Main (main) where
7
8
9+import Control.Exception (SomeException, displayException, try)
8import Control.Monad
10import Control.Monad
11+import Data.Bool (bool)
12+import Data.Either (lefts)
9−import Data.List (intercalate)
13+import Data.List (intercalate, sort)
14+import qualified Data.Text.IO as TIO
10import Data.Version (showVersion)
15import Data.Version (showVersion)
11import Development.GitRev
16import Development.GitRev
12import Options.Applicative
17import Options.Applicative
13import Ormolu
18import Ormolu
19+import Ormolu.Parser (manualExts)
20+import Ormolu.Utils (showOutputable)
14import Paths_ormolu (version)
21import Paths_ormolu (version)
15import System.Exit (ExitCode (..), exitWith)
22import System.Exit (ExitCode (..), exitWith)
16import System.IO (hPutStrLn, stderr)
23import System.IO (hPutStrLn, stderr)
17−import qualified Data.Text.IO as TIO
18
24
19-- | Entry point of the program.
25-- | Entry point of the program.
20−
21main :: IO ()
26main :: IO ()
22main = withPrettyOrmoluExceptions $ do
27main = withPrettyOrmoluExceptions $ do
23 Opts {..} <- execParser optsParserInfo
28 Opts {..} <- execParser optsParserInfo
24− r <- case optInputFile of
29+ let formatOne' = formatOne optMode optConfig
30+ case optInputFiles of
31+ [] -> formatOne' Nothing
32+ ["-"] -> formatOne' Nothing
33+ [x] -> formatOne' (Just x)
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+
43+-- | Format a single input.
44+formatOne ::
45+ -- | Mode of operation
46+ Mode ->
47+ -- | Configuration
48+ Config RegionIndices ->
49+ -- | File to format or stdin as 'Nothing'
50+ Maybe FilePath ->
51+ IO ()
52+formatOne mode config = \case
53+ Nothing -> do
25− "-" -> ormoluStdin optConfig
54+ r <- ormoluStdin config
26− inputFile -> ormoluFile optConfig inputFile
55+ case mode of
27− let notForStdin = do
56+ Stdout -> TIO.putStr r
28− when (optInputFile == "-") $ do
57+ _ -> do
29− hPutStrLn
58+ hPutStrLn
30− stderr
59+ stderr
31− "This feature is not supported when input comes from stdin."
60+ "This feature is not supported when input comes from stdin."
32− -- 101 is different from all the other exit codes we already use.
61+ -- 101 is different from all the other exit codes we already use.
33− exitWith (ExitFailure 101)
62+ exitWith (ExitFailure 101)
63+ Just inputFile -> do
64+ originalInput <- TIO.readFile inputFile
65+ formattedInput <- ormoluFile config inputFile
34− case optMode of
66+ case mode of
35− Stdout ->
67+ Stdout ->
36− TIO.putStr r
68+ TIO.putStr formattedInput
37− InPlace -> do
69+ InPlace -> do
38− notForStdin
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) $
39− TIO.writeFile optInputFile r
74+ TIO.writeFile inputFile formattedInput
40− Check -> do
75+ Check -> do
41− notForStdin
76+ when (formattedInput /= originalInput) $
42− r' <- TIO.readFile optInputFile
43− when (r /= r') $
44− -- 100 is different to all the other exit code that are emitted
77+ -- 100 is different to all the other exit code that are emitted
45− -- either from an 'OrmoluException' or from 'error' and
78+ -- either from an 'OrmoluException' or from 'error' and
46− -- 'notImplemented'.
79+ -- 'notImplemented'.
47− exitWith (ExitFailure 100)
80+ exitWith (ExitFailure 100)
48
81
49----------------------------------------------------------------------------
82----------------------------------------------------------------------------
50-- Command line options parsing.
83-- Command line options parsing.
51
84
52data Opts = Opts
85data Opts = Opts
53− { optMode :: !Mode
54− -- ^ Mode of operation
86+ { -- | Mode of operation
55− , optConfig :: !Config
87+ optMode :: !Mode,
56− -- ^ Ormolu 'Config'
88+ -- | Ormolu 'Config'
57− , optInputFile :: !FilePath
89+ optConfig :: !(Config RegionIndices),
58− -- ^ Input source file or stdin ("-")
90+ -- | Haskell source files to format or stdin (when the list is empty)
91+ optInputFiles :: ![FilePath]
59 }
92 }
60
93
61-- | Mode of operation.
94-- | Mode of operation.
62−
63data Mode
95data Mode
64− = Stdout -- ^ Output formatted source code to stdout
96+ = -- | Output formatted source code to stdout
97+ Stdout
65− | InPlace -- ^ Overwrite original file
98+ | -- | Overwrite original file
99+ InPlace
66− | Check -- ^ Exit with non-zero status code if
100+ | -- | Exit with non-zero status code if
67− -- source is not already formatted
101+ -- source is not already formatted
102+ Check
68 deriving (Eq, Show)
103 deriving (Eq, Show)
69
104
70optsParserInfo :: ParserInfo Opts
105optsParserInfo :: ParserInfo Opts
106+optsParserInfo =
71−optsParserInfo = info (helper <*> ver <*> optsParser) . mconcat $
107+ info (helper <*> ver <*> exts <*> optsParser) . mconcat $
72− [ fullDesc
108+ [ fullDesc,
73− , progDesc ""
109+ progDesc "",
74− , header ""
110+ header ""
75− ]
111+ ]
76 where
112 where
77 ver :: Parser (a -> a)
113 ver :: Parser (a -> a)
114+ ver =
78− ver = infoOption verStr . mconcat $
115+ infoOption verStr . mconcat $
79− [ long "version"
116+ [ long "version",
80− , short 'v'
117+ short 'v',
81− , help "Print version of the program"
118+ help "Print version of the program"
82− ]
83− verStr = intercalate "\n"
84− [ unwords
85− [ "ormolu"
86− , showVersion version
87− , $gitBranch
88− , $gitHash
89 ]
119 ]
90− , "using ghc " ++ VERSION_ghc
120+ verStr =
121+ intercalate
122+ "\n"
123+ [ unwords
124+ [ "ormolu",
125+ showVersion version,
126+ $gitBranch,
127+ $gitHash
128+ ],
129+ "using ghc-lib-parser " ++ VERSION_ghc_lib_parser
130+ ]
131+ exts :: Parser (a -> a)
132+ exts =
133+ infoOption displayExts . mconcat $
134+ [ long "manual-exts",
135+ help "Display extensions that need to be enabled manually"
91− ]
136+ ]
137+ displayExts = unlines $ sort (showOutputable <$> manualExts)
92
138
93optsParser :: Parser Opts
139optsParser :: Parser Opts
94−optsParser = Opts
140+optsParser =
141+ Opts
142+ <$> ( (fmap (bool Stdout InPlace) . switch . mconcat)
143+ [ short 'i',
144+ help "A shortcut for --mode inplace"
145+ ]
95− <$> (option parseMode . mconcat)
146+ <|> (option parseMode . mconcat)
96− [ long "mode"
147+ [ long "mode",
97− , short 'm'
148+ short 'm',
98− , metavar "MODE"
149+ metavar "MODE",
99− , value Stdout
150+ value Stdout,
100− , help "Mode of operation: 'stdout', 'inplace', or 'check'"
151+ help "Mode of operation: 'stdout' (default), 'inplace', or 'check'"
101− ]
152+ ]
153+ )
102− <*> configParser
154+ <*> configParser
103− <*> (strArgument . mconcat)
155+ <*> (many . strArgument . mconcat)
104− [ metavar "FILE"
156+ [ metavar "FILE",
105− , value "-"
106− , help "Haskell source file to format or stdin (default)"
157+ help "Haskell source files to format or stdin (default)"
107− ]
158+ ]
108
159
109−configParser :: Parser Config
160+configParser :: Parser (Config RegionIndices)
110−configParser = Config
161+configParser =
162+ Config
111− <$> (fmap (fmap DynOption) . many . strOption . mconcat)
163+ <$> (fmap (fmap DynOption) . many . strOption . mconcat)
112− [ long "ghc-opt"
164+ [ long "ghc-opt",
113− , short 'o'
165+ short 'o',
114− , metavar "OPT"
166+ metavar "OPT",
115− , help "GHC options to enable (e.g. language extensions)"
167+ help "GHC options to enable (e.g. language extensions)"
116− ]
168+ ]
117− <*> (switch . mconcat)
169+ <*> (switch . mconcat)
118− [ long "unsafe"
170+ [ long "unsafe",
119− , short 'u'
171+ short 'u',
120− , help "Do formatting faster but without automatic detection of defects"
172+ help "Do formatting faster but without automatic detection of defects"
121− ]
173+ ]
122− <*> (switch . mconcat)
174+ <*> (switch . mconcat)
123− [ long "debug"
175+ [ long "debug",
124− , short 'd'
176+ short 'd',
125− , help "Output information useful for debugging"
177+ help "Output information useful for debugging"
178+ ]
179+ <*> (switch . mconcat)
180+ [ long "check-idempotence",
181+ short 'c',
182+ help "Fail if formatting is not idempotent"
126− ]
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+ ]
190+ <*> (optional . option auto . mconcat)
191+ [ long "end-line",
192+ metavar "END",
193+ help "End line of the region to format (inclusive)"
194+ ]
195+ )
127
196
128----------------------------------------------------------------------------
197----------------------------------------------------------------------------
129-- Helpers
198-- Helpers
130
199
131-- | Parse 'Mode'.
200-- | Parse 'Mode'.
132−
133parseMode :: ReadM Mode
201parseMode :: ReadM Mode
134parseMode = eitherReader $ \case
202parseMode = eitherReader $ \case
135 "stdout" -> Right Stdout
203 "stdout" -> Right Stdout
data/examples/declaration/annotation/annotation-out.hs+4−2
@@ -2,8 +2,8 @@
2
2
3{-# ANN
3{-# ANN
4 module
4 module
5− ( 5
5+ ( 5 ::
6− :: Int
6+ Int
7 )
7 )
8 #-}
8 #-}
9
9
@@ -17,4 +17,6 @@ foo = 5
17 #-}
17 #-}
18
18
19data Foo = Foo Int
19data Foo = Foo Int
20+{-# ANN type Foo ("HLint: ignore") #-}
21+
20{- Comment -}
22{- Comment -}
data/examples/declaration/annotation/annotation.hs+2
@@ -15,4 +15,6 @@ foo = 5
15
15
16data Foo = Foo Int
16data Foo = Foo Int
17
17
18+{-# ANN type Foo ("HLint: ignore") #-}
19+
18{- Comment -}
20{- Comment -}
data/examples/declaration/class/associated-data1-out.hsnew file+13
@@ -0,0 +1,13 @@
1+{-# LANGUAGE TypeFamilies #-}
2+
3+class Foo a where data FooBar a
4+
5+-- | Something.
6+class Bar a where
7+ -- | Bar bar
8+ data BarBar a
9+
10+ -- | Bar baz
11+ data
12+ BarBaz
13+ a
data/examples/declaration/class/associated-data1.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE TypeFamilies #-}
2+
3+class Foo a where data FooBar a
4+
5+-- | Something.
6+class Bar a
7+ where
8+ -- | Bar bar
9+ data BarBar a
10+ -- | Bar baz
11+ data family BarBaz
12+ a
data/examples/declaration/class/associated-data-out.hs → data/examples/declaration/class/associated-data2-out.hsrenamed+1−15
@@ -1,23 +1,9 @@
1{-# LANGUAGE TypeFamilies #-}
1{-# LANGUAGE TypeFamilies #-}
2
2
3−class Foo a where
3+module Main where
4−
5− data FooBar a
6−
7−-- | Something.
8−class Bar a where
9−
10− -- | Bar bar
11− data BarBar a
12−
13− -- | Bar baz
14− data
15− BarBaz
16− a
17
4
18-- | Something more.
5-- | Something more.
19class Baz a where
6class Baz a where
20−
21 -- | Baz bar
7 -- | Baz bar
22 data
8 data
23 BazBar
9 BazBar
data/examples/declaration/class/associated-data.hs → data/examples/declaration/class/associated-data2.hsrenamed+2−11
@@ -1,15 +1,6 @@
1−{-# LANGUAGE TypeFamilies #-}
1+module Main where
2−
3−class Foo a where data FooBar a
4
2
5−-- | Something.
3+{-# LANGUAGE TypeFamilies #-}
6−class Bar a
7− where
8− -- | Bar bar
9− data BarBar a
10− -- | Bar baz
11− data family BarBaz
12− a
13
4
14-- | Something more.
5-- | Something more.
15class Baz a where
6class Baz a where
data/examples/declaration/class/associated-type-defaults-out.hs+1−5
@@ -1,12 +1,9 @@
1{-# LANGUAGE TypeFamilies #-}
1{-# LANGUAGE TypeFamilies #-}
2
2
3−class Foo a where
3+class Foo a where type FooBar a = Int
4−
5− type FooBar a = Int
6
4
7-- | Something.
5-- | Something.
8class Bar a where
6class Bar a where
9−
10 -- Define bar
7 -- Define bar
11 type
8 type
12 BarBar a =
9 BarBar a =
@@ -20,7 +17,6 @@ class Bar a where
20 a
17 a
21
18
22class Baz a where
19class Baz a where
23−
24 type
20 type
25 BazBar
21 BazBar
26 a
22 a
data/examples/declaration/class/associated-types1-out.hsnew file+13
@@ -0,0 +1,13 @@
1+{-# LANGUAGE TypeFamilies #-}
2+
3+class Foo a where type FooBar a
4+
5+-- | Something.
6+class Bar a where
7+ -- | Bar bar
8+ type BarBar a
9+
10+ -- | Bar baz
11+ type
12+ BarBaz
13+ a
data/examples/declaration/class/associated-types1.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE TypeFamilies #-}
2+
3+class Foo a where type FooBar a
4+
5+-- | Something.
6+class Bar a
7+ where
8+ -- | Bar bar
9+ type BarBar a
10+ -- | Bar baz
11+ type BarBaz
12+ a
data/examples/declaration/class/associated-types-out.hs → data/examples/declaration/class/associated-types2-out.hsrenamed+1−15
@@ -1,23 +1,9 @@
1{-# LANGUAGE TypeFamilies #-}
1{-# LANGUAGE TypeFamilies #-}
2
2
3−class Foo a where
3+module Main where
4−
5− type FooBar a
6−
7−-- | Something.
8−class Bar a where
9−
10− -- | Bar bar
11− type BarBar a
12−
13− -- | Bar baz
14− type
15− BarBaz
16− a
17
4
18-- | Something more.
5-- | Something more.
19class Baz a where
6class Baz a where
20−
21 -- | Baz bar
7 -- | Baz bar
22 type
8 type
23 BazBar
9 BazBar
data/examples/declaration/class/associated-types.hs → data/examples/declaration/class/associated-types2.hsrenamed+2−11
@@ -1,15 +1,6 @@
1−{-# LANGUAGE TypeFamilies #-}
1+module Main where
2−
3−class Foo a where type FooBar a
4
2
5−-- | Something.
3+{-# LANGUAGE TypeFamilies #-}
6−class Bar a
7− where
8− -- | Bar bar
9− type BarBar a
10− -- | Bar baz
11− type BarBaz
12− a
13
4
14-- | Something more.
5-- | Something more.
15class Baz a where
6class Baz a where
data/examples/declaration/class/default-implementations-comments-out.hsnew file+26
@@ -0,0 +1,26 @@
1+module Main where
2+
3+-- | Baz
4+class Baz a where
5+ foobar :: a -> a
6+ foobar a =
7+ barbaz (bazbar a)
8+
9+ -- | Bar baz
10+ barbaz ::
11+ a -> a
12+
13+ -- | Baz bar
14+ bazbar ::
15+ a ->
16+ a
17+
18+ -- First comment
19+ barbaz a =
20+ bazbar -- Middle comment
21+ a
22+
23+ -- Last comment
24+ bazbar a =
25+ barbaz
26+ a
data/examples/declaration/class/default-implementations-comments.hsnew file+22
@@ -0,0 +1,22 @@
1+module Main where
2+
3+-- | Baz
4+class Baz a where
5+ foobar :: a -> a
6+ foobar a =
7+ barbaz (bazbar a)
8+ -- | Bar baz
9+ barbaz ::
10+ a -> a
11+ -- | Baz bar
12+ bazbar ::
13+ a ->
14+ a
15+ -- First comment
16+ barbaz a
17+ = bazbar -- Middle comment
18+ a
19+ -- Last comment
20+ bazbar a
21+ = barbaz
22+ a
data/examples/declaration/class/default-implementations-out.hs+5−31
@@ -1,39 +1,13 @@
1+module Main where
2+
1-- | Foo
3-- | Foo
2class Foo a where
4class Foo a where
3−
4 foo :: a -> a
5 foo :: a -> a
5 foo a = a
6 foo a = a
6
7
7-- | Bar
8-- | Bar
8class Bar a where
9class Bar a where
9−
10− bar
10+ bar ::
11− :: a
11+ a ->
12− -> Int
12+ Int
13 bar = const 0
13 bar = const 0
14−
15−-- | Baz
16−class Baz a where
17−
18− foobar :: a -> a
19− foobar a =
20− barbaz (bazbar a)
21−
22− -- | Bar baz
23− barbaz
24− :: a -> a
25−
26− -- | Baz bar
27− bazbar
28− :: a
29− -> a
30−
31− -- First comment
32− barbaz a =
33− bazbar -- Middle comment
34− a
35−
36− -- Last comment
37− bazbar a =
38− barbaz
39− a
data/examples/declaration/class/default-implementations.hs+2−21
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Foo
3-- | Foo
2class Foo a where
4class Foo a where
3 foo :: a -> a
5 foo :: a -> a
@@ -9,24 +11,3 @@ class Bar a where
9 a
11 a
10 -> Int
12 -> Int
11 bar = const 0
13 bar = const 0
12−
13−-- | Baz
14−class Baz a where
15− foobar :: a -> a
16− foobar a =
17− barbaz (bazbar a)
18− -- | Bar baz
19− barbaz ::
20− a -> a
21− -- | Baz bar
22− bazbar ::
23− a ->
24− a
25− -- First comment
26− barbaz a
27− = bazbar -- Middle comment
28− a
29− -- Last comment
30− bazbar a
31− = barbaz
32− a
data/examples/declaration/class/default-signatures-out.hs+12−21
@@ -1,31 +1,22 @@
1{-# LANGUAGE DefaultSignatures #-}
1{-# LANGUAGE DefaultSignatures #-}
2
2
3−-- | Something.
3+module Main where
4−class Foo a where
5−
6− -- | Foo
7− foo :: a -> String
8−
9− default foo :: Show a => a -> String
10− foo = show
11
4
12-- | Something else.
5-- | Something else.
13class Bar a where
6class Bar a where
14−
15 -- | Bar
7 -- | Bar
16− bar
8+ bar ::
17− :: String
9+ String ->
18− -> String
10+ String ->
19− -> a
11+ a
20−
21 -- Pointless comment
12 -- Pointless comment
22− default bar
13+ default bar ::
23− :: ( Read a
14+ ( Read a,
24− , Semigroup a
15+ Semigroup a
25− )
26− => a
16+ ) =>
27− -> a
17+ a ->
18+ a ->
28− -> a
19+ a
29 -- Even more pointless comment
20 -- Even more pointless comment
30 bar
21 bar
31 a
22 a
data/examples/declaration/class/default-signatures-simple-out.hsnew file+8
@@ -0,0 +1,8 @@
1+module Main where
2+
3+-- | Something.
4+class Foo a where
5+ -- | Foo
6+ foo :: a -> String
7+ default foo :: Show a => a -> String
8+ foo = show
data/examples/declaration/class/default-signatures-simple.hsnew file+8
@@ -0,0 +1,8 @@
1+module Main where
2+
3+-- | Something.
4+class Foo a where
5+ -- | Foo
6+ foo :: a -> String
7+ default foo :: Show a => a -> String
8+ foo = show
data/examples/declaration/class/default-signatures.hs+2−7
@@ -1,11 +1,6 @@
1−{-# LANGUAGE DefaultSignatures #-}
1+module Main where
2
2
3−-- | Something.
3+{-# LANGUAGE DefaultSignatures #-}
4−class Foo a where
5− -- | Foo
6− foo :: a -> String
7− default foo :: Show a => a -> String
8− foo = show
9
4
10-- | Something else.
5-- | Something else.
11class Bar a
6class Bar a
data/examples/declaration/class/dependency-super-classes-out.hs+13−13
@@ -1,25 +1,25 @@
1{-# LANGUAGE FunctionalDependencies #-}
1{-# LANGUAGE FunctionalDependencies #-}
2
2
3+module Main where
4+
3-- | Something.
5-- | Something.
4class (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
5−
6 get :: m s
7 get :: m s
7−
8 put :: s -> m ()
8 put :: s -> m ()
9
9
10-- | 'MonadParsec'
10-- | 'MonadParsec'
11class
11class
12− ( Stream s -- Token streams
12+ ( Stream s, -- Token streams
13− , MonadPlus m -- Potential for failure
13+ MonadPlus m -- Potential for failure
14− )
14+ ) =>
15− => MonadParsec e s m
15+ MonadParsec e s m
16+ | m -> e s
16− | m -> e s where
17+ where
17−
18 -- | 'getState' returns state
18 -- | 'getState' returns state
19− getState
19+ getState ::
20− :: m s
20+ m s
21
21
22 -- | 'putState' sets state
22 -- | 'putState' sets state
23− putState
23+ putState ::
24− :: s
24+ s ->
25− -> m ()
25+ m ()
data/examples/declaration/class/dependency-super-classes.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1{-# LANGUAGE FunctionalDependencies #-}
3{-# LANGUAGE FunctionalDependencies #-}
2
4
3-- | Something.
5-- | Something.
data/examples/declaration/class/empty-classes-out.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Foo!
3-- | Foo!
2class Foo a
4class Foo a
3
5
data/examples/declaration/class/empty-classes.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Foo!
3-- | Foo!
2class Foo a where
4class Foo a where
3-- | Bar!
5-- | Bar!
data/examples/declaration/class/functional-dependencies-out.hs+9−9
@@ -1,19 +1,19 @@
1{-# LANGUAGE FunctionalDependencies #-}
1{-# LANGUAGE FunctionalDependencies #-}
2
2
3+module Main where
4+
3-- | Something.
5-- | Something.
4class Foo a b | a -> b
6class Foo a b | a -> b
5
7
6−class Bar a b | a -> b, b -> a where
8+class Bar a b | a -> b, b -> a where bar :: a
7−
8− bar :: a
9
9
10-- | Something else.
10-- | Something else.
11class
11class
12 Baz a b c d
12 Baz a b c d
13− | a b -> c d -- Foo
13+ | a b -> c d, -- Foo
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 where
17+ a b d -> a b c d
18−
18+ where
19 baz :: a -> b
19 baz :: a -> b
data/examples/declaration/class/functional-dependencies.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1{-# LANGUAGE FunctionalDependencies #-}
3{-# LANGUAGE FunctionalDependencies #-}
2
4
3-- | Something.
5-- | Something.
data/examples/declaration/class/multi-parameters-out.hsdeleted−36
@@ -1,36 +0,0 @@
1−{-# LANGUAGE MultiParamTypeClasses #-}
2−
3−class Foo a b where
4−
5− foo :: a -> b
6−
7−-- | Something.
8−class Bar a b c d where
9−
10− bar
11− :: a
12− -> b
13− -> c
14− -> d
15−
16−class -- Before name
17− Baz where
18−
19− baz :: Int
20−
21−-- | Something else.
22−class
23− BarBaz
24− a -- Foo
25− b -- Bar
26− c -- Baz bar
27− d -- Baz baz
28− e -- Rest
29− f where
30−
31− barbaz
32− :: a -> f
33−
34− bazbar
35− :: e
36− -> f
data/examples/declaration/class/multi-parameters1-out.hsnew file+15
@@ -0,0 +1,15 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+
3+class Foo a b where foo :: a -> b
4+
5+-- | Something.
6+class Bar a b c d where
7+ bar ::
8+ a ->
9+ b ->
10+ c ->
11+ d
12+
13+class -- Before name
14+ Baz where
15+ baz :: Int
data/examples/declaration/class/multi-parameters1.hsnew file+18
@@ -0,0 +1,18 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+
3+class Foo a b where foo :: a -> b
4+
5+-- | Something.
6+class Bar a b c d
7+ where
8+ bar ::
9+ a
10+ -> b
11+ -> c
12+ -> d
13+
14+class -- Before name
15+ Baz
16+ where
17+ baz :: Int
18+
data/examples/declaration/class/multi-parameters2-out.hsnew file+19
@@ -0,0 +1,19 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+
3+module Main where
4+
5+-- | Something else.
6+class
7+ BarBaz
8+ a -- Foo
9+ b -- Bar
10+ c -- Baz bar
11+ d -- Baz baz
12+ e -- Rest
13+ f
14+ where
15+ barbaz ::
16+ a -> f
17+ bazbar ::
18+ e ->
19+ f
data/examples/declaration/class/multi-parameters.hs → data/examples/declaration/class/multi-parameters2.hsrenamed+2−16
@@ -1,20 +1,6 @@
1−{-# LANGUAGE MultiParamTypeClasses #-}
1+module Main where
2−
3−class Foo a b where foo :: a -> b
4
2
5−-- | Something.
3+{-# LANGUAGE MultiParamTypeClasses #-}
6−class Bar a b c d
7− where
8− bar ::
9− a
10− -> b
11− -> c
12− -> d
13−
14−class -- Before name
15− Baz
16− where
17− baz :: Int
18
4
19-- | Something else.
5-- | Something else.
20class
6class
data/examples/declaration/class/newlines-after-where-out.hsnew file+5
@@ -0,0 +1,5 @@
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.hsnew file+7
@@ -0,0 +1,7 @@
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.hsnew file+11
@@ -0,0 +1,11 @@
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.hsnew file+13
@@ -0,0 +1,13 @@
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.hsnew file+23
@@ -0,0 +1,23 @@
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.hsnew file+19
@@ -0,0 +1,19 @@
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.hsnew file+17
@@ -0,0 +1,17 @@
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.hsnew file+15
@@ -0,0 +1,15 @@
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/poly-kinded-classes-out.hs+2−2
@@ -4,6 +4,6 @@ class Foo (a :: k)
4
4
5class
5class
6 Bar
6 Bar
7− ( a -- Variable
7+ ( a :: -- Variable
8− :: * -- Star
8+ * -- Star
9 )
9 )
data/examples/declaration/class/single-parameters-out.hs+14−15
@@ -1,27 +1,26 @@
1−-- | Something.
1+module Main where
2−class Foo a where
3
2
4− foo :: a
3+-- | Something.
4+class Foo a where foo :: a
5
5
6-- | Something more.
6-- | Something more.
7class Bar a where
7class Bar a where
8−
9 -- | Bar
8 -- | Bar
10 bar :: a -> a -> a
9 bar :: a -> a -> a
11
10
12class Baz a where
11class Baz a where
13−
14 -- | Baz
12 -- | Baz
15− baz
13+ baz ::
14+ -- | First argument
16− :: ( a
15+ ( a,
17− , a -- ^ First argument
16+ a
18− )
17+ ) ->
19− -> a -- ^ Second argument
18+ -- | Second argument
19+ a ->
20− -> a -- ^ Return value
20+ -- | Return value
21+ a
21
22
22class BarBaz a where
23class BarBaz a where
23−
24− barbaz
24+ barbaz ::
25− :: a -> b
25+ a -> b
26−
27 bazbar :: b -> a
26 bazbar :: b -> a
data/examples/declaration/class/single-parameters.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2class Foo a where foo :: a
4class Foo a where foo :: a
3
5
data/examples/declaration/class/super-classes-out.hs+7−7
@@ -3,12 +3,12 @@ class Foo a
3class Foo a => Bar a
3class Foo a => Bar a
4
4
5class
5class
6− (Foo a, Bar a)
6+ (Foo a, Bar a) =>
7− => Baz a
7+ Baz a
8
8
9class
9class
10− ( Foo a -- Foo?
10+ ( Foo a, -- Foo?
11− , Bar a -- Bar?
11+ Bar a, -- Bar?
12− , Baz a -- Baz
12+ Baz a -- Baz
13− )
13+ ) =>
14− => BarBar a
14+ BarBar a
data/examples/declaration/class/type-operators-out.hsdeleted−35
@@ -1,35 +0,0 @@
1−{-# LANGUAGE MultiParamTypeClasses #-}
2−{-# LANGUAGE TypeOperators #-}
3−
4−class (:$) a b
5−
6−class
7− (:&)
8− a
9− b
10−
11−class a :* b
12−
13−class
14− a :+ -- Before operator
15− b -- After operator
16−
17−class
18− ( f :.
19− g
20− )
21− a
22−
23−class a `Pair` b
24−
25−class
26− a `Sum`
27− b
28−
29−class (f `Product` g) a
30−
31−class
32− ( f `Sum`
33− g
34− )
35− a
data/examples/declaration/class/type-operators1-out.hsnew file+21
@@ -0,0 +1,21 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+{-# LANGUAGE TypeOperators #-}
3+
4+class (:$) a b
5+
6+class
7+ (:&)
8+ a
9+ b
10+
11+class a :* b
12+
13+class
14+ a -- Before operator
15+ :+ b -- After operator
16+
17+class
18+ ( f
19+ :. g
20+ )
21+ a
data/examples/declaration/class/type-operators.hs → data/examples/declaration/class/type-operators1.hsrenamed−13
@@ -17,16 +17,3 @@ class
17class (
17class (
18 f :. g
18 f :. g
19 ) a
19 ) a
20−
21−class
22− a`Pair`b
23−
24−class
25− a
26− `Sum` b
27−
28−class (f`Product`g)a
29−
30−class (
31− f `Sum` g
32− ) a
data/examples/declaration/class/type-operators2-out.hsnew file+16
@@ -0,0 +1,16 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+{-# LANGUAGE TypeOperators #-}
3+
4+class a `Pair` b
5+
6+class
7+ a
8+ `Sum` b
9+
10+class (f `Product` g) a
11+
12+class
13+ ( f
14+ `Sum` g
15+ )
16+ a
data/examples/declaration/class/type-operators2.hsnew file+16
@@ -0,0 +1,16 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+{-# LANGUAGE TypeOperators #-}
3+
4+class
5+ a`Pair`b
6+
7+class
8+ a
9+ `Sum` b
10+
11+class (f`Product`g)a
12+
13+class (
14+ f `Sum` g
15+ ) a
16+
data/examples/declaration/class/type-operators3-out.hsnew file+10
@@ -0,0 +1,10 @@
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.hsnew file+7
@@ -0,0 +1,7 @@
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/deriving-out.hsnew file+2
@@ -0,0 +1,2 @@
1+newtype R r a = R (ReaderT r IO a)
2+ deriving (MonadReader r)
data/examples/declaration/data/deriving-strategies-out.hs+7−5
@@ -1,12 +1,14 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2newtype Foo = Foo Int
4newtype Foo = Foo Int
3 deriving stock (Eq, Show, Generic)
5 deriving stock (Eq, Show, Generic)
4 deriving anyclass
6 deriving anyclass
5− ( ToJSON
7+ ( ToJSON,
6− , FromJSON
8+ FromJSON
7 )
9 )
8− deriving newtype Num
10+ deriving newtype (Num)
9− deriving Monoid via (Sum Int)
11+ deriving (Monoid) via (Sum Int)
10 deriving
12 deriving
11− Semigroup
13+ (Semigroup)
12 via (Sum Int)
14 via (Sum Int)
data/examples/declaration/data/deriving-strategies.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2
4
3newtype Foo = Foo Int
5newtype Foo = Foo Int
data/examples/declaration/data/deriving.hsnew file+2
@@ -0,0 +1,2 @@
1+newtype R r a = R (ReaderT r IO a)
2+ deriving (MonadReader r)
data/examples/declaration/data/existential-multiline-out.hs+12
@@ -3,3 +3,15 @@
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,3 +3,10 @@
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,3 +1,5 @@
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,3 +1,5 @@
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/fat-multiline-out.hs+6−4
@@ -1,10 +1,12 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2data Foo
4data Foo
5+ = -- | Foo
3− = Foo
6+ Foo
4 Int
7 Int
5 Int
8 Int
6− -- ^ Foo
9+ | -- | Bar
7− | Bar
10+ Bar
8 Bool
11 Bool
9 Bool
12 Bool
10− -- ^ Bar
data/examples/declaration/data/fat-multiline.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2
4
3data Foo
5data Foo
data/examples/declaration/data/field-layout/gadt-out.hsnew file+11
@@ -0,0 +1,11 @@
1+module Main where
2+
3+-- | Foo.
4+data Foo a b where
5+ -- | Something
6+ Foo :: Foo Int Int
7+ -- | Something else
8+ Bar ::
9+ Foo
10+ Char
11+ Char
data/examples/declaration/data/field-layout/gadt.hsnew file+10
@@ -0,0 +1,10 @@
1+module Main where
2+
3+-- | Foo.
4+
5+data Foo a b where
6+ -- | Something
7+ Foo :: Foo Int Int
8+ -- | Something else
9+ Bar :: Foo Char
10+ Char
data/examples/declaration/data/field-layout/record-out.hsnew file+12
@@ -0,0 +1,12 @@
1+module Main where
2+
3+-- | Foo.
4+data Foo = Foo
5+ { -- | Something
6+ foo :: Foo Int Int,
7+ -- | Something else
8+ bar ::
9+ Bar
10+ Char
11+ Char
12+ }
data/examples/declaration/data/field-layout/record.hsnew file+11
@@ -0,0 +1,11 @@
1+module Main where
2+
3+-- | Foo.
4+
5+data Foo = Foo
6+ { foo :: Foo Int Int
7+ -- ^ Something
8+ , bar :: Bar Char
9+ Char
10+ -- ^ Something else
11+ }
data/examples/declaration/data/field-layout/variants-out.hsnew file+10
@@ -0,0 +1,10 @@
1+module Main where
2+
3+-- | Foo.
4+data Foo
5+ = -- | Something
6+ Foo Int Int
7+ | -- | Something else
8+ Bar
9+ Char
10+ Char
data/examples/declaration/data/field-layout/variants.hsnew file+10
@@ -0,0 +1,10 @@
1+module Main where
2+
3+-- | Foo.
4+
5+data Foo =
6+ Foo Int Int
7+ -- ^ Something
8+ | Bar Char
9+ Char
10+ -- ^ Something else
data/examples/declaration/data/gadt-syntax-out.hs+3−3
@@ -1,3 +1,3 @@
1−{-# LANUGAGE GADTSyntax #-}
1+{-# LANGUAGE GADTSyntax #-}
2−data Foo where
2+
3− MKFoo :: a -> (a -> Bool) -> Foo
3+data Foo where MKFoo :: a -> (a -> Bool) -> Foo
data/examples/declaration/data/gadt-syntax.hs+1−1
@@ -1,3 +1,3 @@
1−{-# LANUGAGE GADTSyntax #-}
1+{-# LANGUAGE GADTSyntax #-}
2
2
3data Foo where { MKFoo :: a -> (a->Bool) -> Foo }
3data Foo where { MKFoo :: a -> (a->Bool) -> Foo }
data/examples/declaration/data/gadt/multiline-out.hs+17−13
@@ -1,21 +1,25 @@
1{-# LANGUAGE ExplicitForAll #-}
1{-# LANGUAGE ExplicitForAll #-}
2
2
3+module Main where
4+
3-- | Here goes a comment.
5-- | Here goes a comment.
4data Foo a where
6data Foo a where
5 -- | 'Foo' is wonderful.
7 -- | 'Foo' is wonderful.
6− Foo
8+ Foo ::
9+ forall a b.
7− :: forall a b. (Show a, Eq b) -- foo
10+ (Show a, Eq b) => -- foo
8− -- bar
11+ -- bar
9− => a
12+ a ->
10− -> b
13+ b ->
11− -> Foo 'Int
14+ Foo 'Int
12 -- | But 'Bar' is also not too bad.
15 -- | But 'Bar' is also not too bad.
13− Bar
16+ Bar ::
14− :: Int
17+ Int ->
15− -> Maybe Text
18+ Maybe Text ->
16− -> Foo 'Bool
19+ Foo 'Bool
17 -- | So is 'Baz'.
20 -- | So is 'Baz'.
18− Baz
21+ Baz ::
19− :: forall a. a
22+ forall a.
23+ a ->
20− -> Foo 'String
24+ Foo 'String
21 (:~>) :: Foo a -> Foo a -> Foo a
25 (:~>) :: Foo a -> Foo a -> Foo a
data/examples/declaration/data/gadt/multiline-where-out.hsnew file+7
@@ -0,0 +1,7 @@
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.hsnew file+6
@@ -0,0 +1,6 @@
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/multiline.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1{-# LANGUAGE ExplicitForAll #-}
3{-# LANGUAGE ExplicitForAll #-}
2
4
3-- | Here goes a comment.
5-- | Here goes a comment.
data/examples/declaration/data/gadt/multiple-declaration-out.hsnew file+15
@@ -0,0 +1,15 @@
1+data GADT0 a where
2+ GADT01, GADT02 :: Int -> GADT0 a
3+
4+data GADT1 a where
5+ GADT11,
6+ GADT12 ::
7+ Int ->
8+ GADT1 a
9+
10+data GADT2 a where
11+ GADT21,
12+ GADT21,
13+ GADT22 ::
14+ Int ->
15+ GADT2 a
data/examples/declaration/data/gadt/multiple-declaration.hsnew file+11
@@ -0,0 +1,11 @@
1+data GADT0 a where
2+ GADT01, GADT02 :: Int -> GADT0 a
3+
4+data GADT1 a where
5+ GADT11
6+ , GADT12 :: Int -> GADT1 a
7+
8+data GADT2 a where
9+ GADT21
10+ , GADT21
11+ , GADT22 :: Int -> GADT2 a
data/examples/declaration/data/gadt/record-out.hs+11−8
@@ -1,11 +1,14 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2data Foo where
4data Foo where
3 Foo :: {fooX :: Int} -> Foo
5 Foo :: {fooX :: Int} -> Foo
4− Bar
6+ Bar ::
5− :: { fooY :: Int
7+ { fooY :: Int,
6− , fooBar, fooBaz :: Bool
8+ fooBar, fooBaz :: Bool,
7− , fooFoo
9+ fooFoo,
8− , barBar
10+ barBar,
11+ bazBaz ::
9− :: Int
12+ Int
10− }
13+ } ->
11− -> Foo
14+ Foo
data/examples/declaration/data/gadt/record.hs+4−1
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2
4
3data Foo where
5data Foo where
@@ -5,5 +7,6 @@ data Foo where
5 Bar :: { fooY :: Int
7 Bar :: { fooY :: Int
6 , fooBar, fooBaz :: Bool
8 , fooBar, fooBaz :: Bool
7 , fooFoo
9 , fooFoo
8− , barBar :: Int
10+ , barBar
11+ , bazBaz :: Int
9 } -> Foo
12 } -> Foo
data/examples/declaration/data/gadt/simple-out.hs+12−2
@@ -1,8 +1,18 @@
1{-# LANGUAGE ExplicitForAll #-}
1{-# LANGUAGE ExplicitForAll #-}
2
2
3+module Main where
4+
3-- | Here goes a comment.
5-- | Here goes a comment.
4data Foo a where
6data Foo a where
5 -- | 'Foo' is wonderful.
7 -- | 'Foo' is wonderful.
6 Foo :: forall a b. (Show a, Eq b) => a -> b -> Foo 'Int
8 Foo :: forall a b. (Show a, Eq b) => a -> b -> Foo 'Int
9+ Bar ::
10+ Int ->
11+ Text ->
7− Bar :: Int -> Text -> Foo 'Bool -- ^ But 'Bar' is also not too bad.
12+ -- | But 'Bar' is also not too bad.
13+ Foo 'Bool
14+ Baz ::
15+ forall a.
16+ a ->
17+ -- | So is 'Baz'.
8− Baz :: forall a. a -> Foo 'String -- ^ So is 'Baz'.
18+ Foo 'String
data/examples/declaration/data/gadt/simple.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1{-# LANGUAGE ExplicitForAll #-}
3{-# LANGUAGE ExplicitForAll #-}
2
4
3-- | Here goes a comment.
5-- | Here goes a comment.
data/examples/declaration/data/gadt/strictness-out.hs+2−1
@@ -1,2 +1,3 @@
1data Foo a where
1data Foo a where
2− Foo :: !Int -> {-# UNPACK #-} !Bool -> Foo Int
2+ Foo1 :: !Int -> {-# UNPACK #-} !Bool -> Foo Int
3+ Foo2 :: {-# UNPACK #-} Maybe Int && Bool -> Foo Int
data/examples/declaration/data/gadt/strictness.hs+2−1
@@ -1,2 +1,3 @@
1data Foo a where
1data Foo a where
2− Foo :: !Int -> {-# UNPACK #-} !Bool -> Foo Int
2+ Foo1 :: !Int -> {-# UNPACK #-} !Bool -> Foo Int
3+ Foo2 :: {-# UNPACK #-} Maybe Int && Bool -> Foo Int
data/examples/declaration/data/kind-annotations-out.hs+10
@@ -1 +1,11 @@
1data Something (n :: Nat) = Something
1data Something (n :: Nat) = Something
2+
3+data 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+9
@@ -1 +1,10 @@
1data Something (n :: Nat) = Something
1data Something (n :: Nat) = Something
2+
3+data 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+4−2
@@ -1,8 +1,10 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2data Foo
4data Foo
3 = Foo
5 = Foo
4 Bar
6 Bar
5 (Set Baz) -- and here we go
7 (Set Baz) -- and here we go
6− -- and that's it
8+ -- and that's it
7 Text
9 Text
8− deriving Eq
10+ deriving (Eq)
data/examples/declaration/data/multiline-arg-parens.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2
4
3data Foo
5data Foo
data/examples/declaration/data/multiline-names-out.hsnew file+29
@@ -0,0 +1,29 @@
1+data
2+ Foo
3+ a
4+ b
5+ = Foo a b
6+
7+data a :-> b = Arrow (a -> b)
8+
9+data (f :* g) a = f a :* g a
10+
11+data
12+ ( f
13+ :+ g
14+ )
15+ a
16+ = L (f a)
17+ | R (g a)
18+
19+data a `Arrow` b = Arrow' (a -> b)
20+
21+data (f `Product` g) a = f a `Product` g a
22+
23+data
24+ ( f
25+ `Sum` g
26+ )
27+ a
28+ = L' (f a)
29+ | R' (g a)
data/examples/declaration/data/multiline-names.hsnew file+23
@@ -0,0 +1,23 @@
1+data Foo a
2+ b
3+ = Foo a b
4+
5+data a :-> b = Arrow (a -> b)
6+
7+data (f :* g) a = f a :* g a
8+
9+data (f
10+ :+
11+ g)
12+ a = L (f a)
13+ | R (g a)
14+
15+data a `Arrow` b = Arrow' (a -> b)
16+
17+data (f `Product` g) a = f a `Product` g a
18+
19+data (f
20+ `Sum`
21+ g)
22+ a = L' (f a)
23+ | R' (g a)
data/examples/declaration/data/multiline-out.hs+8−3
@@ -1,7 +1,12 @@
1+module Main where
2+
1-- | Here we have 'Foo'.
3-- | Here we have 'Foo'.
2data Foo
4data Foo
5+ = -- | One
3− = Foo -- ^ One
6+ Foo
7+ | -- | Two
4− | Bar Int -- ^ Two
8+ Bar Int
5− | Baz -- ^ Three
9+ | -- | Three
10+ Baz
6 deriving
11 deriving
7 (Eq, Show)
12 (Eq, Show)
data/examples/declaration/data/multiline.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Here we have 'Foo'.
3-- | Here we have 'Foo'.
2
4
3data Foo
5data Foo
data/examples/declaration/data/newtype-out.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2newtype Foo = Foo Int
4newtype Foo = Foo Int
3 deriving (Eq, Show)
5 deriving (Eq, Show)
data/examples/declaration/data/newtype.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2
4
3newtype Foo = Foo Int
5newtype Foo = Foo Int
data/examples/declaration/data/operators-out.hsnew file+12
@@ -0,0 +1,12 @@
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.hsnew file+12
@@ -0,0 +1,12 @@
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.hsnew file+5
@@ -0,0 +1,5 @@
1+data Optimisation
2+ = PETransform
3+ | -- | partial eval and associated transforms
4+ GeneralisedNatHack
5+ deriving (Show, Eq, Generic)
data/examples/declaration/data/partly-documented.hsnew file+2
@@ -0,0 +1,2 @@
1+data Optimisation = PETransform | GeneralisedNatHack -- ^ partial eval and associated transforms
2+ deriving (Show, Eq, Generic)
data/examples/declaration/data/record-multi-const-out.hsnew file+17
@@ -0,0 +1,17 @@
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.hsnew file+13
@@ -0,0 +1,13 @@
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+21−16
@@ -1,18 +1,23 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2−data Foo
4+data Foo = Foo
3− = Foo
5+ { -- | X
4− { fooX :: Int -- ^ X
6+ fooX :: Int,
7+ -- | Y
5− , fooY :: Int -- ^ Y
8+ fooY :: Int,
9+ -- | BarBaz
6− , fooBar, fooBaz :: NonEmpty (Identity Bool) -- ^ BarBaz
10+ fooBar, fooBaz :: NonEmpty (Identity Bool),
11+ -- | GagGog
7− , fooGag
12+ fooGag,
8− , fooGog
13+ fooGog ::
9− :: NonEmpty
14+ NonEmpty
10− ( Indentity
15+ ( Indentity
11− Bool
16+ Bool
12− )
17+ ),
13− -- ^ GagGog
14− , fooFoo
15− , barBar
16− :: Int -- ^ Huh!
18+ -- | Huh!
19+ fooFoo,
20+ barBar ::
21+ Int
17− }
22+ }
18 deriving (Eq, Show)
23 deriving (Eq, Show)
data/examples/declaration/data/record-singleline-out.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2data Foo = Foo {fooX :: Int, fooY :: Int}
4data Foo = Foo {fooX :: Int, fooY :: Int}
3 deriving (Eq, Show)
5 deriving (Eq, Show)
data/examples/declaration/data/record-singleline.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2
4
3data Foo = Foo { fooX :: Int , fooY :: Int }
5data Foo = Foo { fooX :: Int , fooY :: Int }
data/examples/declaration/data/record.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2
4
3data Foo = Foo
5data Foo = Foo
data/examples/declaration/data/simple-broken-out.hs+5−4
@@ -1,8 +1,9 @@
1+module Main where
2+
1-- | Here we go.
3-- | Here we go.
2−data Foo
3− = Foo {unFoo :: Int}
4+data Foo = Foo {unFoo :: Int}
4− deriving Eq
5+ deriving (Eq)
5
6
6-- | And once again.
7-- | And once again.
7data Bar = Bar {unBar :: Int}
8data Bar = Bar {unBar :: Int}
8− deriving Eq
9+ deriving (Eq)
data/examples/declaration/data/simple-broken.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Here we go.
3-- | Here we go.
2
4
3data Foo
5data Foo
data/examples/declaration/data/simple-out.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | And here we have 'Foo'.
3-- | And here we have 'Foo'.
2data Foo = Foo | Bar Int | Baz
4data Foo = Foo | Bar Int | Baz
3 deriving (Eq, Show)
5 deriving (Eq, Show)
data/examples/declaration/data/simple.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | And here we have 'Foo'.
3-- | And here we have 'Foo'.
2
4
3data Foo = Foo | Bar Int | Baz
5data Foo = Foo | Bar Int | Baz
data/examples/declaration/data/strictness-out.hs+5−1
@@ -1,2 +1,6 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
4+data Foo
2−data Foo = Foo !Int {-# UNPACK #-} !Bool {-# NOUNPACK #-} !String
5+ = Foo1 !Int {-# UNPACK #-} !Bool {-# NOUNPACK #-} !String
6+ | Foo2 {a :: {-# UNPACK #-} Maybe Int && Bool}
data/examples/declaration/data/strictness.hs+5−1
@@ -1,3 +1,7 @@
1+module Main where
2+
1-- | Something.
3-- | Something.
2
4
5+data Foo
3−data Foo = Foo !Int {-# UNPACK #-} !Bool {-# NOUNPACK #-} !String
6+ = Foo1 !Int {-# UNPACK #-} !Bool {-# NOUNPACK #-} !String
7+ | Foo2 { a :: {-# UNPACK #-} Maybe Int && Bool }
data/examples/declaration/data/unnamed-field-comment-0-out.hsnew file+7
@@ -0,0 +1,7 @@
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.hsnew file+5
@@ -0,0 +1,5 @@
1+data Foo
2+ = -- | Bar
3+ Bar
4+ Field1 -- ^ Field 1
5+ Field2 -- ^ Field 2
data/examples/declaration/data/unnamed-field-comment-1-out.hsnew file+5
@@ -0,0 +1,5 @@
1+data X
2+ = B
3+ !Int
4+ -- ^ y
5+ C
data/examples/declaration/data/unnamed-field-comment-1.hsnew file+4
@@ -0,0 +1,4 @@
1+data X
2+ = B
3+ !Int -- ^ y
4+ C
data/examples/declaration/data/with-comment-out.hsnew file+4
@@ -0,0 +1,4 @@
1+data A
2+ = B -- C
3+ | -- D
4+ E
data/examples/declaration/data/with-comment.hsnew file+5
@@ -0,0 +1,5 @@
1+data A =
2+ B -- C
3+
4+ -- D
5+ | E
data/examples/declaration/data/with-weird-haddock-out.hsnew file+4
@@ -0,0 +1,4 @@
1+data PlusLevel' t
2+ = -- | @n + ℓ@.
3+ Plus Integer (LevelAtom' t)
4+ deriving (Show, Data)
data/examples/declaration/data/with-weird-haddock.hsnew file+2
@@ -0,0 +1,2 @@
1+data PlusLevel' t = Plus Integer (LevelAtom' t) -- ^ @n + ℓ@.
2+ deriving (Show, Data)
data/examples/declaration/default/default-out.hs+3−3
@@ -1,7 +1,7 @@
1default (Int, Foo, Bar)
1default (Int, Foo, Bar)
2
2
3default
3default
4− ( Int
4+ ( Int,
5− , Foo
5+ Foo,
6− , Bar
6+ Bar
7 )
7 )
data/examples/declaration/deriving/multiline-out.hs−20
@@ -14,26 +14,6 @@ deriving newtype instance
14 Data
14 Data
15 Foo
15 Foo
16
16
17−deriving instance
18− {-# OVERLAPPABLE #-}
19− Ord
20− Foo
21−
22−deriving instance
23− {-# OVERLAPPING #-}
24− Num
25− Foo
26−
27−deriving instance
28− {-# OVERLAPS #-}
29− Read
30− Foo
31−
32−deriving instance
33− {-# INCOHERENT #-}
34− Show
35− Foo
36−
37deriving via
17deriving via
38 Foo
18 Foo
39 Int
19 Int
data/examples/declaration/deriving/multiline.hs−17
@@ -11,23 +11,6 @@ deriving newtype instance
11 Data
11 Data
12 Foo
12 Foo
13
13
14−deriving instance
15− {-# OVERLAPPABLE #-}
16− Ord
17− Foo
18−deriving instance
19− {-# OVERLAPPING #-}
20− Num
21− Foo
22−deriving instance
23− {-# OVERLAPS #-}
24− Read
25− Foo
26−deriving instance
27− {-# INCOHERENT #-}
28− Show
29− Foo
30−
31deriving via Foo
14deriving via Foo
32 Int
15 Int
33 instance Triple
16 instance Triple
data/examples/declaration/deriving/overlapping-out.hsnew file+19
@@ -0,0 +1,19 @@
1+deriving instance
2+ {-# OVERLAPPABLE #-}
3+ Ord
4+ Foo
5+
6+deriving instance
7+ {-# OVERLAPPING #-}
8+ Num
9+ Foo
10+
11+deriving instance
12+ {-# OVERLAPS #-}
13+ Read
14+ Foo
15+
16+deriving instance
17+ {-# INCOHERENT #-}
18+ Show
19+ Foo
data/examples/declaration/deriving/overlapping.hsnew file+17
@@ -0,0 +1,17 @@
1+deriving instance
2+ {-# OVERLAPPABLE #-}
3+ Ord
4+ Foo
5+deriving instance
6+ {-# OVERLAPPING #-}
7+ Num
8+ Foo
9+deriving instance
10+ {-# OVERLAPS #-}
11+ Read
12+ Foo
13+deriving instance
14+ {-# INCOHERENT #-}
15+ Show
16+ Foo
17+
data/examples/declaration/foreign/foreign-export-out.hs+2−1
@@ -2,7 +2,8 @@ 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 ::
5− foreignTomFun :: StablePtr Storage -> TomForegin {- Storage is bad -}
6+ StablePtr Storage {- Storage is bad -} -> TomForegin
6
7
7foreign export {- We can't use capi here -} ccall "dynamic"
8foreign export {- We can't use capi here -} ccall "dynamic"
8 export_nullaryMeth :: (IO HRESULT) -> IO (Ptr ())
9 export_nullaryMeth :: (IO HRESULT) -> IO (Ptr ())
data/examples/declaration/foreign/foreign-import-out.hs+10−10
@@ -10,16 +10,16 @@ foreign import stdcall unsafe "boo"
10 boo :: Int -> Text -> IO Array
10 boo :: Int -> Text -> IO Array
11
11
12foreign import javascript
12foreign import javascript
13− baz
13+ baz ::
14− :: String
14+ String ->
15− -> Int
15+ Int ->
16− -> IO Foo
16+ IO Foo
17
17
18foreign import {- We use capi here -} capi "pi.h value pi" c_pi :: CDouble
18foreign import {- We use capi here -} capi "pi.h value pi" c_pi :: CDouble
19
19
20−foreign import stdcall "dynamic" {- This is a bad place for a comment -}
20+foreign import stdcall {- This is a bad place for a comment -} "dynamic"
21− dyn_gluBeginSurface
21+ dyn_gluBeginSurface ::
22− :: FunPtr (Ptr GLUnurbs -> IO ())
23− -- ^ This 'FunPtr' is extremely dangerous, beware
22+ -- | This 'FunPtr' is extremely dangerous, beware
23+ FunPtr (Ptr GLUnurbs -> IO ()) ->
24− -> Ptr GLUnurbs
24+ Ptr GLUnurbs ->
25− -> IO ()
25+ IO ()
data/examples/declaration/instance/associated-data-out.hs+4−7
@@ -1,20 +1,17 @@
1{-# LANGUAGE TypeFamilies #-}
1{-# LANGUAGE TypeFamilies #-}
2
2
3−instance Foo Int where
4−
5− data Bar Int = IntBar Int Int
3+instance Foo Int where data Bar Int = IntBar Int Int
6
4
7instance Foo Double where
5instance Foo Double where
8−
9− newtype Bar Double
6+ newtype
7+ Bar
8+ Double
10 = DoubleBar
9 = DoubleBar
11 Double
10 Double
12 Double
11 Double
13
12
14instance Foo [a] where
13instance Foo [a] where
15−
16 data Bar [a]
14 data Bar [a]
17 = ListBar [Bar a]
15 = ListBar [Bar a]
18−
19 data Baz [a]
16 data Baz [a]
20 = ListBaz
17 = ListBaz
data/examples/declaration/instance/associated-data.hs+1
@@ -13,6 +13,7 @@ instance Foo Double where
13
13
14instance Foo [a]
14instance Foo [a]
15 where
15 where
16+
16 data Bar [a] =
17 data Bar [a] =
17 ListBar [Bar a]
18 ListBar [Bar a]
18 data Baz [a] =
19 data Baz [a] =
data/examples/declaration/instance/associated-types-out.hs+1−4
@@ -1,11 +1,8 @@
1{-# LANGUAGE TypeFamilies #-}
1{-# LANGUAGE TypeFamilies #-}
2
2
3−instance Foo Int where
3+instance Foo Int where type Bar Int = Double
4−
5− type Bar Int = Double
6
4
7instance Foo Double where
5instance Foo Double where
8−
9 type
6 type
10 Bar
7 Bar
11 Double =
8 Double =
data/examples/declaration/instance/associated-types.hs+2
@@ -9,5 +9,7 @@ instance Foo Double
9 Double
9 Double
10 =
10 =
11 [Double]
11 [Double]
12+
13+
12 type instance Baz Double
14 type instance Baz Double
13 = [Double]
15 = [Double]
data/examples/declaration/instance/contexts-comments-out.hsnew file+17
@@ -0,0 +1,17 @@
1+instance
2+ ( Read a, -- Foo
3+ Read b,
4+ Read
5+ ( c, -- Bar
6+ d
7+ )
8+ ) =>
9+ Read
10+ ( a, -- Baz
11+ b,
12+ ( c, -- Quux
13+ d
14+ )
15+ )
16+ where
17+ readsPrec = undefined
data/examples/declaration/instance/contexts-comments.hsnew file+18
@@ -0,0 +1,18 @@
1+instance (
2+ Read a, -- Foo
3+ Read b
4+ , Read (
5+ c, -- Bar
6+ d
7+ )
8+ )
9+ =>
10+ Read (
11+ a, -- Baz
12+ b
13+ ,(
14+ c, -- Quux
15+ d
16+ )
17+ ) where
18+ readsPrec = undefined
data/examples/declaration/instance/contexts-out.hs+12−34
@@ -1,40 +1,18 @@
1−instance Eq a => Eq [a] where
1+instance Eq a => Eq [a] where (==) _ _ = False
2−
3− (==) _ _ = False
4
2
5instance
3instance
6− ( Ord a
4+ ( Ord a,
7− , Ord b
5+ Ord b
8− )
6+ ) =>
9− => Ord (a, b) where
7+ Ord (a, b)
10−
8+ where
11 compare _ _ = GT
9 compare _ _ = GT
12
10
13instance
11instance
14− (Show a, Show b)
12+ (Show a, Show b) =>
15− => Show
13+ Show
16− ( a
14+ ( a,
17− , b
15+ b
16+ )
18− ) where
17+ where
19−
20 showsPrec _ _ = showString ""
18 showsPrec _ _ = showString ""
21−
22−instance
23− ( Read a -- Foo
24− , Read b
25− , Read
26− ( c
27− , -- Bar
28− d
29− )
30− )
31− => Read
32− ( a
33− , -- Baz
34− b
35− , ( c -- Quux
36− , d
37− )
38− ) where
39−
40− readsPrec = undefined
data/examples/declaration/instance/contexts.hs−19
@@ -12,22 +12,3 @@ instance (Show a, Show b) =>
12 b
12 b
13 ) where
13 ) where
14 showsPrec _ _ = showString ""
14 showsPrec _ _ = showString ""
15−
16−instance (
17− Read a, -- Foo
18− Read b
19− , Read (
20− c, -- Bar
21− d
22− )
23− )
24− =>
25− Read (
26− a, -- Baz
27− b
28− ,(
29− c, -- Quux
30− d
31− )
32− ) where
33− readsPrec = undefined
data/examples/declaration/instance/data-family-instances-gadt-out.hsnew file+13
@@ -0,0 +1,13 @@
1+{-# LANGUAGE GADTSyntax #-}
2+{-# LANGUAGE TypeFamilies #-}
3+
4+data instance Bar Int a where
5+ SameBar ::
6+ Bar
7+ Int
8+ Int
9+ CloseBar :: Bar Int Double
10+ OtherBar ::
11+ Bar
12+ Int
13+ a
data/examples/declaration/instance/data-family-instances-gadt.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE GADTSyntax #-}
2+{-# LANGUAGE TypeFamilies #-}
3+data instance Bar Int a where
4+ SameBar
5+ :: Bar Int
6+ Int
7+ CloseBar :: Bar Int Double
8+ OtherBar
9+ :: Bar Int
10+ a
data/examples/declaration/instance/data-family-instances-newtype-out.hsnew file+6
@@ -0,0 +1,6 @@
1+{-# LANGUAGE GADTSyntax #-}
2+{-# LANGUAGE TypeFamilies #-}
3+
4+newtype instance Foo [Double] = DoubleListFoo
5+ { unDoubleListFoo :: Double
6+ }
data/examples/declaration/instance/data-family-instances-newtype.hsnew file+6
@@ -0,0 +1,6 @@
1+{-# LANGUAGE GADTSyntax #-}
2+{-# LANGUAGE TypeFamilies #-}
3+newtype instance Foo [Double] = DoubleListFoo {
4+ unDoubleListFoo :: Double
5+}
6+
data/examples/declaration/instance/data-family-instances-out.hs+7−19
@@ -3,30 +3,18 @@
3
3
4data instance Foo Int = FooInt Int
4data instance Foo Int = FooInt Int
5
5
6−data instance Foo [Int]
6+data instance
7+ Foo
8+ [Int]
7 = IntListFoo
9 = IntListFoo
8− ( Int
10+ ( Int,
9− , Int
11+ Int
10 )
12 )
11− ( Double
13+ ( Double,
12− , Double
14+ Double
13 )
15 )
14
16
15−newtype instance Foo [Double]
16− = DoubleListFoo
17− { unDoubleListFoo :: Double
18− }
19−
20data instance Bar Double a
17data instance Bar Double a
21 = DoubleBar
18 = DoubleBar
22 Double
19 Double
23 (Bar a)
20 (Bar a)
24−
25−data instance Bar Int a where
26− SameBar
27− :: Bar Int
28− Int
29− CloseBar :: Bar Int Double
30− OtherBar
31− :: Bar Int
32− a
data/examples/declaration/instance/data-family-instances.hs−12
@@ -13,20 +13,8 @@ data instance
13 Double
13 Double
14 )
14 )
15
15
16−newtype instance Foo [Double] = DoubleListFoo {
17− unDoubleListFoo :: Double
18−}
19−
20data instance Bar Double a =
16data instance Bar Double a =
21 DoubleBar
17 DoubleBar
22 Double
18 Double
23 (Bar a)
19 (Bar a)
24
20
25−data instance Bar Int a where
26− SameBar
27− :: Bar Int
28− Int
29− CloseBar :: Bar Int Double
30− OtherBar
31− :: Bar Int
32− a
data/examples/declaration/instance/instance-sigs-multiple-out.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE InstanceSigs #-}
2+
3+instance Applicative [] where
4+ pure ::
5+ a ->
6+ [a]
7+ pure a = [a]
8+ (<*>) ::
9+ [a] -> [a] -> [a]
10+ (<*>) _ _ = []
data/examples/declaration/instance/instance-sigs-multiple.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE InstanceSigs #-}
2+
3+instance Applicative [] where
4+ pure ::
5+ a
6+ -> [a]
7+ pure a = [a]
8+ (<*>)
9+ :: [ a ] -> [ a ] -> [ a ]
10+ (<*>) _ _ = []
data/examples/declaration/instance/instance-sigs-out.hs+4−17
@@ -1,28 +1,15 @@
1{-# LANGUAGE InstanceSigs #-}
1{-# LANGUAGE InstanceSigs #-}
2
2
3instance Eq Int where
3instance Eq Int where
4−
5 (==) :: Int -> Int -> Bool
4 (==) :: Int -> Int -> Bool
6 (==) _ _ = False
5 (==) _ _ = False
7
6
8instance Ord Int where
7instance Ord Int where
9−
10− compare
8+ compare ::
11− :: Int
9+ Int ->
12− -> Int
10+ Int ->
13− -> Ordering
11+ Ordering
14 compare
12 compare
15 _
13 _
16 _ =
14 _ =
17 GT
15 GT
18−
19−instance Applicative [] where
20−
21− pure
22− :: a
23− -> [a]
24− pure a = [a]
25−
26− (<*>)
27− :: [a] -> [a] -> [a]
28− (<*>) _ _ = []
data/examples/declaration/instance/instance-sigs.hs−9
@@ -14,12 +14,3 @@ instance Ord Int where
14 _
14 _
15 _
15 _
16 = GT
16 = GT
17−
18−instance Applicative [] where
19− pure ::
20− a
21− -> [a]
22− pure a = [a]
23− (<*>)
24− :: [ a ] -> [ a ] -> [ a ]
25− (<*>) _ _ = []
data/examples/declaration/instance/multi-parameter-out.hs+1−5
@@ -1,9 +1,5 @@
1−instance MonadReader a ((->) a) where
1+instance MonadReader a ((->) a) where ask = id
2−
3− ask = id
4
2
5instance MonadState s (State s) where
3instance MonadState s (State s) where
6−
7 get = State.get
4 get = State.get
8−
9 put = State.put
5 put = State.put
data/examples/declaration/instance/newlines-after-where-out.hsnew file+5
@@ -0,0 +1,5 @@
1+instance Num X where
2+ (+) = undefined
3+
4+instance Num Y where
5+ (+) = undefined
data/examples/declaration/instance/newlines-after-where.hsnew file+7
@@ -0,0 +1,7 @@
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.hsnew file+18
@@ -0,0 +1,18 @@
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.hsnew file+16
@@ -0,0 +1,16 @@
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/overlappable-instances-out.hs+3−7
@@ -1,18 +1,14 @@
1−instance {-# OVERLAPPABLE #-} Eq Int where
1+instance {-# OVERLAPPABLE #-} Eq Int where (==) _ _ = False
2−
3− (==) _ _ = False
4
2
5instance {-# OVERLAPPING #-} Ord Int where
3instance {-# OVERLAPPING #-} Ord Int where
6−
7 compare _ _ = GT
4 compare _ _ = GT
8
5
9instance {-# OVERLAPS #-} Eq Double where
6instance {-# OVERLAPS #-} Eq Double where
10−
11 (==) _ _ = False
7 (==) _ _ = False
12
8
13instance
9instance
14 {-# INCOHERENT #-}
10 {-# INCOHERENT #-}
15 Ord
11 Ord
16− Double where
12+ Double
17−
13+ where
18 compare _ _ = GT
14 compare _ _ = GT
data/examples/declaration/instance/single-parameter-out.hs+3−5
@@ -1,11 +1,9 @@
1−instance Monoid Int where
1+instance Monoid Int where (<>) x y = x + y
2−
3− (<>) x y = x + y
4
2
5instance Enum Int where
3instance Enum Int where
6−
7 fromEnum x = x
4 fromEnum x = x
8−
9 toEnum =
5 toEnum =
10 \x ->
6 \x ->
11 x
7 x
8+
9+instance Foo Int where foo x = x; bar y = y
data/examples/declaration/instance/single-parameter.hs+2
@@ -6,3 +6,5 @@ instance Enum Int
6 toEnum
6 toEnum
7 = \x ->
7 = \x ->
8 x
8 x
9+
10+instance Foo Int where { foo x = x; bar y = y }
data/examples/declaration/instance/type-family-instances-out.hs+4−4
@@ -5,8 +5,8 @@ type instance Foo Int = Int
5type instance
5type instance
6 Foo
6 Foo
7 [Int] =
7 [Int] =
8− ( Int
8+ ( Int,
9− , Int
9+ Int
10 )
10 )
11
11
12type instance Bar Int [Int] Double = (Int, Double)
12type instance Bar Int [Int] Double = (Int, Double)
@@ -16,6 +16,6 @@ type instance
16 [Int]
16 [Int]
17 [Int]
17 [Int]
18 Double =
18 Double =
19− ( Int
19+ ( Int,
20− , Double
20+ Double
21 )
21 )
data/examples/declaration/rewrite-rule/basic1-out.hsnew file+19
@@ -0,0 +1,19 @@
1+{-# RULES
2+"fold/build" foldr k z (build g) = g k z
3+ #-}
4+
5+{-# RULES
6+"fusable/aux"
7+ fusable x (aux y) =
8+ faux x y
9+ #-}
10+
11+{-# RULES
12+"map/map"
13+ map
14+ f
15+ (map g xs) =
16+ map
17+ (f . g)
18+ xs
19+ #-}
data/examples/declaration/rewrite-rule/basic1.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# RULES
2+"fold/build" foldr k z (build g) = g k z
3+ #-}
4+
5+{-# RULES
6+"fusable/aux"
7+ fusable x (aux y) = faux x y
8+ #-}
9+
10+{-# RULES
11+"map/map"
12+ map f
13+ (map g xs) = map
14+ (f . g)
15+ xs
16+ #-}
17+
data/examples/declaration/rewrite-rule/basic2-out.hsnew file+16
@@ -0,0 +1,16 @@
1+{-# RULES
2+"++" xs ++ ys = augment (\c n -> foldr c n xs) ys
3+"concat" xs `concat` ys = augment (\c n -> foldr c n xs) ys
4+ #-}
5+
6+{-# RULES
7+"++" xs ++ ys = augment (\c n -> foldr c n xs) ys
8+"concat" xs `concat` ys = augment (\c n -> foldr c n xs) ys
9+"map/Double" fmap f xs = foldr (++) f xs
10+ #-}
11+
12+{-# RULES
13+"fb' >\\ (Request b' fb )" forall fb' b' fb.
14+ fb' >\\ (Request b' fb) =
15+ fb' b' >>= \b -> fb' >\\ fb b
16+ #-}
data/examples/declaration/rewrite-rule/basic2.hsnew file+16
@@ -0,0 +1,16 @@
1+{-# RULES
2+"++" xs ++ ys = augment (\c n -> foldr c n xs) ys
3+"concat" xs `concat` ys = augment (\c n -> foldr c n xs) ys
4+ #-}
5+
6+{-# RULES
7+"++" xs ++ ys = augment (\c n -> foldr c n xs) ys;
8+"concat" xs `concat` ys = augment (\c n -> foldr c n xs) ys;
9+"map/Double" fmap f xs = foldr (++) f xs
10+ #-}
11+
12+{-# RULES
13+ "fb' >\\ (Request b' fb )" forall fb' b' fb .
14+ fb' >\\ (Request b' fb ) = fb' b' >>= \b -> fb' >\\ fb b;
15+#-}
16+
data/examples/declaration/rewrite-rule/empty-out.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# RULES
2+
3+ #-}
data/examples/declaration/rewrite-rule/empty.hsnew file+2
@@ -0,0 +1,2 @@
1+{-# RULES
2+ #-}
data/examples/declaration/rewrite-rule/forall-0-out.hsnew file+9
@@ -0,0 +1,9 @@
1+{-# RULES
2+"fold/build" forall k z. foldr k z (build g) = g k z
3+ #-}
4+
5+{-# RULES
6+"fusable/aux" forall x y.
7+ fusable x (aux y) =
8+ faux x y
9+ #-}
data/examples/declaration/rewrite-rule/forall-0.hsnew file+8
@@ -0,0 +1,8 @@
1+{-# RULES
2+"fold/build" forall k z . foldr k z (build g) = g k z
3+ #-}
4+
5+{-# RULES
6+"fusable/aux" forall x y.
7+ fusable x (aux y) = faux x y
8+ #-}
data/examples/declaration/rewrite-rule/forall-1-out.hsnew file+23
@@ -0,0 +1,23 @@
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.hsnew file+17
@@ -0,0 +1,17 @@
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/phase-out.hsnew file+23
@@ -0,0 +1,23 @@
1+{-# RULES
2+"map/map" [2]
3+ map
4+ f
5+ (map g xs) =
6+ map
7+ (f . g)
8+ xs
9+ #-}
10+
11+{-# RULES
12+"map/map" [1] forall x y z.
13+ map
14+ f
15+ (map g xs) =
16+ map
17+ (f . g)
18+ xs
19+ #-}
20+
21+{-# RULES
22+"++" [~1] forall xs ys. xs ++ ys = augment (\c n -> foldr c n xs) ys
23+ #-}
data/examples/declaration/rewrite-rule/phase.hsnew file+19
@@ -0,0 +1,19 @@
1+{-# RULES
2+"map/map" [2]
3+ map f
4+ (map g xs) = map
5+ (f . g)
6+ xs
7+ #-}
8+
9+{-# RULES
10+"map/map" [1] forall x y z.
11+ map f
12+ (map g xs) = map
13+ (f . g)
14+ xs
15+ #-}
16+
17+{-# RULES
18+"++" [~1] forall xs ys. xs ++ ys = augment (\c n -> foldr c n xs) ys
19+ #-}
data/examples/declaration/rewrite-rule/prelude1-out.hsnew file+18
@@ -0,0 +1,18 @@
1+{-# RULES
2+"map/map" forall f g xs. map f (map g xs) = map (f . g) xs
3+"map/append" forall f xs ys. map f (xs ++ ys) = map f xs ++ map f ys
4+ #-}
5+
6+{-# RULES
7+"map" [~1] forall f xs. map f xs = build (\c n -> foldr (mapFB c f) n xs)
8+"mapList" [1] forall f. foldr (mapFB (:) f) [] = map f
9+"mapFB" forall c f g. mapFB (mapFB c f) g = mapFB c (f . g)
10+ #-}
11+
12+{-# RULES
13+"map/map" [~2] forall f g xs.
14+ map f (map g xs) =
15+ map (f . g) xs
16+"f" op True y = False
17+"g" op True y = False
18+ #-}
data/examples/declaration/rewrite-rule/prelude1.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# RULES
2+"map/map" forall f g xs. map f (map g xs) = map (f.g) xs
3+"map/append" forall f xs ys. map f (xs ++ ys) = map f xs ++ map f ys
4+ #-}
5+
6+{-# RULES
7+"map" [~1] forall f xs. map f xs = build (\c n -> foldr (mapFB c f) n xs)
8+"mapList" [1] forall f. foldr (mapFB (:) f) [] = map f
9+"mapFB" forall c f g. mapFB (mapFB c f) g = mapFB c (f.g)
10+ #-}
11+
12+{-# RULES
13+ "map/map" [~2] forall f g xs.
14+ map f (map g xs) = map (f.g) xs; "f" op True y = False;
15+ "g" op True y = False
16+#-}
17+
data/examples/declaration/rewrite-rule/prelude2-out.hsnew file+31
@@ -0,0 +1,31 @@
1+{-# RULES
2+"fold/build" forall k z (g :: forall b. (a -> b -> b) -> b -> b).
3+ foldr k z (build g) =
4+ g k z
5+"foldr/augment" forall k z xs (g :: forall b. (a -> b -> b) -> b -> b).
6+ foldr k z (augment g xs) =
7+ g k (foldr k z xs)
8+"foldr/id" foldr (:) [] = \x -> x
9+"foldr/app" [1] forall ys. foldr (:) ys = \xs -> xs ++ ys
10+-- Only activate this from phase 1, because that's
11+-- when we disable the rule that expands (++) into foldr
12+
13+-- The foldr/cons rule looks nice, but it can give disastrously
14+-- bloated code when commpiling
15+-- array (a,b) [(1,2), (2,2), (3,2), ...very long list... ]
16+-- i.e. when there are very very long literal lists
17+-- So I've disabled it for now. We could have special cases
18+-- for short lists, I suppose.
19+-- "foldr/cons" forall k z x xs. foldr k z (x:xs) = k x (foldr k z xs)
20+
21+"foldr/single" forall k z x. foldr k z [x] = k x z
22+"foldr/nil" forall k z. foldr k z [] = z
23+"augment/build" forall
24+ (g :: forall b. (a -> b -> b) -> b -> b)
25+ (h :: forall b. (a -> b -> b) -> b -> b).
26+ augment g (build h) =
27+ build (\c n -> g c (h c n))
28+"augment/nil" forall (g :: forall b. (a -> b -> b) -> b -> b).
29+ augment g [] =
30+ build g
31+ #-}
data/examples/declaration/rewrite-rule/prelude2.hsnew file+29
@@ -0,0 +1,29 @@
1+{-# RULES
2+"fold/build" forall k z (g::forall b. (a->b->b) -> b -> b) .
3+ foldr k z (build g) = g k z
4+
5+"foldr/augment" forall k z xs (g::forall b. (a->b->b) -> b -> b) .
6+ foldr k z (augment g xs) = g k (foldr k z xs)
7+
8+"foldr/id" foldr (:) [] = \x -> x
9+"foldr/app" [1] forall ys. foldr (:) ys = \xs -> xs ++ ys
10+ -- Only activate this from phase 1, because that's
11+ -- when we disable the rule that expands (++) into foldr
12+
13+-- The foldr/cons rule looks nice, but it can give disastrously
14+-- bloated code when commpiling
15+-- array (a,b) [(1,2), (2,2), (3,2), ...very long list... ]
16+-- i.e. when there are very very long literal lists
17+-- So I've disabled it for now. We could have special cases
18+-- for short lists, I suppose.
19+-- "foldr/cons" forall k z x xs. foldr k z (x:xs) = k x (foldr k z xs)
20+
21+"foldr/single" forall k z x. foldr k z [x] = k x z
22+"foldr/nil" forall k z. foldr k z [] = z
23+
24+"augment/build" forall (g::forall b. (a->b->b) -> b -> b)
25+ (h::forall b. (a->b->b) -> b -> b) .
26+ augment g (build h) = build (\c n -> g c (h c n))
27+"augment/nil" forall (g::forall b. (a->b->b) -> b -> b) .
28+ augment g [] = build g
29+ #-}
data/examples/declaration/rewrite-rule/prelude3-out.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE MagicHash #-}
2+
3+{-# RULES
4+"x# `eqChar#` x#" forall x#. x# `eqChar#` x# = True
5+"x# `neChar#` x#" forall x#. x# `neChar#` x# = False
6+"x# `gtChar#` x#" forall x#. x# `gtChar#` x# = False
7+"x# `geChar#` x#" forall x#. x# `geChar#` x# = True
8+"x# `leChar#` x#" forall x#. x# `leChar#` x# = True
9+"x# `ltChar#` x#" forall x#. x# `ltChar#` x# = False
10+ #-}
data/examples/declaration/rewrite-rule/prelude3.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE MagicHash #-}
2+
3+{-# RULES
4+"x# `eqChar#` x#" forall x#. x# `eqChar#` x# = True
5+"x# `neChar#` x#" forall x#. x# `neChar#` x# = False
6+"x# `gtChar#` x#" forall x#. x# `gtChar#` x# = False
7+"x# `geChar#` x#" forall x#. x# `geChar#` x# = True
8+"x# `leChar#` x#" forall x#. x# `leChar#` x# = True
9+"x# `ltChar#` x#" forall x#. x# `ltChar#` x# = False
10+ #-}
data/examples/declaration/rewrite-rule/prelude4-out.hsnew file+7
@@ -0,0 +1,7 @@
1+{-# RULES
2+"unpack" [~1] forall a. unpackCString # a = build (unpackFoldrCString # a)
3+"unpack-list" [1] forall a. unpackFoldrCString # a (:) [] = unpackCString # a
4+"unpack-append" forall a n. unpackFoldrCString # a (:) n = unpackAppendCString # a n
5+-- There's a built-in rule (in PrelRules.lhs) for
6+-- unpackFoldr "foo" c (unpackFoldr "baz" c n) = unpackFoldr "foobaz" c n
7+ #-}
data/examples/declaration/rewrite-rule/prelude4.hsnew file+9
@@ -0,0 +1,9 @@
1+{-# RULES
2+"unpack" [~1] forall a . unpackCString# a = build (unpackFoldrCString# a)
3+"unpack-list" [1] forall a . unpackFoldrCString# a (:) [] = unpackCString# a
4+"unpack-append" forall a n . unpackFoldrCString# a (:) n = unpackAppendCString# a n
5+
6+-- There's a built-in rule (in PrelRules.lhs) for
7+-- unpackFoldr "foo" c (unpackFoldr "baz" c n) = unpackFoldr "foobaz" c n
8+
9+ #-}
data/examples/declaration/rewrite-rule/type-signature-out.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# RULES
2+"fold/build" forall k z (g :: forall b. (a -> b -> b) -> b -> b). foldr k z (build g) = g k z
3+ #-}
4+
5+{-# RULES
6+"fold/build" forall
7+ k
8+ z
9+ ( g ::
10+ forall b.
11+ (a -> b -> b) ->
12+ b ->
13+ b
14+ ).
15+ foldr k z (build g) =
16+ g k z
17+ #-}
data/examples/declaration/rewrite-rule/type-signature.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# RULES
2+"fold/build" forall k z (g :: forall b. (a -> b -> b) -> b -> b). foldr k z (build g) = g k z
3+ #-}
4+
5+{-# RULES
6+"fold/build"
7+ forall k z
8+ (g :: forall b.
9+ (a -> b -> b) -> b -> b).
10+ foldr k z (build g) =
11+ g k z
12+ #-}
data/examples/declaration/role-annotation/multi-line-out.hsnew file+15
@@ -0,0 +1,15 @@
1+type role
2+ D
3+ phantom
4+ nominal
5+
6+type role
7+ E
8+ _
9+ nominal
10+
11+type role
12+ E
13+ _
14+ nominal
15+ phantom
data/examples/declaration/role-annotation/multi-line.hsnew file+15
@@ -0,0 +1,15 @@
1+type role
2+ D phantom nominal
3+
4+type
5+ role
6+ E
7+ _
8+ nominal
9+
10+type
11+ role
12+ E
13+ _
14+ nominal
15+ phantom
data/examples/declaration/role-annotation/simple-out.hs → data/examples/declaration/role-annotation/single-line-out.hsrenamed−16
@@ -8,19 +8,3 @@ type role A nominal nominal
8type role B _ phantom
8type role B _ phantom
9
9
10type role C _ _
10type role C _ _
11−
12−type role
13− D
14− phantom
15− nominal
16−
17−type role
18− E
19− _
20− nominal
21−
22−type role
23− E
24− _
25− nominal
26− phantom
data/examples/declaration/role-annotation/simple.hs → data/examples/declaration/role-annotation/single-line.hsrenamed−16
@@ -7,19 +7,3 @@ type role A nominal nominal
7
7
8type role B _ phantom
8type role B _ phantom
9type role C _ _
9type role C _ _
10−
11−type role
12− D phantom nominal
13−
14−type
15− role
16− E
17− _
18− nominal
19−
20−type
21− role
22− E
23− _
24− nominal
25− phantom
data/examples/declaration/signature/complete/complete-out.hs+4−4
@@ -3,8 +3,8 @@
3{-# COMPLETE A, B #-}
3{-# COMPLETE A, B #-}
4
4
5{-# COMPLETE
5{-# COMPLETE
6− A
6+ A,
7− , B
7+ B,
8− , C
8+ C ::
9− :: Foo
9+ Foo
10 #-}
10 #-}
data/examples/declaration/signature/inline/conlike-out.hsnew file+7
@@ -0,0 +1,7 @@
1+foo :: Int
2+foo = 5
3+{-# INLINE CONLIKE foo #-}
4+
5+bar :: Int
6+bar = 6
7+{-# INLINE CONLIKE bar #-}
data/examples/declaration/signature/inline/conlike.hsnew file+7
@@ -0,0 +1,7 @@
1+foo :: Int
2+foo = 5
3+{-# INLINE CONLIKE foo #-}
4+
5+bar :: Int
6+bar = 6
7+{-# INLINE CONLIKE bar #-}
data/examples/declaration/signature/inline/inline-out.hs+4
@@ -9,3 +9,7 @@ bar = id
9baz :: Int -> Int
9baz :: Int -> Int
10baz = id
10baz = id
11{-# INLINE [~2] baz #-}
11{-# INLINE [~2] baz #-}
12+
13+reVector :: Bundle u a -> Bundle v a
14+{-# INLINE reVector #-}
15+reVector = M.reVector
data/examples/declaration/signature/inline/inline.hs+5
@@ -11,3 +11,8 @@ bar = id
11baz :: Int -> Int
11baz :: Int -> Int
12baz = id
12baz = id
13{-# INLINE [~2] baz #-}
13{-# INLINE [~2] baz #-}
14+
15+reVector :: Bundle u a -> Bundle v a
16+
17+{-# INLINE reVector #-}
18+reVector = M.reVector
data/examples/declaration/signature/minimal/minimal-out.hs+3−5
@@ -1,16 +1,14 @@
1class Foo a where
1class Foo a where
2−
3 {-# MINIMAL (==) | ((/=), foo) #-}
2 {-# MINIMAL (==) | ((/=), foo) #-}
4
3
5 {-# MINIMAL
4 {-# MINIMAL
6 a
5 a
7 | ( b, c, d
6 | ( b, c, d
8− | e
7+ | e,
9− , f
8+ f
10 )
9 )
11− | g
10+ | g
12 #-}
11 #-}
13
12
14 (==) :: a -> a -> Bool
13 (==) :: a -> a -> Bool
15−
16 (/=) :: a -> a -> Bool
14 (/=) :: a -> a -> Bool
data/examples/declaration/signature/pattern/multiline-out.hs+17−4
@@ -1,6 +1,19 @@
1{-# LANGUAGE PatternSynonyms #-}
1{-# LANGUAGE PatternSynonyms #-}
2
2
3−pattern Arrow
3+pattern Arrow ::
4+ Type ->
4− :: Type
5+ Type ->
6+ Type
7+
8+pattern
9+ Foo,
10+ Bar ::
5− -> Type
11+ Type -> Type -> Type
6− -> Type
12+
13+pattern
14+ TypeSignature,
15+ FunctionBody,
16+ PatternSignature,
17+ WarningPragma ::
18+ [RdrName] ->
19+ HsDecl GhcPs
data/examples/declaration/signature/pattern/multiline.hs+10
@@ -1,3 +1,13 @@
1{-# LANGUAGE PatternSynonyms #-}
1{-# LANGUAGE PatternSynonyms #-}
2+
2pattern Arrow :: Type
3pattern Arrow :: Type
3 -> Type -> Type
4 -> Type -> Type
5+
6+pattern Foo, Bar ::
7+ Type -> Type -> Type
8+
9+pattern TypeSignature
10+ , FunctionBody
11+ , PatternSignature
12+ , WarningPragma :: [RdrName]
13+ -> HsDecl GhcPs
data/examples/declaration/signature/pattern/single-line-out.hs+2
@@ -1,3 +1,5 @@
1{-# LANGUAGE PatternSynonyms #-}
1{-# LANGUAGE PatternSynonyms #-}
2
2
3pattern Arrow :: Type -> Type -> Type
3pattern Arrow :: Type -> Type -> Type
4+
5+pattern Foo, Bar :: Type -> Type -> Type
data/examples/declaration/signature/pattern/single-line.hs+2
@@ -1,3 +1,5 @@
1{-# LANGUAGE PatternSynonyms #-}
1{-# LANGUAGE PatternSynonyms #-}
2
2
3pattern Arrow :: Type -> Type -> Type
3pattern Arrow :: Type -> Type -> Type
4+
5+pattern Foo, Bar :: Type -> Type -> Type
data/examples/declaration/signature/specialize/specialize-instance-out.hs−4
@@ -3,16 +3,12 @@ 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−
7 {-# SPECIALIZE instance Eq (Foo [(Int, Bar)]) #-}
6 {-# SPECIALIZE instance Eq (Foo [(Int, Bar)]) #-}
8−
9 (==) (Foo a) (Foo b) = (==) a b
7 (==) (Foo a) (Foo b) = (==) a b
10
8
11instance (Num r, V.Vector v r, Factored m r) => Num (VT v m r) where
9instance (Num r, V.Vector v r, Factored m r) => Num (VT v m r) where
12−
13 {-# SPECIALIZE instance
10 {-# SPECIALIZE instance
14 ( Factored m Int => Num (VT U.Vector m Int)
11 ( Factored m Int => Num (VT U.Vector m Int)
15 )
12 )
16 #-}
13 #-}
17−
18 VT x + VT y = VT $ V.zipWith (+) x y
14 VT x + VT y = VT $ V.zipWith (+) x y
data/examples/declaration/signature/specialize/specialize-out.hs+14−5
@@ -1,15 +1,24 @@
1foo :: Num a => a -> a
1foo :: Num a => a -> a
2foo = id
2foo = id
3{-# SPECIALIZE foo :: Int -> Int #-}
3{-# SPECIALIZE foo :: Int -> Int #-}
4−{-# SPECIALIZE foo :: Float -> Float #-}
4+{-# SPECIALIZE INLINE foo :: Float -> Float #-}
5
5
6−{-# SPECIALIZE [2] bar :: Int -> Int #-}
6+{-# SPECIALIZE NOINLINE [2] bar :: Int -> Int #-}
7bar :: Num a => a -> a
7bar :: Num a => a -> a
8bar = id
8bar = id
9
9
10baz :: Num a => a -> a
10baz :: Num a => a -> a
11baz = id
11baz = id
12−{-# SPECIALIZE [~2] baz
12+{-# SPECIALIZE [~2] baz ::
13− :: Int
13+ Int ->
14− -> Int
14+ Int
15 #-}
15 #-}
16+
17+{-# SPECIALIZE fits13Bits :: Int -> Bool, Integer -> Bool #-}
18+{-# SPECIALIZE fits13Bits ::
19+ Int ->
20+ Bool,
21+ Integer -> Bool
22+ #-}
23+fits13Bits :: Integral a => a -> Bool
24+fits13Bits x = x >= -4096 && x < 4096
data/examples/declaration/signature/specialize/specialize.hs+10−2
@@ -2,9 +2,9 @@ foo :: Num a => a -> a
2foo = id
2foo = id
3
3
4{-# SPECIALIZE foo :: Int -> Int #-}
4{-# SPECIALIZE foo :: Int -> Int #-}
5−{-# SPECIALIZE foo :: Float -> Float #-}
5+{-# SPECIALIZE INLINE foo :: Float -> Float #-}
6
6
7−{-# SPECIALIZE [2] bar :: Int -> Int #-}
7+{-# SPECIALIZE NOINLINE [2] bar :: Int -> Int #-}
8
8
9bar :: Num a => a -> a
9bar :: Num a => a -> a
10bar = id
10bar = id
@@ -14,3 +14,11 @@ baz = id
14{-# SPECIALIZE [~2] baz
14{-# SPECIALIZE [~2] baz
15 :: Int
15 :: Int
16 -> Int #-}
16 -> Int #-}
17+
18+{-# SPECIALIZE fits13Bits :: Int -> Bool, Integer -> Bool #-}
19+{-# SPECIALIZE fits13Bits
20+ :: Int
21+ -> Bool
22+ , Integer -> Bool #-}
23+fits13Bits :: Integral a => a -> Bool
24+fits13Bits x = x >= -4096 && x < 4096
data/examples/declaration/signature/standalone-kind-out.hsnew file+13
@@ -0,0 +1,13 @@
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.hsnew file+13
@@ -0,0 +1,13 @@
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/arguments-out.hs+14−13
@@ -1,15 +1,16 @@
1{-# LANGUAGE RankNTypes #-}
1{-# LANGUAGE RankNTypes #-}
2
2
3−functionName
3+functionName ::
4− :: (C1, C2, C3, C4, C5)
4+ (C1, C2, C3, C4, C5) =>
5− => a
5+ a ->
6− -> b
6+ b ->
7− -> ( forall a. (C6, C7)
7+ ( forall a.
8+ (C6, C7) =>
8− => LongDataTypeName
9+ LongDataTypeName ->
9− -> a
10+ a ->
10− -> AnotherLongDataTypeName
11+ AnotherLongDataTypeName ->
11− -> b
12+ b ->
12− -> c
13+ c
13− )
14+ ) ->
14− -> (c -> d)
15+ (c -> d) ->
15− -> (a, b, c, d)
16+ (a, b, c, d)
data/examples/declaration/signature/type/context-multi-line-out.hs+10−10
@@ -1,10 +1,10 @@
1−functionName
1+functionName ::
2− :: ( C1
2+ ( C1,
3− , C2
3+ C2,
4− , C3
4+ C3
5− )
6− => a
5+ ) =>
7− -> b
6+ a ->
8− -> c
7+ b ->
9− -> d
8+ c ->
9+ d ->
10− -> (a, b, c, d)
10+ (a, b, c, d)
data/examples/declaration/signature/type/context-single-line-out.hs+7−7
@@ -1,7 +1,7 @@
1−functionName
1+functionName ::
2− :: (C1, C2, C3)
2+ (C1, C2, C3) =>
3− => a
3+ a ->
4− -> b
4+ b ->
5− -> c
5+ c ->
6− -> d
6+ d ->
7− -> (a, b, c, d)
7+ (a, b, c, d)
data/examples/declaration/signature/type/infix-promoted-type-constructor-out.hs+2−3
@@ -1,3 +1,2 @@
1−fun1 :: Def ('[Ref s (Stored Uint32), IBool] T.:-> IBool)
1+fun1 :: Def ('[Ref s (Stored Uint32), IBool] 'T.:-> IBool)
2−
3−fun2 :: Def ('[Ref s (Stored Uint32), IBool] :-> IBool)
2+fun2 :: Def ('[Ref s (Stored Uint32), IBool] ':-> IBool)
data/examples/declaration/signature/type/long-function-name-out.hs+6−6
@@ -1,6 +1,6 @@
1−longFunctionName
1+longFunctionName ::
2− :: a
2+ a ->
3− -> b
3+ b ->
4− -> c
4+ c ->
5− -> d
5+ d ->
6− -> (a, b, c, d)
6+ (a, b, c, d)
data/examples/declaration/signature/type/long-multiline-applications-out.hs+16−15
@@ -1,15 +1,16 @@
1−functionName
1+functionName ::
2− :: (C1, C2, C3, C4, C5)
2+ (C1, C2, C3, C4, C5) =>
3− => a
3+ forall a b c.
4− -> b
4+ a ->
5+ b ->
5− -> ( LongDataTypeName
6+ ( LongDataTypeName
6− AnotherLongDataTypeName
7+ AnotherLongDataTypeName
7− AnotherLongDataTypeName2
8+ AnotherLongDataTypeName2
8− AnotherLongDataTypeName3
9+ AnotherLongDataTypeName3 ->
9− -> a
10+ a ->
10− -> AnotherLongDataTypeName4
11+ AnotherLongDataTypeName4 ->
11− -> b
12+ b ->
12− -> c
13+ c
13− )
14+ ) ->
14− -> (c -> d)
15+ (c -> d) ->
15− -> (a, b, c, d)
16+ (a, b, c, d)
data/examples/declaration/signature/type/long-multiline-applications.hs+2−1
@@ -1,6 +1,7 @@
1functionName
1functionName
2 :: (C1, C2, C3, C4, C5)
2 :: (C1, C2, C3, C4, C5)
3+ => forall a b c
3− => a
4+ . a
4 -> b
5 -> b
5 -> ( LongDataTypeName
6 -> ( LongDataTypeName
6 AnotherLongDataTypeName
7 AnotherLongDataTypeName
data/examples/declaration/signature/type/multi-value-out.hs+13−4
@@ -1,6 +1,15 @@
1foo, bar :: Int
1foo, bar :: Int
2+foo = 1
3+bar = 2
2
4
5+a, b, c :: Int
6+a = 1
7+b = 2
8+c = 3
9+
3−foo
10+foo,
4− , bar
11+ bar,
5− , baz
12+ baz ::
6− :: Int
13+ Int
14+bar = 2
15+baz = 3
data/examples/declaration/signature/type/multi-value.hs+9
@@ -1,5 +1,14 @@
1foo, bar :: Int
1foo, bar :: Int
2+foo = 1
3+bar = 2
4+
5+a, b, c :: Int
6+a = 1
7+b = 2
8+c = 3
2
9
3foo,
10foo,
4 bar,
11 bar,
5 baz :: Int
12 baz :: Int
13+bar = 2
14+baz = 3
data/examples/declaration/signature/type/unicode-out.hsnew file+4
@@ -0,0 +1,4 @@
1+{-# LANGUAGE UnicodeSyntax #-}
2+
3+foo :: forall a. Show a => a -> String
4+foo = const ()
data/examples/declaration/signature/type/unicode.hsnew file+4
@@ -0,0 +1,4 @@
1+{-# LANGUAGE UnicodeSyntax #-}
2+
3+foo ∷ ∀a. Show a ⇒ a → String
4+foo = const ()
data/examples/declaration/signature/type/unrelated-out.hsnew file+4
@@ -0,0 +1,4 @@
1+clientFunc1 :: SomeType1
2+clientFunc2 :: SomeType2
3+clientFunc3 :: SomeType3
4+clientFunc1 :<|> clientFunc2 :<|> clientFunc3 = hoistClient foo bar baz
data/examples/declaration/signature/type/unrelated.hsnew file+4
@@ -0,0 +1,4 @@
1+clientFunc1 :: SomeType1
2+clientFunc2 :: SomeType2
3+clientFunc3 :: SomeType3
4+clientFunc1 :<|> clientFunc2 :<|> clientFunc3 = hoistClient foo bar baz
data/examples/declaration/splice/bracket-declaration-out.hsnew file+26
@@ -0,0 +1,26 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+
3+[d|data T a where Foo :: T ()|]
4+
5+foo =
6+ [d|
7+ foo :: Int -> Char
8+
9+ bar = 42
10+ |]
11+
12+[d|
13+ data T = T
14+ deriving (Eq, Ord, Enum, Bounded, Show)
15+ |]
16+
17+$(do [d|baz = baz|])
18+
19+$(singletons [d|data T = T deriving (Eq, Ord, Enum, Bounded, Show)|])
20+
21+$( singletons
22+ [d|
23+ data T = T
24+ deriving (Eq, Ord, Enum, Bounded, Show)
25+ |]
26+ )
data/examples/declaration/splice/bracket-declaration.hsnew file+22
@@ -0,0 +1,22 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+
3+[d| data T a where Foo :: T () |]
4+
5+foo = [d|
6+ foo:: Int -> Char
7+ bar = 42
8+ |]
9+
10+[d|
11+ data T = T
12+ deriving (Eq, Ord, Enum, Bounded, Show)
13+ |]
14+
15+$( do [d| baz = baz |] )
16+
17+$(singletons [d| data T = T deriving (Eq, Ord, Enum, Bounded, Show) |])
18+
19+$(singletons [d|
20+ data T = T
21+ deriving (Eq, Ord, Enum, Bounded, Show)
22+ |])
data/examples/declaration/splice/bracket-out.hs+5−13
@@ -1,25 +1,17 @@
1{-# LANGUAGE TemplateHaskell #-}
1{-# LANGUAGE TemplateHaskell #-}
2
2
3foo =
3foo =
4− [e|
4+ [|
5− foo bar
5+ foo bar
6− |]
6+ |]
7
7
8foo =
8foo =
9 [e|
9 [e|
10− foo bar
10+ foo bar
11− |]
11+ |]
12
12
13foo = [t|Char|]
13foo = [t|Char|]
14
14
15−foo =
16− [d|
17− foo :: Int -> Char
18−
19− bar = 42
20−
21− |]
22−
23foo =
15foo =
24 [||
16 [||
25 foo bar
17 foo bar
data/examples/declaration/splice/bracket.hs−5
@@ -8,10 +8,5 @@ foo = [e| foo bar
8
8
9foo = [t| Char |]
9foo = [t| Char |]
10
10
11−foo = [d|
12− foo:: Int -> Char
13− bar = 42
14− |]
15−
16foo = [|| foo bar
11foo = [|| foo bar
17 ||]
12 ||]
data/examples/declaration/splice/grouped-splices-out.hsnew file+3
@@ -0,0 +1,3 @@
1+$(deriveJSON fieldLabelMod ''A)
2+$(deriveJSON fieldLabelMod ''B)
3+$(deriveJSON fieldLabelMod ''C)
data/examples/declaration/splice/grouped-splices.hsnew file+3
@@ -0,0 +1,3 @@
1+$(deriveJSON fieldLabelMod ''A)
2+$(deriveJSON fieldLabelMod ''B)
3+$(deriveJSON fieldLabelMod ''C)
data/examples/declaration/splice/quotes-out.hs+14
@@ -1,3 +1,17 @@
1foo = ''R
1foo = ''R
2
2
3bar = 'foo
3bar = 'foo
4+
5+bar' = 'foo_bar
6+
7+baz = ''(:#)
8+
9+baz' = ''(Foo.Bar.:#)
10+
11+equals = ''(==)
12+
13+unit = ''()
14+
15+list = ''[]
16+
17+quolified = ''Semigroup.Option
data/examples/declaration/splice/quotes.hs+14
@@ -1,3 +1,17 @@
1foo = ''R
1foo = ''R
2
2
3bar = 'foo
3bar = 'foo
4+
5+bar' = 'foo_bar
6+
7+baz = ''(:#)
8+
9+baz' = ''(Foo.Bar.:#)
10+
11+equals = ''(==)
12+
13+unit = ''()
14+
15+list = ''[]
16+
17+quolified = ''Semigroup.Option
data/examples/declaration/splice/splice-decl-out.hs+1−1
@@ -10,7 +10,7 @@ $$foo
10
10
11foo bar
11foo bar
12
12
13−[e|booya|]
13+[|booya|]
14
14
15-- TemplateHaskell allows Q () at the top level
15-- TemplateHaskell allows Q () at the top level
16do
16do
data/examples/declaration/type-families/closed-type-family/multi-line-out.hs+9−8
@@ -1,7 +1,7 @@
1type family
1type family
2− Id a
2+ Id a =
3− = result
3+ result | result -> a
4− | result -> a where
4+ where
5 Id a =
5 Id a =
6 a
6 a
7
7
@@ -9,15 +9,16 @@ type family
9 G
9 G
10 (a :: k)
10 (a :: k)
11 b
11 b
12− c
12+ c =
13− = foo
13+ foo | foo -> k b
14− | foo -> k b where
14+ 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+ * -> *
20− :: * -> * where
21+ where
21 F Int = Double
22 F Int = Double
22 F Bool =
23 F Bool =
23 Char
24 Char
data/examples/declaration/type-families/closed-type-family/simple-out.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Documentation.
3-- | Documentation.
2type family F a :: * -> * where
4type family F a :: * -> * where
3 F Int = Double
5 F Int = Double
data/examples/declaration/type-families/closed-type-family/simple.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Documentation.
3-- | Documentation.
2
4
3type family F a :: * -> * where
5type family F a :: * -> * where
data/examples/declaration/type-families/closed-type-family/with-equal-sign-out.hsnew file+2
@@ -0,0 +1,2 @@
1+type family TF a b = result where
2+ TF a b = Int
data/examples/declaration/type-families/closed-type-family/with-equal-sign.hsnew file+2
@@ -0,0 +1,2 @@
1+type family TF a b = result where
2+ TF a b = Int
data/examples/declaration/type-families/closed-type-family/with-forall-out.hsnew file+3
@@ -0,0 +1,3 @@
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.hsnew file+3
@@ -0,0 +1,3 @@
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/data-family/no-annotation-out.hs+2
@@ -1,2 +1,4 @@
1+module Main where
2+
1-- | Documentation.
3-- | Documentation.
2data family Array e
4data family Array e
data/examples/declaration/type-families/data-family/no-annotation.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Documentation.
3-- | Documentation.
2
4
3data family Array e
5data family Array e
data/examples/declaration/type-families/data-family/simple-out.hs+2
@@ -1,2 +1,4 @@
1+module Main where
2+
1-- | Documentation.
3-- | Documentation.
2data family GMap k :: Type -> Type
4data family GMap k :: Type -> Type
data/examples/declaration/type-families/data-family/simple.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Documentation.
3-- | Documentation.
2
4
3data family GMap k :: Type -> Type
5data family GMap k :: Type -> Type
data/examples/declaration/type-families/type-family/no-annotation-out.hs+2
@@ -1,2 +1,4 @@
1+module Main where
2+
1-- | Documentation.
3-- | Documentation.
2type family F a b :: Type -> Type
4type family F a b :: Type -> Type
data/examples/declaration/type-families/type-family/no-annotation.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Documentation.
3-- | Documentation.
2
4
3type family F a b :: Type -> Type
5type family F a b :: Type -> Type
data/examples/declaration/type-families/type-family/operator-out.hsnew file+3
@@ -0,0 +1,3 @@
1+type family a ! b
2+
3+type family a . b
data/examples/declaration/type-families/type-family/operator.hsnew file+2
@@ -0,0 +1,2 @@
1+type family a ! b
2+type family a . b
data/examples/declaration/type-families/type-family/simple-out.hs+2
@@ -1,2 +1,4 @@
1+module Main where
2+
1-- | Documentation.
3-- | Documentation.
2type family Elem c :: Type
4type family Elem c :: Type
data/examples/declaration/type-families/type-family/simple.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
1-- | Documentation.
3-- | Documentation.
2
4
3type family Elem c :: Type
5type family Elem c :: Type
data/examples/declaration/type-synonyms/multi-line-out.hs+16−5
@@ -1,7 +1,18 @@
1−type Foo a b c
1+type Foo a b c =
2− = Bar c a b
2+ Bar c a b
3
3
4type Foo
4type Foo
5+ a
6+ b
7+ c =
8+ Bar c a b
9+
10+type Foo =
5− = Bar
11+ Bar
6− Baz
12+ Baz
7− Quux
13+ Quux
14+
15+type API =
16+ "route1" :> ApiRoute1
17+ :<|> "route2" :> ApiRoute2 -- comment here
18+ :<|> OmitDocs :> "i" :> ASomething API
data/examples/declaration/type-synonyms/multi-line.hs+10
@@ -1,7 +1,17 @@
1type Foo a b c
1type Foo a b c
2 = Bar c a b
2 = Bar c a b
3
3
4+type Foo
5+ a
6+ b c
7+ = Bar c a b
8+
4type Foo =
9type Foo =
5 Bar
10 Bar
6 Baz
11 Baz
7 Quux
12 Quux
13+
14+type API
15+ = "route1" :> ApiRoute1
16+ :<|> "route2" :> ApiRoute2 -- comment here
17+ :<|> OmitDocs :> "i" :> ASomething API
data/examples/declaration/type-synonyms/simple-out.hs+6
@@ -1,2 +1,8 @@
1+module Main where
2+
1-- | Documentation.
3-- | Documentation.
2type Foo a b c = Bar c a b
4type Foo a b c = Bar c a b
5+
6+type a ~> b = TyFun a b -> Type
7+
8+type (a :+: b) c d e = ()
data/examples/declaration/type-synonyms/simple.hs+6
@@ -1,3 +1,9 @@
1+module Main where
2+
1-- | Documentation.
3-- | Documentation.
2
4
3type Foo a b c = Bar c a b
5type Foo a b c = Bar c a b
6+
7+type a ~> b = TyFun a b -> Type
8+
9+type (a :+: b) c d e = ()
data/examples/declaration/type-synonyms/with-weird-haddock-out.hsnew file+3
@@ -0,0 +1,3 @@
1+type Elims =
2+ -- | eliminations ordered left-to-right.
3+ [Elim]
data/examples/declaration/type-synonyms/with-weird-haddock.hsnew file+1
@@ -0,0 +1 @@
1+type Elims = [Elim] -- ^ eliminations ordered left-to-right.
data/examples/declaration/type/forall-out.hsnew file+4
@@ -0,0 +1,4 @@
1+type CoerceLocalSig m m' =
2+ forall r a.
3+ LocalSig m r a ->
4+ LocalSig m' r a
data/examples/declaration/type/forall.hsnew file+4
@@ -0,0 +1,4 @@
1+type CoerceLocalSig m m' =
2+ forall r a.
3+ LocalSig m r a ->
4+ LocalSig m' r a
data/examples/declaration/type/lits-out.hsnew file+6
@@ -0,0 +1,6 @@
1+type A = "foo"
2+
3+type B =
4+ "foo\
5+ \bar" ->
6+ ()
data/examples/declaration/type/lits.hsnew file+4
@@ -0,0 +1,4 @@
1+type A = "foo"
2+
3+type B = "foo\
4+ \bar" -> ()
data/examples/declaration/type/misc-kind-signatures-out.hsnew file+5
@@ -0,0 +1,5 @@
1+instance DemoteNodeTypes ('[] :: [NodeType]) where
2+ demoteNodeTypes _ = []
3+
4+b :: (Bool :: *)
5+b = True
data/examples/declaration/type/misc-kind-signatures.hsnew file+5
@@ -0,0 +1,5 @@
1+instance DemoteNodeTypes ('[] :: [NodeType]) where
2+ demoteNodeTypes _ = []
3+
4+b :: (Bool :: *)
5+b = True
data/examples/declaration/type/promotion-out.hsnew file+19
@@ -0,0 +1,19 @@
1+type Foo = Cluster '[ 'NodeCore, 'NodeRelay', 'NodeEdge]
2+
3+data T = T' | T'T
4+
5+type S0 = ' T'
6+
7+type S1 = ' T'T
8+
9+type S2 = Proxy ('[ '[], '[]])
10+
11+type S4 = Proxy ('( 'Just, ' T'T))
12+
13+type S5 = Proxy ('[ 'Just, 'TT'T])
14+
15+type S6 = Proxy ('( '(), '()))
16+
17+type S7 = Proxy ('( 'a, 'b))
18+
19+type S8 = Proxy ('[Int, Bool])
data/examples/declaration/type/promotion.hsnew file+15
@@ -0,0 +1,15 @@
1+type Foo = Cluster '[ 'NodeCore, 'NodeRelay', 'NodeEdge ]
2+
3+data T = T' | T'T
4+
5+type S0 = ' T'
6+
7+type S1 = ' T'T
8+
9+type S2 = Proxy ( '[ '[], '[] ])
10+type S4 = Proxy ( '( 'Just, ' T'T))
11+type S5 = Proxy ( '[ 'Just, ' TT'T])
12+type S6 = Proxy ( '( '(), '() ))
13+type S7 = Proxy ( '( 'a, 'b ))
14+type S8 = Proxy ( '[ Int, Bool ])
15+
data/examples/declaration/type/splice-out.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+
3+type Foo = $(bar [t|Int|])
data/examples/declaration/type/splice.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+
3+type Foo = $( bar [t|Int|] )
data/examples/declaration/type/type-applications-out.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# LANGUAGE TypeApplications #-}
2+
3+type P = K @Bool @(Bool :: *) 'True 'False
data/examples/declaration/type/type-applications.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# LANGUAGE TypeApplications #-}
2+
3+type P = K @Bool @(Bool :: *) 'True 'False
data/examples/declaration/type/visible-forall-out.hsnew file+2
@@ -0,0 +1,2 @@
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.hsnew file+2
@@ -0,0 +1,2 @@
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-0-out.hsnew file+17
@@ -0,0 +1,17 @@
1+foo =
2+ f1
3+ p1
4+ p2
5+ p3
6+
7+foo' =
8+ f2
9+ p1
10+ p2
11+ p3
12+
13+foo'' =
14+ f3
15+ p1
16+ p2
17+ p3
data/examples/declaration/value/function/application-0.hsnew file+12
@@ -0,0 +1,12 @@
1+foo =
2+ f1
3+ p1
4+ p2 p3
5+
6+foo' = f2 p1
7+ p2
8+ p3
9+
10+foo'' =
11+ f3 p1 p2
12+ p3
data/examples/declaration/value/function/application-1-out.hsnew file+19
@@ -0,0 +1,19 @@
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.hsnew file+14
@@ -0,0 +1,14 @@
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/arg-breakpoints-out.hsnew file+3
@@ -0,0 +1,3 @@
1+foo
2+ bar =
3+ body
data/examples/declaration/value/function/arg-breakpoints.hsnew file+3
@@ -0,0 +1,3 @@
1+foo
2+ bar =
3+ body
data/examples/declaration/value/function/arithmetic-sequences-out.hs+16−6
@@ -1,14 +1,24 @@
1−foo = [0..]
1+foo = [0 ..]
2+
3+foo' = [0 .. 5]
2
4
3bar x =
5bar x =
4 [ 0
6 [ 0
5− .. x
7+ .. x
6 ]
8 ]
7
9
8baz x =
10baz x =
9− [ 1
11+ [ 1,
10− , 3
12+ 3
11− .. x
13+ .. x
12 ]
14 ]
13
15
14−barbaz x = [0, 1..]
16+barbaz x = [0, 1 ..]
17+
18+arst = [0 :: Int ..]
19+
20+brst = [0, 1 :: Int ..]
21+
22+crst = [0 :: Int .. 10]
23+
24+drst = [0, 1 :: Int .. 10]
data/examples/declaration/value/function/arithmetic-sequences.hs+5
@@ -1,4 +1,5 @@
1foo = [0..]
1foo = [0..]
2+foo' = [0..5]
2bar x = [
3bar x = [
3 0..x
4 0..x
4 ]
5 ]
@@ -8,3 +9,7 @@ baz x = [
8 x
9 x
9 ]
10 ]
10barbaz x = [ 0, 1.. ]
11barbaz x = [ 0, 1.. ]
12+arst = [0 :: Int ..]
13+brst = [0, 1 :: Int ..]
14+crst = [0 :: Int .. 10]
15+drst = [0, 1 :: Int .. 10]
data/examples/declaration/value/function/arrow/expression-applications-out.hsdeleted−9
@@ -1,9 +0,0 @@
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.hsdeleted−9
@@ -1,9 +0,0 @@
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.hsdeleted−13
@@ -1,13 +0,0 @@
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− )
10− ( g -<
11− y
12− )
13− |)
data/examples/declaration/value/function/arrow/expression-forms.hsdeleted−11
@@ -1,11 +0,0 @@
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.hsnew file+8
@@ -0,0 +1,8 @@
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.hsnew file+7
@@ -0,0 +1,7 @@
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+10−9
@@ -4,15 +4,16 @@ foo x = proc a -> a -< x
4
4
5bar f x =
5bar f x =
6 proc
6 proc
7− ( y
7+ ( y,
8− , z
8+ z,
9− , w
10− )
11− ->
12− f -< -- The value
13− ( x -- Foo
14− , w -- Bar
9+ w
15− , z -- Baz
16 )
10 )
11+ ->
12+ f -- The value
13+ -<
14+ ( x, -- Foo
15+ w, -- Bar
16+ z -- Baz
17+ )
17
18
18baz x = proc a -> a -<< x
19baz x = proc a -> a -<< x
data/examples/declaration/value/function/arrow/proc-cases-out.hs+3−3
@@ -5,9 +5,9 @@ foo f = proc a -> case a of Left b -> f -< b
5bar f g h j =
5bar f g h j =
6 proc a -> case a of
6 proc a -> case a of
7 Left
7 Left
8− ( (a, b)
8+ ( (a, b),
9− , (c, d)
9+ (c, d)
10− ) -> f (a <> c) -< b <> d
10+ ) -> f (a <> c) -< b <> d
11 Right
11 Right
12 (Left a) ->
12 (Left a) ->
13 h -< a
13 h -< a
data/examples/declaration/value/function/arrow/proc-do-complex-out.hs+40−39
@@ -6,56 +6,57 @@ foo
6 h
6 h
7 ma =
7 ma =
8 proc
8 proc
9− ( (a, b)
9+ ( (a, b),
10− , (c, d)
10+ (c, d),
11− , (e, f)
11+ (e, f)
12− )
12+ )
13 -> do
13 -> do
14 -- Begin do
14 -- Begin do
15 (x, y) <- -- GHC parser fails if layed out over multiple lines
15 (x, y) <- -- GHC parser fails if layed out over multiple lines
16 f -- Call into f
16 f -- Call into f
17− ( a
17+ ( a,
18− , c -- Tuple together arguments
18+ c -- Tuple together arguments
19 )
19 )
20− ( b
20+ ( b,
21− , d
22− ) -<
23− ( b + 1 -- Funnel into arrow
24− , d * b
21+ d
25 )
22 )
23+ -<
24+ ( b + 1, -- Funnel into arrow
25+ d * b
26+ )
26 if x `mod` y == 0 -- Basic condition
27 if x `mod` y == 0 -- Basic condition
27− then
28− case e of -- Only left case is relevant
28+ then case e of -- Only left case is relevant
29 Left
29 Left
30− ( z
30+ ( z,
31− , w
31+ w
32− ) -> \u -> -- Procs can have lambdas
32+ ) -> \u -> -- Procs can have lambdas
33 let v =
33 let v =
34− u ^ -- Actually never used
34+ u -- Actually never used
35− 2
35+ ^ 2
36− in ( returnA -<
36+ in ( returnA
37+ -<
37− -- Just do the calculation
38+ -- Just do the calculation
38− (x + y * z)
39+ (x + y * z)
39− )
40− else
41− do
42− let u = x -- Let bindings bind expressions, not commands
43− -- Could pattern match directly on x
44− i <-
45− case u of
46− 0 -> (g . h -< u)
47− n ->
48− ( ( h . g -<
49− y -- First actual use of y
50 )
40 )
41+ else do
42+ let u = x -- Let bindings bind expressions, not commands
43+ -- Could pattern match directly on x
44+ i <- case u of
45+ 0 -> (g . h -< u)
46+ n ->
47+ ( ( h . g
48+ -<
49+ y -- First actual use of y
51 )
50 )
51+ )
52 returnA -< ()
52 returnA -< ()
53 -- Sometimes execute effects
53 -- Sometimes execute effects
54 if i > 0
54 if i > 0
55− then ma -< ()
55+ then ma -< ()
56− else returnA -< ()
56+ else returnA -< ()
57− returnA -<
57+ returnA
58+ -<
58− ( i +
59+ ( i
59− x *
60+ + x
60− y -- Just do the calculation
61+ * y -- Just do the calculation
61− )
62+ )
data/examples/declaration/value/function/arrow/proc-do-simple-out.hsdeleted−36
@@ -1,36 +0,0 @@
1−{-# LANGUAGE Arrows #-}
2−
3−foo f = proc a -> do
4− f -< a
5−
6−bar f = proc a -> do
7− b <- f -< a
8−
9−barbar f g = proc a -> do
10− b <- f -< a
11− returnA -< b
12−
13−barbaz f g = proc (a, b) -> do
14− c <- f -< a
15− d <- g -< b
16−
17−bazbar f = proc a -> do
18− a <-
19− f -<
20− a
21−
22−bazbaz f g h = proc (a, b, c) -> do
23− x <-
24− f b -< a
25− y <-
26− g b -< b
27− z <-
28− h
29− x
30− y -<
31− ( a
32− , b
33− , c
34− )
35− returnA -<
36− (x, y, z)
data/examples/declaration/value/function/arrow/proc-do-simple1-out.hsnew file+18
@@ -0,0 +1,18 @@
1+{-# LANGUAGE Arrows #-}
2+
3+bar f = proc a -> do
4+ b <- f -< a
5+
6+barbar f g = proc a -> do
7+ b <- f -< a
8+ returnA -< b
9+
10+barbaz f g = proc (a, b) -> do
11+ c <- f -< a
12+ d <- g -< b
13+
14+bazbar f = proc a -> do
15+ a <-
16+ f
17+ -<
18+ a
data/examples/declaration/value/function/arrow/proc-do-simple1.hsnew file+20
@@ -0,0 +1,20 @@
1+{-# LANGUAGE Arrows #-}
2+
3+bar f = proc a ->
4+ do b <- f -< a
5+
6+barbar f g = proc a ->
7+ do b <- f -< a
8+ returnA -< b
9+
10+barbaz f g = proc (a, b) ->
11+ do c <- f -< a
12+ d <- g -< b
13+
14+bazbar f = proc a ->
15+ do a
16+ <-
17+ f
18+ -<
19+ a
20+
data/examples/declaration/value/function/arrow/proc-do-simple2-out.hsnew file+22
@@ -0,0 +1,22 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo f = proc a -> do
4+ f -< a
5+
6+bazbaz f g h = proc (a, b, c) -> do
7+ x <-
8+ f b -< a
9+ y <-
10+ g b -< b
11+ z <-
12+ h
13+ x
14+ y
15+ -<
16+ ( a,
17+ b,
18+ c
19+ )
20+ returnA
21+ -<
22+ (x, y, z)
data/examples/declaration/value/function/arrow/proc-do-simple.hs → data/examples/declaration/value/function/arrow/proc-do-simple2.hsrenamed−19
@@ -1,26 +1,7 @@
1{-# LANGUAGE Arrows #-}
1{-# LANGUAGE Arrows #-}
2−
3foo f = proc a ->
2foo f = proc a ->
4 do f -< a
3 do f -< a
5
4
6−bar f = proc a ->
7− do b <- f -< a
8−
9−barbar f g = proc a ->
10− do b <- f -< a
11− returnA -< b
12−
13−barbaz f g = proc (a, b) ->
14− do c <- f -< a
15− d <- g -< b
16−
17−bazbar f = proc a ->
18− do a
19− <-
20− f
21− -<
22− a
23−
24bazbaz f g h = proc (a, b, c) ->
5bazbaz f g h = proc (a, b, c) ->
25 do x
6 do x
26 <- f b -< a
7 <- f b -< a
data/examples/declaration/value/function/arrow/proc-forms-out.hsdeleted−35
@@ -1,35 +0,0 @@
1−{-# LANGUAGE Arrows #-}
2−
3−foo0 f g x y = proc _ -> (|f (g -< (x, y))|)
4−
5−foo1 f g h x =
6− proc (y, z) ->
7− (|test (h f . (h g) -< (y x) . y z) ((h g) . h f -< y z . (y x))|)
8−
9−foo2 f g h x =
10− proc (y, z) ->
11− (| test
12− ( h f .
13− h g -<
14− y x .
15− y z
16− )
17− ( h g .
18− h f -<
19− y z .
20− y x
21− )
22− |)
23−
24−bar0 f g x y = proc _ -> f -< x &&& g -< y
25−
26−bar1 f g h x =
27− proc (y, z) ->
28− h f . (h g) -< (y x) . y z ||| (h g) . h f -< y z . (y x)
29−
30−bar2 f g h x =
31− proc (y, z) ->
32− (h f . h g) -<
33− (y x) . y z |||
34− (h g . h f) -<
35− y z . (y x)
data/examples/declaration/value/function/arrow/proc-forms.hsdeleted−36
@@ -1,36 +0,0 @@
1−{-# LANGUAGE Arrows #-}
2−
3−foo0 f g x y = proc _ -> (| f (g -< (x, y)) |)
4−
5−foo1 f g h x =
6− proc (y, z) ->
7− (| test (h f.(h g) -< (y x).y z)((h g) . h f-<y z . (y x)) |)
8−
9−foo2 f g h x =
10− proc (y, z) -> (|
11− test ( h f
12− . h g
13− -<
14− y x
15− . y z
16− )
17− ( h g
18− . h f
19− -<
20− y z
21− . y x)
22− |)
23−
24−bar0 f g x y = proc _ -> f -< x&&&g -< y
25−
26−bar1 f g h x =
27− proc (y, z) ->
28− h f.(h g) -< (y x).y z ||| (h g) . h f-<y z . (y x)
29−
30−bar2 f g h x =
31− proc (y, z) ->
32− (h f.h g)
33− -< (y x).y z
34− |||
35− (h g . h f)
36− -<y z . (y x)
data/examples/declaration/value/function/arrow/proc-forms1-out.hsnew file+21
@@ -0,0 +1,21 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo0 f g x y = proc _ -> (| f (g -< (x, y)) |)
4+
5+foo1 f g h x =
6+ proc (y, z) ->
7+ (|
8+ test
9+ ( h f
10+ . h g
11+ -<
12+ y x
13+ . y z
14+ )
15+ ( h g
16+ . h f
17+ -<
18+ y z
19+ . y x
20+ )
21+ |)
data/examples/declaration/value/function/arrow/proc-forms1.hsnew file+19
@@ -0,0 +1,19 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo0 f g x y = proc _ -> (| f (g -< (x, y)) |)
4+
5+foo1 f g h x =
6+ proc (y, z) -> (|
7+ test ( h f
8+ . h g
9+ -<
10+ y x
11+ . y z
12+ )
13+ ( h g
14+ . h f
15+ -<
16+ y z
17+ . y x)
18+ |)
19+
data/examples/declaration/value/function/arrow/proc-forms2-out.hsnew file+22
@@ -0,0 +1,22 @@
1+{-# LANGUAGE Arrows #-}
2+
3+bar0 f g h x =
4+ proc (y, z) ->
5+ (| test (h f . (h g) -< (y x) . y z) ((h g) . h f -< y z . (y x)) |)
6+
7+bar1 f g x y = proc _ -> (f -< x) &&& (g -< y)
8+
9+bar2 f g h x =
10+ proc (y, z) ->
11+ (h f . (h g) -< (y x) . y z) ||| ((h g) . h f -< y z . (y x))
12+
13+bar3 f g h x =
14+ proc (y, z) ->
15+ ( (h f . h g)
16+ -<
17+ (y x) . y z
18+ ) |||
19+ ( (h g . h f)
20+ -<
21+ y z . (y x)
22+ )
data/examples/declaration/value/function/arrow/proc-forms2.hsnew file+19
@@ -0,0 +1,19 @@
1+{-# LANGUAGE Arrows #-}
2+
3+bar0 f g h x =
4+ proc (y, z) ->
5+ (| test (h f.(h g) -< (y x).y z)((h g) . h f-<y z . (y x)) |)
6+
7+bar1 f g x y = proc _ -> (f -< x)&&&(g -< y)
8+
9+bar2 f g h x =
10+ proc (y, z) ->
11+ (h f.(h g) -< (y x).y z) ||| ((h g) . h f-<y z . (y x))
12+
13+bar3 f g h x =
14+ proc (y, z) ->
15+ ((h f.h g)
16+ -< (y x).y z)
17+ |||
18+ ((h g . h f)
19+ -<y z . (y x))
data/examples/declaration/value/function/arrow/proc-ifs-out.hs+9−7
@@ -4,10 +4,12 @@ foo f = proc a -> if a then f -< 0 else f -< 1
4
4
5bar f g = proc a ->
5bar 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+ -<
10− a
11+ a
11− else
12+ else
12− g -<
13+ g
14+ -<
13− b
15+ b
data/examples/declaration/value/function/arrow/proc-lets-out.hs+5−5
@@ -4,9 +4,9 @@ foo f = proc a -> let b = a in f -< b
4
4
5bar f g = proc a ->
5bar f g = proc a ->
6 let h =
6 let h =
7− f .
7+ f
8− g a
8+ . g a
9 j =
9 j =
10− g .
10+ g
11− h
11+ . h
12− in id -< (h, j)
12+ in id -< (h, j)
data/examples/declaration/value/function/arrow/proc-parentheses-out.hs+8−7
@@ -4,15 +4,16 @@ foo f = proc a -> (f -< a)
4
4
5bar f g = proc a ->
5bar f g = proc a ->
6 ( ( (f)
6 ( ( (f)
7− ( g
7+ ( g
8− )
8+ )
9+ )
9− ) -<
10+ -<
10− ( ( ( ( ( ( g
11+ ( ( ( ( ( ( g
11− a
12+ a
13+ )
14+ )
12 )
15 )
13 )
16 )
14 )
17 )
15 )
18 )
16− )
17− )
18 )
19 )
data/examples/declaration/value/function/arrow/recursive-procs-out.hs+14−10
@@ -3,17 +3,21 @@
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+ -<
7− y
8+ y
8− bar -<
9+ bar
10+ -<
9− ( a
11+ ( a,
10− , b
12+ b
11− )
13+ )
12 rec p <-
14 rec p <-
13 f
15 f
14− p -<
16+ p
17+ -<
15− a
18+ a
16 rec q <-
19 rec q <-
17 g
20 g
18− q -<
21+ q
22+ -<
19− b
23+ b
data/examples/declaration/value/function/awkward-comment-0-out.hsnew file+6
@@ -0,0 +1,6 @@
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.hsnew file+5
@@ -0,0 +1,5 @@
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.hsnew file+9
@@ -0,0 +1,9 @@
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.hsnew file+7
@@ -0,0 +1,7 @@
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/backticks-lhs-out.hsnew file+7
@@ -0,0 +1,7 @@
1+x `op1` (Just 0) = True
2+op1 x (Just _) = False
3+op1 x Nothing = undefined
4+
5+op2 1 y = False
6+x `op2` y =
7+ True
data/examples/declaration/value/function/backticks-lhs.hsnew file+7
@@ -0,0 +1,7 @@
1+x `op1` (Just 0) = True
2+op1 x (Just _) = False
3+op1 x Nothing = undefined
4+
5+op2 1 y = False
6+x `op2` y =
7+ True
data/examples/declaration/value/function/blank-lines-let-out.hsnew file+6
@@ -0,0 +1,6 @@
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.hsnew file+9
@@ -0,0 +1,9 @@
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.hsnew file+6
@@ -0,0 +1,6 @@
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.hsnew file+7
@@ -0,0 +1,7 @@
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.hsnew file+34
@@ -0,0 +1,34 @@
1+f1 = foo do bar
2+
3+f2 = foo do
4+ bar
5+
6+f3 = foo case True of
7+ True -> bar
8+ False -> baz
9+
10+f4 = foo let a = 3 in b
11+
12+f5 =
13+ foo
14+ let a = 3
15+ b = a
16+ in b
17+
18+f6 =
19+ foo
20+ if bar
21+ then baz
22+ else not baz
23+
24+f7 = foo \x -> y
25+
26+f8 = foo \x ->
27+ y
28+
29+f9 = foo do { bar } baz
30+
31+f10 = foo
32+ do a
33+ do b
34+ do c
data/examples/declaration/value/function/block-arguments.hsnew file+30
@@ -0,0 +1,30 @@
1+f1 = foo do bar
2+
3+f2 = foo do
4+ bar
5+
6+f3 = foo case True of
7+ True -> bar
8+ False -> baz
9+
10+f4 = foo let a = 3 in b
11+
12+f5 = foo let a = 3
13+ b = a
14+ in b
15+
16+f6 = foo if bar
17+ then baz
18+ else not baz
19+
20+f7 = foo \x -> y
21+
22+f8 = foo \x ->
23+ y
24+
25+f9 = foo do { bar } baz
26+
27+f10 = foo
28+ do { a }
29+ do { b }
30+ do c
data/examples/declaration/value/function/case-multi-line-guards-out.hsnew file+16
@@ -0,0 +1,16 @@
1+withGuards :: Int -> Int
2+withGuards x =
3+ case x of
4+ x
5+ | x > 10 ->
6+ foo
7+ + bar
8+ x | x > 5 -> 10
9+ _ -> 20
10+
11+case x of
12+ '-' | not isUrl -> case xs of
13+ _ -> emitc '-'
14+ '*' | not isUrl ->
15+ case xs of
16+ _ -> emitc '*'
data/examples/declaration/value/function/case-multi-line-guards.hsnew file+15
@@ -0,0 +1,15 @@
1+withGuards :: Int -> Int
2+withGuards x =
3+ case x of
4+ x | x > 10 ->
5+ foo +
6+ bar
7+ x | x > 5 -> 10
8+ _ -> 20
9+
10+case x of
11+ '-' | not isUrl -> case xs of
12+ _ -> emitc '-'
13+ '*' | not isUrl ->
14+ case xs of
15+ _ -> emitc '*'
data/examples/declaration/value/function/case-multi-line-out.hs+2−12
@@ -8,8 +8,8 @@ bar x =
8 case x of
8 case x of
9 5 ->
9 5 ->
10 if x > 5
10 if x > 5
11− then 10
11+ then 10
12− else 12
12+ else 12
13 _ -> 12
13 _ -> 12
14
14
15baz :: Int -> Int
15baz :: Int -> Int
@@ -21,16 +21,6 @@ quux :: Int -> Int
21quux x = case x of
21quux x = case x of
22 x -> x
22 x -> x
23
23
24−withGuards :: Int -> Int
25−withGuards x =
26− case x of
27− x
28− | x > 10 ->
29− foo +
30− bar
31− x | x > 5 -> 10
32− _ -> 20
33−
34funnyComment =
24funnyComment =
35 -- comment
25 -- comment
36 case () of
26 case () of
data/examples/declaration/value/function/case-multi-line.hs−9
@@ -18,15 +18,6 @@ quux :: Int -> Int
18quux x = case x of
18quux x = case x of
19 x -> x
19 x -> x
20
20
21−withGuards :: Int -> Int
22−withGuards x =
23− case x of
24− x | x > 10 ->
25− foo +
26− bar
27− x | x > 5 -> 10
28− _ -> 20
29−
30funnyComment = -- comment
21funnyComment = -- comment
31 case () of
22 case () of
32 () -> ()
23 () -> ()
data/examples/declaration/value/function/case-single-line-out.hs+4
@@ -1,2 +1,6 @@
1foo :: Int -> Int
1foo :: Int -> Int
2foo x = case x of x -> x
2foo x = case x of x -> x
3+
4+foo :: IO ()
5+foo = case [1] of [_] -> "singleton"; _ -> "not singleton"
6+foo = case [1] of { [] -> foo; _ -> bar } `finally` baz
data/examples/declaration/value/function/case-single-line.hs+4
@@ -1,2 +1,6 @@
1foo :: Int -> Int
1foo :: Int -> Int
2foo x = case x of x -> x
2foo x = case x of x -> x
3+
4+foo :: IO ()
5+foo = case [1] of [_] -> "singleton"; _ -> "not singleton"
6+foo = case [1] of { [] -> foo; _ -> bar } `finally` baz
data/examples/declaration/value/function/complex-list-out.hsnew file+15
@@ -0,0 +1,15 @@
1+handleStuff =
2+ handle
3+ [ \ExceptionA ->
4+ something,
5+ \ExceptionB ->
6+ somethingElse
7+ ]
8+
9+handleStuff =
10+ handle
11+ [ foo
12+ bar,
13+ baz
14+ qux
15+ ]
data/examples/declaration/value/function/complex-list.hsnew file+15
@@ -0,0 +1,15 @@
1+handleStuff =
2+ handle
3+ [ \ExceptionA ->
4+ something
5+ , \ExceptionB ->
6+ somethingElse
7+ ]
8+
9+handleStuff =
10+ handle
11+ [ foo
12+ bar
13+ , baz
14+ qux
15+ ]
data/examples/declaration/value/function/comprehension/transform-multi-line1-out.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+foo' xs ys =
4+ [ ( x,
5+ y
6+ )
7+ | x <- xs,
8+ y <- ys,
9+ then
10+ -- First comment
11+ reverse -- Second comment
12+ ]
data/examples/declaration/value/function/comprehension/transform-multi-line1.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+foo' xs ys = [
4+ (x,
5+ y) |
6+ x <- xs,
7+ y <- ys,
8+ then -- First comment
9+ reverse -- Second comment
10+ ]
data/examples/declaration/value/function/comprehension/transform-multi-line2-out.hsnew file+16
@@ -0,0 +1,16 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+bar' xs ys =
4+ [ ( x,
5+ y
6+ )
7+ | x <- xs,
8+ y <- ys,
9+ then
10+ -- First comment
11+ sortWith
12+ by
13+ ( x
14+ + y -- Second comment
15+ )
16+ ]
data/examples/declaration/value/function/comprehension/transform-multi-line2.hsnew file+15
@@ -0,0 +1,15 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+bar' xs ys = [
4+ (x,
5+ y) |
6+ x <- xs,
7+ y <- ys,
8+ then -- First comment
9+ sortWith
10+ by
11+ (x
12+ + y) -- Second comment
13+ ]
14+
15+
data/examples/declaration/value/function/comprehension/transform-multi-line3-out.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+baz' xs ys =
4+ [ ( x,
5+ y
6+ )
7+ | x <- xs,
8+ y <- ys,
9+ then group using
10+ -- First comment
11+ permutations -- Second comment
12+ ]
data/examples/declaration/value/function/comprehension/transform-multi-line3.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+baz' xs ys = [
4+ (x,
5+ y) |
6+ x <- xs,
7+ y <- ys,
8+ then
9+ group
10+ using -- First comment
11+ permutations -- Second comment
12+ ]
data/examples/declaration/value/function/comprehension/transform-multi-line4-out.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+quux' xs ys =
4+ [ ( x,
5+ y
6+ )
7+ | x <- xs,
8+ y <- ys,
9+ then group by
10+ -- First comment
11+ ( x
12+ + y
13+ )
14+ using
15+ -- Second comment
16+ groupWith -- Third comment
17+ ]
data/examples/declaration/value/function/comprehension/transform-multi-line4.hsnew file+15
@@ -0,0 +1,15 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+quux' xs ys = [
4+ (x,
5+ y) |
6+ x <- xs,
7+ y <- ys,
8+ then
9+ group
10+ by -- First comment
11+ (x
12+ + y)
13+ using -- Second comment
14+ groupWith -- Third comment
15+ ]
data/examples/declaration/value/function/comprehension/transform-single-line-out.hsnew file+9
@@ -0,0 +1,9 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+foo xs ys = [(x, y) | x <- xs, y <- ys, then reverse]
4+
5+bar xs ys = [(x, y) | x <- xs, y <- ys, then sortWith by (x + y)]
6+
7+baz xs ys = [(x, y) | x <- xs, y <- ys, then group using permutations]
8+
9+quux xs ys = [(x, y) | x <- xs, y <- ys, then group by (x + y) using groupWith]
data/examples/declaration/value/function/comprehension/transform-single-line.hsnew file+9
@@ -0,0 +1,9 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+foo xs ys = [(x, y) | x <- xs, y <- ys, then reverse]
4+
5+bar xs ys = [(x, y) | x <- xs, y <- ys, then sortWith by (x + y)]
6+
7+baz xs ys = [(x, y) | x <- xs, y <- ys, then group using permutations]
8+
9+quux xs ys = [(x, y) | x <- xs, y <- ys, then group by (x + y) using groupWith]
data/examples/declaration/value/function/do-out.hsdeleted−54
@@ -1,54 +0,0 @@
1−{-# LANGUAGE RecursiveDo #-}
2−
3−bar = do
4− foo
5− bar
6−
7−baz =
8− mdo
9− bar a
10− a <- foo
11− b <-
12− bar
13− 1
14− 2
15− 3
16− return (a + b)
17−
18−baz = do
19− a <- foo
20− let b = a + 2
21− c = b + 3
22− bar c
23− let d = c + 2
24− return d
25−
26−quux =
27− something $ do
28− foo
29− case x of
30− 1 -> 10
31− 2 -> 20
32− bar
33− if something
34− then x
35− else y
36− baz
37−
38−foo = do
39− rec a <- b + 5
40− let d = c
41− b <- a * 5
42− something
43− c <- a + b
44− print c
45− rec something $ do
46− x <- a
47− print x
48− y <- c
49− print y
50−
51−trickyLet = do
52− foo
53− let x = 5
54− in bar x
data/examples/declaration/value/function/do-single-multi-out.hsnew file+4
@@ -0,0 +1,4 @@
1+foo = do
2+ ( bar
3+ baz
4+ )
data/examples/declaration/value/function/do-single-multi.hsnew file+2
@@ -0,0 +1,2 @@
1+foo = do (bar
2+ baz)
data/examples/declaration/value/function/do.hsdeleted−53
@@ -1,53 +0,0 @@
1−{-# LANGUAGE RecursiveDo #-}
2−
3−bar = do { foo; bar }
4−
5−baz =
6− mdo bar a
7− a <- foo
8− b <- bar
9− 1 2 3
10− return (a + b)
11−
12−baz = do
13− a <- foo
14− let b = a + 2
15− c = b + 3
16− bar c
17− let d = c + 2
18− return d
19−
20−quux = something $ do
21− foo
22− case x of
23− 1 -> 10
24− 2 -> 20
25− bar
26− if something
27− then x
28− else y
29− baz
30−
31−foo = do
32− rec
33− a <- b + 5
34−
35− let d = c
36−
37− b <- a * 5
38−
39− something
40−
41− c <- a + b
42− print c
43− rec something $ do
44− x <- a
45− print x
46−
47− y <- c
48− print y
49−
50−trickyLet = do
51− foo
52− let x = 5
53− in bar x
data/examples/declaration/value/function/do/applications-and-parens-out.hsnew file+9
@@ -0,0 +1,9 @@
1+warningFor var place = do
2+ guard $ isVariableName var
3+ guard . not $ isInArray var place || isGuarded place
4+ ( if includeGlobals || isLocal var
5+ then warningForLocals
6+ else warningForGlobals
7+ )
8+ var
9+ place
data/examples/declaration/value/function/do/applications-and-parens.hsnew file+6
@@ -0,0 +1,6 @@
1+warningFor var place = do
2+ guard $ isVariableName var
3+ guard . not $ isInArray var place || isGuarded place
4+ (if includeGlobals || isLocal var
5+ then warningForLocals
6+ else warningForGlobals) var place
data/examples/declaration/value/function/do/blocks-out.hsnew file+19
@@ -0,0 +1,19 @@
1+foo = do bar
2+
3+foo = do bar; baz
4+
5+foo = do
6+ bar
7+ baz
8+
9+foo = do do { foo; bar }; baz
10+
11+readInClause = do
12+ do
13+ lookAhead g_Do
14+ parseNote ErrorC 1063 "You need a line feed or semicolon before the 'do'."
15+ <|> do
16+ optional g_Semi
17+ void allspacing
18+
19+ return things
data/examples/declaration/value/function/do/blocks.hsnew file+17
@@ -0,0 +1,17 @@
1+foo = do bar
2+foo = do { bar; baz }
3+foo = do { bar
4+ ; baz
5+ }
6+foo = do { do {foo; bar}; baz }
7+
8+readInClause = do
9+ do {
10+ lookAhead g_Do;
11+ parseNote ErrorC 1063 "You need a line feed or semicolon before the 'do'.";
12+ } <|> do {
13+ optional g_Semi;
14+ void allspacing;
15+ }
16+
17+ return things
data/examples/declaration/value/function/do/comment-alignment-out.hsnew file+9
@@ -0,0 +1,9 @@
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.hsnew file+9
@@ -0,0 +1,9 @@
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.hsnew file+7
@@ -0,0 +1,7 @@
1+foo = do
2+ bar
3+ -- foo
4+ baz
5+
6+ -- foo
7+ quux
data/examples/declaration/value/function/do/comment-spacing.hsnew file+7
@@ -0,0 +1,7 @@
1+foo = do
2+ bar
3+ -- foo
4+ baz
5+
6+ -- foo
7+ quux
data/examples/declaration/value/function/do/expr-out.hsnew file+10
@@ -0,0 +1,10 @@
1+quux = something $ do
2+ foo
3+ case x of
4+ 1 -> 10
5+ 2 -> 20
6+ bar
7+ if something
8+ then x
9+ else y
10+ baz
data/examples/declaration/value/function/do/expr.hsnew file+10
@@ -0,0 +1,10 @@
1+quux = something $ do
2+ foo
3+ case x of
4+ 1 -> 10
5+ 2 -> 20
6+ bar
7+ if something
8+ then x
9+ else y
10+ baz
data/examples/declaration/value/function/do/hang-rhs-arrow-out.hsnew file+9
@@ -0,0 +1,9 @@
1+foo = do
2+ something <- case bar of
3+ Foo -> return 1
4+ Bar -> return 2
5+ somethingElse <-
6+ case boom of
7+ Foo -> return 1
8+ Bar -> return 2
9+ quux something somethingElse
data/examples/declaration/value/function/do/hang-rhs-arrow.hsnew file+9
@@ -0,0 +1,9 @@
1+foo = do
2+ something <- case bar of
3+ Foo -> return 1
4+ Bar -> return 2
5+ somethingElse <-
6+ case boom of
7+ Foo -> return 1
8+ Bar -> return 2
9+ quux something somethingElse
data/examples/declaration/value/function/do/let-out.hsnew file+18
@@ -0,0 +1,18 @@
1+main = do
2+ a <- bar
3+ let a = b; c = d
4+ baz d
5+ let e = f
6+ g = h
7+ return c
8+
9+-- single line let-where
10+samples n f = do
11+ gen <- newQCGen
12+ let rands g = g1 : rands g2 where (g1, g2) = split g
13+ return $ rands gen
14+
15+trickyLet = do
16+ foo
17+ let x = 5
18+ in bar x
data/examples/declaration/value/function/do/let.hsnew file+18
@@ -0,0 +1,18 @@
1+main = do
2+ a <- bar
3+ let a = b; c = d
4+ baz d
5+ let e = f
6+ g = h
7+ return c
8+
9+-- single line let-where
10+samples n f = do
11+ gen <- newQCGen
12+ let rands g = g1 : rands g2 where (g1, g2) = split g
13+ return $ rands gen
14+
15+trickyLet = do
16+ foo
17+ let x = 5
18+ in bar x
data/examples/declaration/value/function/do/operator-and-parens-out.hsnew file+7
@@ -0,0 +1,7 @@
1+scientifically :: (Scientific -> a) -> Parser a
2+scientifically h = do
3+ something
4+ ( I.satisfy (\w -> w == 'e' || w == 'E')
5+ *> fmap (h . Sci.scientific signedCoeff . (e +)) (signed decimal)
6+ )
7+ <|> return (h $ Sci.scientific signedCoeff e)
data/examples/declaration/value/function/do/operator-and-parens.hsnew file+7
@@ -0,0 +1,7 @@
1+scientifically :: (Scientific -> a) -> Parser a
2+scientifically h = do
3+ something
4+ ( I.satisfy (\w -> w == 'e' || w == 'E')
5+ *> fmap (h . Sci.scientific signedCoeff . (e +)) (signed decimal)
6+ )
7+ <|> return (h $ Sci.scientific signedCoeff e)
data/examples/declaration/value/function/do/recursive-do-mdo-out.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE RecursiveDo #-}
2+
3+baz =
4+ mdo
5+ bar a
6+ a <- foo
7+ b <-
8+ bar
9+ 1
10+ 2
11+ 3
12+ return (a + b)
data/examples/declaration/value/function/do/recursive-do-mdo.hsnew file+8
@@ -0,0 +1,8 @@
1+{-# LANGUAGE RecursiveDo #-}
2+
3+baz =
4+ mdo bar a
5+ a <- foo
6+ b <- bar
7+ 1 2 3
8+ return (a + b)
data/examples/declaration/value/function/do/recursive-do-rec-out.hsnew file+19
@@ -0,0 +1,19 @@
1+{-# LANGUAGE RecursiveDo #-}
2+
3+foo = do
4+ rec a <- b + 5
5+
6+ let d = c
7+
8+ b <- a * 5
9+
10+ something
11+
12+ c <- a + b
13+ print c
14+ rec something $ do
15+ x <- a
16+ print x
17+
18+ y <- c
19+ print y
data/examples/declaration/value/function/do/recursive-do-rec.hsnew file+20
@@ -0,0 +1,20 @@
1+{-# LANGUAGE RecursiveDo #-}
2+
3+foo = do
4+ rec
5+ a <- b + 5
6+
7+ let d = c
8+
9+ b <- a * 5
10+
11+ something
12+
13+ c <- a + b
14+ print c
15+ rec something $ do
16+ x <- a
17+ print x
18+
19+ y <- c
20+ print y
data/examples/declaration/value/function/explicit-type-out.hs+2−2
@@ -1,5 +1,5 @@
1foo = 5 :: Int
1foo = 5 :: Int
2
2
3bar =
3bar =
4− 5
4+ 5 ::
5− :: Int
5+ Int
data/examples/declaration/value/function/fancy-forall-0-out.hsnew file+10
@@ -0,0 +1,10 @@
1+wrapError ::
2+ forall outertag innertag t outer inner m a.
3+ ( forall x. Coercible (t m x) (m x),
4+ forall m'.
5+ HasCatch outertag outer m' =>
6+ HasCatch innertag inner (t m'),
7+ HasCatch outertag outer m
8+ ) =>
9+ (forall m'. HasCatch innertag inner m' => m' a) ->
10+ m a
data/examples/declaration/value/function/fancy-forall-0.hsnew file+6
@@ -0,0 +1,6 @@
1+wrapError :: forall outertag innertag t outer inner m a.
2+ ( forall x. Coercible (t m x) (m x)
3+ , forall m'. HasCatch outertag outer m'
4+ => HasCatch innertag inner (t m')
5+ , HasCatch outertag outer m )
6+ => (forall m'. HasCatch innertag inner m' => m' a) -> m a
data/examples/declaration/value/function/fancy-forall-1-out.hsnew file+10
@@ -0,0 +1,10 @@
1+magnify ::
2+ forall outertag innertag t outer inner m a.
3+ ( forall x. Coercible (t m x) (m x),
4+ forall m'.
5+ HasReader outertag outer m' =>
6+ HasReader innertag inner (t m'),
7+ HasReader outertag outer m
8+ ) =>
9+ (forall m'. HasReader innertag inner m' => m' a) ->
10+ m a
data/examples/declaration/value/function/fancy-forall-1.hsnew file+6
@@ -0,0 +1,6 @@
1+magnify :: forall outertag innertag t outer inner m a.
2+ ( forall x. Coercible (t m x) (m x)
3+ , forall m'. HasReader outertag outer m'
4+ => HasReader innertag inner (t m')
5+ , HasReader outertag outer m )
6+ => (forall m'. HasReader innertag inner m' => m' a) -> m a
data/examples/declaration/value/function/guards-out.hs−15
@@ -1,18 +1,3 @@
1−foo :: Int -> Int
2−foo x
3− | x == 5 = 10
4− | otherwise = 12
5−
6−bar :: Int -> Int
7−bar x
8− | x == 5 =
9− foo x +
10− foo 10
11− | x == 6 =
12− foo x +
13− foo 20
14− | otherwise = foo 100
15−
16baz :: Int -> Int
1baz :: Int -> Int
17baz x | x < 0 = x
2baz x | x < 0 = x
18baz x | otherwise = x
3baz x | otherwise = x
data/examples/declaration/value/function/guards.hs−13
@@ -1,16 +1,3 @@
1−foo :: Int -> Int
2−foo x
3− | x == 5 = 10
4− | otherwise = 12
5−
6−bar :: Int -> Int
7−bar x
8− | x == 5 = foo x
9− + foo 10
10− | x == 6 = foo x
11− + foo 20
12− | otherwise = foo 100
13−
14baz :: Int -> Int
1baz :: Int -> Int
15baz x | x < 0 = x
2baz x | x < 0 = x
16baz x | otherwise = x
3baz x | otherwise = x
data/examples/declaration/value/function/if-multi-line-out.hs+14−7
@@ -1,16 +1,23 @@
1foo :: Int -> Int
1foo :: Int -> Int
2foo x =
2foo x =
3 if x > 5
3 if x > 5
4− then 10
4+ then 10
5− else 12
5+ else 12
6
6
7bar :: Int -> Int
7bar :: Int -> Int
8bar x =
8bar x =
9 if x > 5
9 if x > 5
10− then
10+ then
11− foo x +
11+ foo x
12− 100
12+ + 100
13− else
14− case x of
13+ else case x of
15 1 -> 10
14 1 -> 10
16 _ -> 20
15 _ -> 20
16+
17+baz :: Int -> Bar
18+baz x =
19+ if x > 5
20+ then \case
21+ Foo -> bar
22+ else do
23+ undefined
data/examples/declaration/value/function/if-multi-line.hs+10
@@ -10,3 +10,13 @@ bar x =
10 else case x of
10 else case x of
11 1 -> 10
11 1 -> 10
12 _ -> 20
12 _ -> 20
13+
14+baz :: Int -> Bar
15+baz x =
16+ if x > 5
17+ then
18+ \case
19+ Foo -> bar
20+ else
21+ do
22+ undefined
data/examples/declaration/value/function/if-with-comment-out.hsnew file+8
@@ -0,0 +1,8 @@
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.hsnew file+8
@@ -0,0 +1,8 @@
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+8−7
@@ -1,15 +1,16 @@
1{-# LANGUAGE ImplicitParams #-}
1{-# LANGUAGE ImplicitParams #-}
2
2
3sortBy :: (a -> a -> Bool) -> [a] -> [a]
3sortBy :: (a -> a -> Bool) -> [a] -> [a]
4+sortBy = undefined
4
5
5sort :: (?cmp :: a -> a -> Bool) => [a] -> [a]
6sort :: (?cmp :: a -> a -> Bool) => [a] -> [a]
6sort = sortBy ?cmp
7sort = sortBy ?cmp
7
8
8−sort'
9+sort' ::
9− :: ( ?cmp
10+ ( ?cmp ::
10− :: a -> a -> Bool
11+ a -> a -> Bool,
11− , ?foo :: Int
12+ ?foo :: Int
12− )
13+ ) =>
13− => [a]
14+ [a] ->
14− -> [a]
15+ [a]
15sort' = sort
16sort' = sort
data/examples/declaration/value/function/implicit-params.hs+2
@@ -1,6 +1,8 @@
1{-# LANGUAGE ImplicitParams #-}
1{-# LANGUAGE ImplicitParams #-}
2sortBy :: (a -> a -> Bool) -> [a] -> [a]
2sortBy :: (a -> a -> Bool) -> [a] -> [a]
3
3
4+sortBy = undefined
5+
4sort :: (?cmp :: a -> a -> Bool) => [a] -> [a]
6sort :: (?cmp :: a -> a -> Bool) => [a] -> [a]
5sort = sortBy ?cmp
7sort = sortBy ?cmp
6
8
data/examples/declaration/value/function/infix/applicative-out.hsnew file+4
@@ -0,0 +1,4 @@
1+f =
2+ Foo <$> bar
3+ <*> baz
4+ <*> baz'
data/examples/declaration/value/function/infix/applicative.hsnew file+4
@@ -0,0 +1,4 @@
1+f =
2+ Foo <$> bar
3+ <*> baz
4+ <*> baz'
data/examples/declaration/value/function/infix/comments-out.hsnew file+8
@@ -0,0 +1,8 @@
1+main =
2+ bar $ -- bar
3+ baz -- baz
4+
5+bar $
6+ {- foo
7+ -}
8+ bar
data/examples/declaration/value/function/infix/comments.hsnew file+8
@@ -0,0 +1,8 @@
1+main =
2+ bar $ -- bar
3+ baz -- baz
4+
5+bar $
6+ {- foo
7+ -}
8+ bar
data/examples/declaration/value/function/infix/do-out.hsnew file+13
@@ -0,0 +1,13 @@
1+main =
2+ do stuff
3+ `finally` do
4+ recover
5+
6+main = do stuff `finally` recover
7+
8+main = do { stuff } `finally` recover
9+
10+foo =
11+ do
12+ 1
13+ + 2
data/examples/declaration/value/function/infix/do.hsnew file+13
@@ -0,0 +1,13 @@
1+main =
2+ do stuff
3+ `finally` do
4+ recover
5+
6+main = do stuff `finally` recover
7+
8+main = do { stuff } `finally` recover
9+
10+foo = do
11+ 1
12+ +
13+ 2
data/examples/declaration/value/function/infix/dollar-chains-out.hsnew file+22
@@ -0,0 +1,22 @@
1+module Main where
2+
3+foo =
4+ fmap escapeLeadingDollar
5+ . dropPaddingSpace
6+ . dropWhileEnd T.null
7+ . fmap (T.stripEnd . T.pack)
8+ . lines
9+ $ unpackHDS docStr
10+
11+foo =
12+ when (GHC.xopt Cpp dynFlags && not cfgTolerateCpp) $
13+ throwIO (OrmoluCppEnabled path)
14+
15+foo =
16+ bar $
17+ baz $
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.hsnew file+22
@@ -0,0 +1,22 @@
1+module Main where
2+
3+foo =
4+ fmap escapeLeadingDollar
5+ . dropPaddingSpace
6+ . dropWhileEnd T.null
7+ . fmap (T.stripEnd . T.pack)
8+ . lines
9+ $ unpackHDS docStr
10+
11+foo =
12+ when (GHC.xopt Cpp dynFlags && not cfgTolerateCpp) $
13+ throwIO (OrmoluCppEnabled path)
14+
15+foo =
16+ bar
17+ $ baz
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.hsnew file+23
@@ -0,0 +1,23 @@
1+f = unFoo . foo bar baz 3 $ do
2+ act
3+ ret
4+
5+g = unFoo
6+ . foo
7+ bar
8+ baz
9+ 3
10+ $ do
11+ act
12+ ret
13+
14+update =
15+ do
16+ foobar
17+ `catch` \case
18+ a -> a
19+
20+foo =
21+ bar
22+ ++ case foo of
23+ a -> a
data/examples/declaration/value/function/infix/hanging.hsnew file+19
@@ -0,0 +1,19 @@
1+f = unFoo . foo bar baz 3 $ do
2+ act
3+ ret
4+
5+g = unFoo . foo
6+ bar
7+ baz 3 $ do
8+ act
9+ ret
10+
11+update =
12+ do
13+ foobar
14+ `catch` \case
15+ a -> a
16+
17+foo = bar ++
18+ case foo of
19+ a -> a
data/examples/declaration/value/function/infix/lenses-out.hsnew file+21
@@ -0,0 +1,21 @@
1+lenses =
2+ Just $
3+ M.fromList $
4+ "type" .= ("user.connection" :: Text)
5+ # "connection" .= uc
6+ # "user" .= case name of
7+ Just n -> Just $ object ["name" .= n]
8+ Nothing -> Nothing
9+ # []
10+
11+foo =
12+ a
13+ & b .~ 2
14+ & c .~ 3
15+
16+wreq =
17+ let opts =
18+ defaults & auth ?~ awsAuth AWSv4 "key" "secret"
19+ & header "Accept" .~ ["application/json"]
20+ & header "Runscope-Bucket-Auth" .~ ["1example-1111-4yyyy-zzzz-xxxxxxxx"]
21+ in getWith opts
data/examples/declaration/value/function/infix/lenses.hsnew file+16
@@ -0,0 +1,16 @@
1+lenses = Just $ M.fromList
2+ $ "type" .= ("user.connection" :: Text)
3+ # "connection" .= uc
4+ # "user" .= case name of
5+ Just n -> Just $ object ["name" .= n]
6+ Nothing -> Nothing
7+ # []
8+
9+foo = a
10+ & b .~ 2 & c .~ 3
11+
12+wreq =
13+ let opts = defaults & auth ?~ awsAuth AWSv4 "key" "secret"
14+ & header "Accept" .~ ["application/json"]
15+ & header "Runscope-Bucket-Auth" .~ ["1example-1111-4yyyy-zzzz-xxxxxxxx"]
16+ in getWith opts
data/examples/declaration/value/function/infix.hs → data/examples/declaration/value/function/infix/simple-out.hsrenamed+2−2
@@ -8,5 +8,5 @@ bar :: Int -> Int -> Int -> Int
8(x `bar` y) z = z
8(x `bar` y) z = z
9
9
10multiline :: Int -> Int -> Int
10multiline :: Int -> Int -> Int
11−x `multiline`
11+x
12− y = z
12+ `multiline` y = z
data/examples/declaration/value/function/infix-out.hs → data/examples/declaration/value/function/infix/simple.hsrenamed

The content is the same.

data/examples/declaration/value/function/infix/unicode-out.hsnew file+3
@@ -0,0 +1,3 @@
1+main = print ('a' → 'a')
2+ where
3+ (→) = (,)
data/examples/declaration/value/function/infix/unicode.hsnew file+3
@@ -0,0 +1,3 @@
1+main = print ('a' → 'a')
2+ where
3+ (→) = (,)
data/examples/declaration/value/function/lambda-case-out.hs+2
@@ -1,5 +1,7 @@
1{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE LambdaCase #-}
2
2
3+foo = bar (\case JKey {} -> True; _ -> False)
4+
3foo :: Int -> Int
5foo :: Int -> Int
4foo = \case
6foo = \case
5 5 -> 10
7 5 -> 10
data/examples/declaration/value/function/lambda-case.hs+2
@@ -1,5 +1,7 @@
1{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE LambdaCase #-}
2
2
3+foo = bar (\case JKey{} -> True; _ -> False)
4+
3foo :: Int -> Int
5foo :: Int -> Int
4foo = \case
6foo = \case
5 5 -> 10
7 5 -> 10
data/examples/declaration/value/function/lambda-multi-line-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−foo :: a -> a -> a
2−foo x = \y ->
3− x
4−
5−bar :: Int -> Int -> Int
6−bar x = \y ->
7− if x > y
8− then 10
9− else 12
data/examples/declaration/value/function/lambda-multi-line.hsdeleted−9
@@ -1,9 +0,0 @@
1−foo :: a -> a -> a
2−foo x = \y ->
3− x
4−
5−bar :: Int -> Int -> Int
6−bar x = \y ->
7− if x > y
8− then 10
9− else 12
data/examples/declaration/value/function/lambda-multi-line1-out.hsnew file+15
@@ -0,0 +1,15 @@
1+foo :: a -> a -> a
2+foo x = \y ->
3+ x
4+
5+bar :: Int -> Int -> Int
6+bar x = \y ->
7+ if x > y
8+ then 10
9+ else 12
10+
11+foo =
12+ prop "is inverse to closure" $
13+ \(f :: StaticPtr (Int -> Int))
14+ (x :: Int) ->
15+ (unclosure . closure) f x == deRefStaticPtr f x
data/examples/declaration/value/function/lambda-multi-line1.hsnew file+14
@@ -0,0 +1,14 @@
1+foo :: a -> a -> a
2+foo x = \y ->
3+ x
4+
5+bar :: Int -> Int -> Int
6+bar x = \y ->
7+ if x > y
8+ then 10
9+ else 12
10+
11+foo =
12+ prop "is inverse to closure" $ \(f :: StaticPtr (Int -> Int))
13+ (x :: Int) ->
14+ (unclosure . closure) f x == deRefStaticPtr f x
data/examples/declaration/value/function/lambda-multi-line2-out.hsnew file+12
@@ -0,0 +1,12 @@
1+tricky0 =
2+ flip all (zip ws gs) $ \(wt, gt) ->
3+ canUnify poly_given_ok wt gt || go False wt gt
4+
5+tricky1 =
6+ flip all (zip ws gs) $
7+ \(wt, gt) -> canUnify poly_given_ok wt gt || go False wt gt
8+
9+tricky2 =
10+ flip all (zip ws gs) $
11+ \(wt, gt) ->
12+ canUnify poly_given_ok wt gt || go False wt gt
data/examples/declaration/value/function/lambda-multi-line2.hsnew file+12
@@ -0,0 +1,12 @@
1+tricky0 =
2+ flip all (zip ws gs) $ \(wt, gt) ->
3+ canUnify poly_given_ok wt gt || go False wt gt
4+
5+tricky1 =
6+ flip all (zip ws gs) $
7+ \(wt, gt) -> canUnify poly_given_ok wt gt || go False wt gt
8+
9+tricky2 =
10+ flip all (zip ws gs) $
11+ \(wt, gt) ->
12+ canUnify poly_given_ok wt gt || go False wt gt
data/examples/declaration/value/function/lambda-single-line-out.hs+8
@@ -1,3 +1,5 @@
1+{-# LANGUAGE BangPatterns #-}
2+
1foo :: a -> a -> a
3foo :: a -> a -> a
2foo x = \y -> x
4foo x = \y -> x
3
5
@@ -7,3 +9,9 @@ bar x =
7
9
8baz :: a -> a -> a
10baz :: a -> a -> a
9baz = \ ~x ~y -> x
11baz = \ ~x ~y -> x
12+
13+zag :: a -> a -> a
14+zag = \ !x !y -> x
15+
16+spl :: a -> a
17+spl = \ $([p|x|]) -> x
data/examples/declaration/value/function/lambda-single-line.hs+8
@@ -1,3 +1,5 @@
1+{-# LANGUAGE BangPatterns #-}
2+
1foo :: a -> a -> a
3foo :: a -> a -> a
2foo x = \y -> x
4foo x = \y -> x
3
5
@@ -7,3 +9,9 @@ bar x =
7
9
8baz :: a -> a -> a
10baz :: a -> a -> a
9baz = \ ~x ~y -> x
11baz = \ ~x ~y -> x
12+
13+zag :: a -> a -> a
14+zag = \ !x !y -> x
15+
16+spl :: a -> a
17+spl = \ $([p|x|]) -> x
data/examples/declaration/value/function/let-multi-line-out.hs+18−2
@@ -8,5 +8,21 @@ bar :: Int -> Int
8bar x =
8bar x =
9 let z = y
9 let z = y
10 y = x
10 y = x
11− in z +
11+ in z
12− 100
12+ + 100
13+
14+inlineComment :: Int -> Int
15+inlineComment =
16+ let {- join -} go = case () of
17+ () -> undefined
18+ in go
19+
20+implicitParams :: HasCallStack => Int
21+implicitParams =
22+ let ?cs = ?callstack
23+ in foo cs
24+
25+sitting =
26+ foo $
27+ let x = 20
28+ in x
data/examples/declaration/value/function/let-multi-line.hs+15
@@ -10,3 +10,18 @@ bar x =
10 y = x
10 y = x
11 in z
11 in z
12 + 100
12 + 100
13+
14+inlineComment :: Int -> Int
15+inlineComment =
16+ let {- join -} go = case () of
17+ () -> undefined
18+ in go
19+
20+implicitParams :: HasCallStack => Int
21+implicitParams =
22+ let ?cs = ?callstack
23+ in foo cs
24+
25+sitting =
26+ foo $ let x = 20
27+ in x
data/examples/declaration/value/function/let-nested-out.hsnew file+3
@@ -0,0 +1,3 @@
1+_ = _
2+ where
3+ _ = [_ | let _ = _]
data/examples/declaration/value/function/let-nested.hsnew file+3
@@ -0,0 +1,3 @@
1+_ = _
2+ where
3+ _ = [_ | let _ = _]
data/examples/declaration/value/function/let-single-line-out.hs+8
@@ -1,2 +1,10 @@
1foo :: a -> a
1foo :: a -> a
2foo x = let x = x in x
2foo x = let x = x in x
3+foo x = let x = z where z = 2 in x
4+foo x = let x = z where { z = 2 }; a = 3 in x
5+foo x = let g :: Int -> Int; g = id in ()
6+
7+let a = b; c = do { foo; bar }; d = baz in b
8+let a = case True of { True -> foo; False -> bar }; b = foo a in b
9+
10+foo x = let ?g = id; ?f = g in x
data/examples/declaration/value/function/let-single-line.hs+6
@@ -1,2 +1,8 @@
1foo :: a -> a
1foo :: a -> a
2foo x = let x = x in x
2foo x = let x = x in x
3+foo x = let x = z where z = 2 in x
4+foo x = let x = z where { z = 2; }; a = 3 in x
5+foo x = let {g :: Int -> Int; g = id} in ()
6+let a = b; c = do { foo; bar }; d = baz in b
7+let a = case True of { True -> foo; False -> bar }; b = foo a in b
8+foo x = let {?g = id; ?f = g} in x
data/examples/declaration/value/function/list-comprehensions-out.hs+17−18
@@ -4,22 +4,21 @@ bar x y = [(a, b) | a <- x, even a, b <- y, a != b]
4
4
5barbaz x y z w =
5barbaz x y z w =
6 [ (a, b, c, d) -- Foo
6 [ (a, b, c, d) -- Foo
7− | a <-
7+ | a <-
8− x -- Bar
8+ x, -- Bar
9− , b <- y -- Baz
9+ b <- y, -- Baz
10− , any even [a, b]
10+ any even [a, b],
11− , c <-
11+ c <-
12− z *
12+ z
13− z ^
14− 2 -- Bar baz
13+ * z ^ 2, -- Bar baz
15− , d <-
14+ d <-
16− w +
15+ w
17− w -- Baz bar
16+ + w, -- Baz bar
18− , all
17+ all
19− even
18+ even
20− [ a
19+ [ a,
21− , b
20+ b,
22− , c
21+ c,
23− , d
22+ d
24− ]
23+ ]
25 ]
24 ]
data/examples/declaration/value/function/list-notation-0-out.hsnew file+5
@@ -0,0 +1,5 @@
1+foo =
2+ testCase "Foo" testFoo :
3+ testCase "Bar" testBar :
4+ testCase "Baz" testBaz :
5+ []
data/examples/declaration/value/function/list-notation-0.hsnew file+5
@@ -0,0 +1,5 @@
1+foo =
2+ testCase "Foo" testFoo :
3+ testCase "Bar" testBar :
4+ testCase "Baz" testBaz :
5+ []
data/examples/declaration/value/function/list-notation-1-out.hsnew file+8
@@ -0,0 +1,8 @@
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.hsnew file+7
@@ -0,0 +1,7 @@
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.hsnew file+6
@@ -0,0 +1,6 @@
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.hsnew file+5
@@ -0,0 +1,5 @@
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.hsnew file+12
@@ -0,0 +1,12 @@
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.hsnew file+10
@@ -0,0 +1,10 @@
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+11−4
@@ -3,7 +3,14 @@
3foo x = if | x == 5 -> 5
3foo x = if | x == 5 -> 5
4
4
5bar x y =
5bar x y =
6+ if
6− if | x > y -> x
7+ | x > y -> x
7− | x < y ->
8+ | x < y ->
8− y
9+ y
9− | otherwise -> x
10+ | otherwise -> x
11+
12+baz =
13+ if
14+ | p -> f
15+ | otherwise -> g
16+ x
data/examples/declaration/value/function/multi-way-if.hs+5
@@ -7,3 +7,8 @@ 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/multiline-arguments-out.hs+1−1
@@ -4,5 +4,5 @@ foo
4 ( Bar
4 ( Bar
5 x
5 x
6 y
6 y
7− )
7+ )
8 z = x
8 z = x
data/examples/declaration/value/function/multiple-guards-out.hsnew file+14
@@ -0,0 +1,14 @@
1+foo :: Int -> Int
2+foo x
3+ | x == 5 = 10
4+ | otherwise = 12
5+
6+bar :: Int -> Int
7+bar x
8+ | x == 5 =
9+ foo x
10+ + foo 10
11+ | x == 6 =
12+ foo x
13+ + foo 20
14+ | otherwise = foo 100
data/examples/declaration/value/function/multiple-guards.hsnew file+13
@@ -0,0 +1,13 @@
1+foo :: Int -> Int
2+foo x
3+ | x == 5 = 10
4+ | otherwise = 12
5+
6+bar :: Int -> Int
7+bar x
8+ | x == 5 = foo x
9+ + foo 10
10+ | x == 6 = foo x
11+ + foo 20
12+ | otherwise = foo 100
13+
data/examples/declaration/value/function/negation-out.hs+6
@@ -1,2 +1,8 @@
1foo :: Int
1foo :: Int
2foo = (-2)
2foo = (-2)
3+
4+bar :: Int
5+bar = -2
6+
7+baz :: Int
8+baz = - 2
data/examples/declaration/value/function/negation.hs+6
@@ -1,2 +1,8 @@
1foo :: Int
1foo :: Int
2foo = (-2)
2foo = (-2)
3+
4+bar :: Int
5+bar = -2
6+
7+baz :: Int
8+baz = - 2
data/examples/declaration/value/function/operator-comments-0-out.hsnew file+16
@@ -0,0 +1,16 @@
1+foo =
2+ bar
3+ ++
4+ {- some comment -}
5+ case foo of
6+ a -> a
7+
8+foo =
9+ bar
10+ ++ {- some comment -} case foo of
11+ a -> a
12+
13+foo =
14+ bar
15+ ++ case foo {- some comment -} of
16+ a -> a
data/examples/declaration/value/function/operator-comments-0.hsnew file+17
@@ -0,0 +1,17 @@
1+foo =
2+ bar
3+ ++
4+ {- some comment -}
5+ case foo of
6+ a -> a
7+
8+foo =
9+ bar
10+ ++ {- some comment -}
11+ case foo of
12+ a -> a
13+
14+foo =
15+ bar
16+ ++ case foo of {- some comment -}
17+ a -> a
data/examples/declaration/value/function/operator-comments-1-out.hsnew file+16
@@ -0,0 +1,16 @@
1+foo =
2+ bar
3+ ++
4+ -- some comment
5+ case foo of
6+ a -> a
7+
8+foo =
9+ bar
10+ ++ case foo of -- some comment
11+ a -> a
12+
13+foo =
14+ bar
15+ ++ case foo of -- some comment
16+ a -> a
data/examples/declaration/value/function/operator-comments-1.hsnew file+17
@@ -0,0 +1,17 @@
1+foo =
2+ bar
3+ ++
4+ -- some comment
5+ case foo of
6+ a -> a
7+
8+foo =
9+ bar
10+ ++ -- some comment
11+ case foo of
12+ a -> a
13+
14+foo =
15+ bar
16+ ++ case foo of -- some comment
17+ a -> a
data/examples/declaration/value/function/operator-comments-2-out.hsnew file+5
@@ -0,0 +1,5 @@
1+x =
2+ y
3+ ++ f g -- commentA
4+ -- commentB
5+ -- commentC
data/examples/declaration/value/function/operator-comments-2.hsnew file+4
@@ -0,0 +1,4 @@
1+x =
2+ y ++ -- commentA
3+-- commentB
4+ f g -- commentC
data/examples/declaration/value/function/operator-sections-out.hs+2−2
@@ -4,10 +4,10 @@ bar = (<> "hello")
4
4
5baz =
5baz =
6 ( 1 * 2
6 ( 1 * 2
7− +
7+ +
8 )
8 )
9 ( *
9 ( *
10− 3 ^ 5
10+ 3 ^ 5
11 )
11 )
12
12
13quux = (,) <$> foo <$> bar
13quux = (,) <$> foo <$> bar
data/examples/declaration/value/function/operators-0-out.hsnew file+5
@@ -0,0 +1,5 @@
1+a =
2+ b & c .~ d
3+ & e
4+ %~ f
5+ g
data/examples/declaration/value/function/operators-0.hsnew file+4
@@ -0,0 +1,4 @@
1+a =
2+ b & c .~ d
3+ & e %~ f
4+ g
data/examples/declaration/value/function/operators-1-out.hsnew file+4
@@ -0,0 +1,4 @@
1+foo =
2+ f
3+ . g
4+ =<< h . i
data/examples/declaration/value/function/operators-1.hsnew file+3
@@ -0,0 +1,3 @@
1+foo = f
2+ . g
3+ =<< h . i
data/examples/declaration/value/function/operators-2-out.hsnew file+4
@@ -0,0 +1,4 @@
1+foo n
2+ | x || y && z || n ** x
3+ || x && n =
4+ 42
data/examples/declaration/value/function/operators-2.hsnew file+4
@@ -0,0 +1,4 @@
1+foo n
2+ | x || y && z || n ** x
3+ || x && n =
4+ 42
data/examples/declaration/value/function/operators-3-out.hsnew file+3
@@ -0,0 +1,3 @@
1+foo =
2+ op <> n <+> colon <+> prettySe <+> text "="
3+ <+> prettySe <> text sc
data/examples/declaration/value/function/operators-3.hsnew file+3
@@ -0,0 +1,3 @@
1+foo =
2+ op <> n <+> colon <+> prettySe <+> text "=" <+>
3+ prettySe <> text sc
data/examples/declaration/value/function/operators-4-out.hsnew file+3
@@ -0,0 +1,3 @@
1+foo =
2+ line <> bindingOf <+> text "=" <+> tPretty <+> colon
3+ <+> align <> prettyPs
data/examples/declaration/value/function/operators-4.hsnew file+3
@@ -0,0 +1,3 @@
1+foo =
2+ line <> bindingOf <+> text "=" <+> tPretty <+> colon <+>
3+ align <> prettyPs
data/examples/declaration/value/function/operators-5-out.hsnew file+5
@@ -0,0 +1,5 @@
1+foo =
2+ map bar $
3+ [ baz
4+ ]
5+ ++ quux
data/examples/declaration/value/function/operators-5.hsnew file+4
@@ -0,0 +1,4 @@
1+foo =
2+ map bar $
3+ [ baz
4+ ] ++ quux
data/examples/declaration/value/function/operators-6-out.hsnew file+9
@@ -0,0 +1,9 @@
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.hsnew file+7
@@ -0,0 +1,7 @@
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.hsnew file+11
@@ -0,0 +1,11 @@
1+reallyincrediblyLongName =
2+ f
3+ a
4+ A
5+ { reallyincrediblyLongName =
6+ f
7+ a
8+ A
9+ { reallyincrediblyLongName
10+ }
11+ }
data/examples/declaration/value/function/overindentation.hsnew file+9
@@ -0,0 +1,9 @@
1+reallyincrediblyLongName = f
2+ a
3+ A
4+ { reallyincrediblyLongName = f
5+ a
6+ A
7+ { reallyincrediblyLongName
8+ }
9+ }
data/examples/declaration/value/function/parallel-comprehensions-complex-out.hsnew file+35
@@ -0,0 +1,35 @@
1+baz x y z w =
2+ [ ( a,
3+ b,
4+ c,
5+ d,
6+ e,
7+ f,
8+ g,
9+ h,
10+ i,
11+ j
12+ )
13+ | a <- -- Foo 1
14+ x, -- Foo 2
15+ b <- -- Bar 1
16+ y, -- Bar 2
17+ a
18+ `mod` b -- Value
19+ == 0
20+ | c <- -- Baz 1
21+ z
22+ * z -- Baz 2
23+ -- Baz 3
24+ | d <- w -- Other
25+ | e <- x * x -- Foo bar
26+ | f <- -- Foo baz 1
27+ y + y -- Foo baz 2
28+ | h <- z + z * w ^ 2 -- Bar foo
29+ | i <- -- Bar bar 1
30+ a
31+ + b, -- Bar bar 2
32+ -- Bar bar 3
33+ j <- -- Bar baz 1
34+ a + b -- Bar baz 2
35+ ]
data/examples/declaration/value/function/parallel-comprehensions.hs → data/examples/declaration/value/function/parallel-comprehensions-complex.hsrenamed−4
@@ -1,7 +1,3 @@
1−foo x y = [(a,b) | a<-x | b<-y]
2−
3−bar x y z w = [(a,b,c,d) | a<-x, b<-y, a`mod`b == 0|c<-z|d<-w ]
4−
5baz x y z w = [
1baz x y z w = [
6 (a,b,c,d,e,
2 (a,b,c,d,e,
7 f,g,h,i,j) |
3 f,g,h,i,j) |
data/examples/declaration/value/function/parallel-comprehensions-out.hsdeleted−37
@@ -1,37 +0,0 @@
1−foo x y = [(a, b) | a <- x | b <- y]
2−
3−bar x y z w = [(a, b, c, d) | a <- x, b <- y, a `mod` b == 0 | c <- z | d <- w]
4−
5−baz x y z w =
6− [ ( a
7− , b
8− , c
9− , d
10− , e
11− , f
12− , g
13− , h
14− , i
15− , j
16− )
17− | a <- -- Foo 1
18− x -- Foo 2
19− , b <- -- Bar 1
20− y -- Bar 2
21− , a `mod`
22− b == -- Value
23− 0
24− | c <- -- Baz 1
25− z * -- Baz 2
26− z -- Baz 3
27− | d <- w -- Other
28− | e <- x * x -- Foo bar
29− | f <- -- Foo baz 1
30− y + y -- Foo baz 2
31− | h <- z + z * w ^ 2 -- Bar foo
32− | i <- -- Bar bar 1
33− a + -- Bar bar 2
34− b -- Bar bar 3
35− , j <- -- Bar baz 1
36− a + b -- Bar baz 2
37− ]
data/examples/declaration/value/function/parallel-comprehensions-single-line-out.hsnew file+3
@@ -0,0 +1,3 @@
1+foo x y = [(a, b) | a <- x | b <- y]
2+
3+bar x y z w = [(a, b, c, d) | a <- x, b <- y, a `mod` b == 0 | c <- z | d <- w]
data/examples/declaration/value/function/parallel-comprehensions-single-line.hsnew file+4
@@ -0,0 +1,4 @@
1+foo x y = [(a,b) | a<-x | b<-y]
2+
3+bar x y z w = [(a,b,c,d) | a<-x, b<-y, a`mod`b == 0|c<-z|d<-w ]
4+
data/examples/declaration/value/function/parens-out.hsnew file+1
@@ -0,0 +1 @@
1+f = p (do foo; bar) baz
data/examples/declaration/value/function/parens.hsnew file+1
@@ -0,0 +1 @@
1+f = p (do foo; bar) baz
data/examples/declaration/value/function/parenthesis-lhs-out.hsnew file+9
@@ -0,0 +1,9 @@
1+(!=!) 2 y = 1
2+x !=! y = 2
3+
4+x ?=? [] = 123
5+(?=?) x (_ : []) = 456
6+x ?=? _ = f x x
7+ where
8+ f x 7 = 789
9+ x `f` _ = 101
data/examples/declaration/value/function/parenthesis-lhs.hsnew file+9
@@ -0,0 +1,9 @@
1+(!=!) 2 y = 1
2+x !=! y = 2
3+
4+x ?=? [] = 123
5+(?=?) x (_:[]) = 456
6+x ?=? _ = f x x
7+ where
8+ f x 7 = 789
9+ x `f` _ = 101
data/examples/declaration/value/function/pattern/as-pattern-out.hsnew file+3
@@ -0,0 +1,3 @@
1+main = case [1] of
2+ xs@(x : _) -> print (x, xs)
3+ xs@[] -> print xs
data/examples/declaration/value/function/pattern/as-pattern.hsnew file+3
@@ -0,0 +1,3 @@
1+main = case [1] of
2+ xs @ (x:_) -> print (x, xs)
3+ xs@[] -> print xs
data/examples/declaration/value/function/pattern/famous-cardano-pattern-out.hsnew file+8
@@ -0,0 +1,8 @@
1+( getNodeSettingsR
2+ :<|> getNodeInfoR
3+ :<|> getNextUpdateR
4+ :<|> restartNodeR
5+ )
6+ :<|> ( getUtxoR
7+ :<|> getConfirmedProposalsR
8+ ) = client nodeV1Api
data/examples/declaration/value/function/pattern/famous-cardano-pattern.hsnew file+7
@@ -0,0 +1,7 @@
1+( getNodeSettingsR
2+ :<|> getNodeInfoR
3+ :<|> getNextUpdateR
4+ :<|> restartNodeR
5+ ):<|>( getUtxoR
6+ :<|> getConfirmedProposalsR
7+ ) = client nodeV1Api
data/examples/declaration/value/function/pattern/multiline-case-pattern-out.hsnew file+15
@@ -0,0 +1,15 @@
1+readerBench doc name =
2+ runPure $ case (getReader name, getWriter name) of
3+ ( Right (TextReader r, rexts),
4+ Right (TextWriter w, wexts)
5+ ) -> undefined
6+
7+f xs = case xs of
8+ [ a,
9+ b
10+ ] -> a + b
11+
12+g xs = case xs of
13+ ( a
14+ : bs
15+ ) -> a + b
data/examples/declaration/value/function/pattern/multiline-case-pattern.hsnew file+12
@@ -0,0 +1,12 @@
1+readerBench doc name =
2+ runPure $ case (getReader name, getWriter name) of
3+ (Right (TextReader r, rexts),
4+ Right (TextWriter w, wexts)) -> undefined
5+
6+f xs = case xs of
7+ [ a,
8+ b ] -> a + b
9+
10+g xs = case xs of
11+ (a:
12+ bs) -> a + b
data/examples/declaration/value/function/pattern/n-plus-k-pattern-out.hs+4−1
@@ -7,4 +7,7 @@ multiline :: Int
7multiline
7multiline
8 ( n
8 ( n
9 + 1
9 + 1
10− ) = n
10+ ) = n
11+
12+n :: Int
13+(n + 1) = 3
data/examples/declaration/value/function/pattern/n-plus-k-pattern.hs+3
@@ -5,3 +5,6 @@ singleline (n + 1) = n
5multiline :: Int
5multiline :: Int
6multiline(n
6multiline(n
7 + 1) = n
7 + 1) = n
8+
9+n :: Int
10+(n + 1) = 3
data/examples/declaration/value/function/pattern/pattern-bind-out.hs+4−1
@@ -1,6 +1,9 @@
1−foo :: Int
2foo = bar
1foo = bar
3 where
2 where
4 Foo bar baz = quux
3 Foo bar baz = quux
5 Baz
4 Baz
6 quux = zoo
5 quux = zoo
6+
7+foo = bar
8+ where
9+ Foo bar baz = quux
data/examples/declaration/value/function/pattern/pattern-bind.hs+4−1
@@ -1,6 +1,9 @@
1−foo :: Int
2foo = bar
1foo = bar
3 where
2 where
4 Foo bar baz = quux
3 Foo bar baz = quux
5 Baz
4 Baz
6 quux = zoo
5 quux = zoo
6+
7+foo = bar
8+ where Foo bar baz = quux
9+
data/examples/declaration/value/function/pattern/record-patterns-out.hs+3−3
@@ -13,7 +13,7 @@ baz Boom {boom = b, ..} = b
13quux :: Boom -> Int
13quux :: Boom -> Int
14quux
14quux
15 Boom
15 Boom
16− { boom = a
16+ { boom = a,
17− , foom = b
17+ foom = b,
18− , ..
18+ ..
19 } = a + b
19 } = a + b
data/examples/declaration/value/function/pattern/sig-pattern-out.hs+2−2
@@ -2,6 +2,6 @@ f = do
2 x :: a <- g
2 x :: a <- g
3
3
4f = do
4f = do
5− (x, y)
5+ (x, y) ::
6− :: (a, b) <-
6+ (a, b) <-
7 g
7 g
data/examples/declaration/value/function/pattern/splice-pattern-out.hs+2−2
@@ -5,8 +5,8 @@ singleLine = case () of
5 $(y "something") -> ()
5 $(y "something") -> ()
6
6
7multiline = case () of
7multiline = case () of
8− $( x +
8+ $( x
9− y
9+ + y
10 ) -> ()
10 ) -> ()
11 $( y
11 $( y
12 "something"
12 "something"
data/examples/declaration/value/function/pattern/strictness-out.hsnew file+5
@@ -0,0 +1,5 @@
1+{-# LANGUAGE BangPatterns #-}
2+
3+!a = ()
4+
5+~b = ()
data/examples/declaration/value/function/pattern/strictness.hsnew file+4
@@ -0,0 +1,4 @@
1+{-# LANGUAGE BangPatterns #-}
2+
3+!a = ()
4+~b = ()
data/examples/declaration/value/function/pattern/unboxed-sum-pattern-out.hsnew file+26
@@ -0,0 +1,26 @@
1+{-# LANGUAGE UnboxedSums #-}
2+
3+v = True
4+ where
5+ (# _x #) = (# True #)
6+
7+p = True
8+ where
9+ (# _x | #) = (# | True #)
10+
11+q = True
12+ where
13+ (# | _x | #) = (# | True | #)
14+
15+z = True
16+ where
17+ (# | | _x #) = (# | | True #)
18+
19+z_multiline = True
20+ where
21+ (#
22+ | | _x
23+ #) =
24+ (#
25+ | | True
26+ #)
data/examples/declaration/value/function/pattern/unboxed-sum-pattern.hsnew file+23
@@ -0,0 +1,23 @@
1+{-# LANGUAGE UnboxedSums #-}
2+
3+v = True
4+ where
5+ (# _x #) = (# True #)
6+
7+p = True
8+ where
9+ (# _x | #) = (# | True #)
10+
11+q = True
12+ where
13+ (# | _x | #) = (# | True | #)
14+
15+z = True
16+ where
17+ (# | | _x #) = (# | | True #)
18+
19+z_multiline = True
20+ where
21+ (# |
22+ | _x #) = (# |
23+ | True #)
data/examples/declaration/value/function/pattern/view-pattern-out.hs+1−1
@@ -12,4 +12,4 @@ multiline
12 Foo
12 Foo
13 bar
13 bar
14 baz
14 baz
15− ) = True
15+ ) = True
data/examples/declaration/value/function/record-constructors-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−foo = Foo {a = 3}
2−
3−bar = Bar
4− { abc = foo
5− , def = Foo {a = 10}
6− }
7−
8−baz = Baz {}
data/examples/declaration/value/function/record-constructors.hsdeleted−6
@@ -1,6 +0,0 @@
1−foo = Foo { a = 3 }
2−bar = Bar {
3− abc = foo,
4− def = Foo {a = 10}
5−}
6−baz = Baz{ }
data/examples/declaration/value/function/record-updaters-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−foo x = x {a = 3}
2−
3−bar x =
4− x
5− { abc = foo
6− , def = Foo {a = 10}
7− }
8−
9−baz x = x {}
data/examples/declaration/value/function/record/constructors-out.hsnew file+31
@@ -0,0 +1,31 @@
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/constructors.hsnew file+22
@@ -0,0 +1,22 @@
1+foo = Foo { a = 3 }
2+bar = Bar {
3+ abc = foo,
4+ def = Foo {a = 10}
5+}
6+baz = Baz{ }
7+sym = Foo { (+) = 3 }
8+aLongVariableName =
9+ ALongRecordName
10+ { short = baz,
11+ aLongRecordFieldName = YetAnotherLongRecordName
12+ { yetAnotherLongRecordFieldName = "a long string"
13+ },
14+ aLongRecordFieldName2 = Just YetAnotherLongRecordName
15+ { yetAnotherLongRecordFieldName = "a long string",
16+ yetAnotherLongRecordFieldName = Just
17+ "a long string"
18+ },
19+ aLongRecordFieldName3 = do
20+ foo
21+ bar
22+ }
data/examples/declaration/value/function/record/dot-out.hsnew file+15
@@ -0,0 +1,15 @@
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.hsnew file+14
@@ -0,0 +1,14 @@
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.hsnew file+8
@@ -0,0 +1,8 @@
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.hsnew file+7
@@ -0,0 +1,7 @@
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.hsnew file+8
@@ -0,0 +1,8 @@
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.hsnew file+7
@@ -0,0 +1,7 @@
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.hsnew file+13
@@ -0,0 +1,13 @@
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.hsnew file+11
@@ -0,0 +1,11 @@
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/record/updaters-out.hsnew file+11
@@ -0,0 +1,11 @@
1+foo x = x {a = 3}
2+
3+bar x =
4+ x
5+ { abc = foo,
6+ def = Foo {a = 10}
7+ }
8+
9+baz x = x {}
10+
11+sym x = x {(+) = 4}
data/examples/declaration/value/function/record-updaters.hs → data/examples/declaration/value/function/record/updaters.hsrenamed+1
@@ -4,3 +4,4 @@ bar x = x {
4 def = Foo {a = 10}
4 def = Foo {a = 10}
5}
5}
6baz x = x{ }
6baz x = x{ }
7+sym x = x { (+) = 4 }
data/examples/declaration/value/function/record-wildcards-out.hs → data/examples/declaration/value/function/record/wildcards-out.hsrenamed+7−6
@@ -3,11 +3,12 @@
3
3
4foo x y = Foo {x, y}
4foo x y = Foo {x, y}
5
5
6−bar x y z = Bar
6+bar x y z =
7+ Bar
7− { x
8+ { x,
8− , y
9+ y,
9− , z
10+ z,
10− , ..
11+ ..
11− }
12+ }
12
13
13baz = Baz {..}
14baz = 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/static-pointers-out.hs+6−5
@@ -6,14 +6,15 @@ foo = static 5
6bar :: StaticPtr [Int]
6bar :: StaticPtr [Int]
7bar =
7bar =
8 static
8 static
9− [ 1
9+ [ 1,
10− , 2
10+ 2,
11− , 3
11+ 3
12 ]
12 ]
13
13
14baz :: StaticPtr Bool
14baz :: StaticPtr Bool
15baz =
15baz =
16 static
16 static
17− ( fun 1
17+ ( fun
18+ 1
18− 2
19+ 2
19 )
20 )
data/examples/declaration/value/function/strings-out.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE MagicHash #-}
2+
3+foo = "foobar"
4+
5+bar = "foo\&barbaz"
6+
7+baz =
8+ "foo\
9+ \bar\
10+ \baz"
data/examples/declaration/value/function/strings.hsnew file+7
@@ -0,0 +1,7 @@
1+{-# LANGUAGE MagicHash #-}
2+
3+foo = "foobar"
4+bar = "foo\&bar\ \baz"
5+baz = "foo\
6+ \bar\
7+ \baz"
data/examples/declaration/value/function/tricky-parens-out.hsnew file+4
@@ -0,0 +1,4 @@
1+handleStuff =
2+ ( let foo = foo
3+ in foo
4+ )
data/examples/declaration/value/function/tricky-parens.hsnew file+4
@@ -0,0 +1,4 @@
1+handleStuff =
2+ ( let foo = foo
3+ in foo
4+ )
data/examples/declaration/value/function/tuple-sections-out.hs+1−2
@@ -5,5 +5,4 @@ foo = (,2)
5bar = (,5,)
5bar = (,5,)
6
6
7baz =
7baz =
8− ( ,,5,6,7,,,
8+ (,,5,6,7,,,)
9− )
data/examples/declaration/value/function/tuples-out.hs+10−3
@@ -1,7 +1,14 @@
1foo = (1, 2, 3)
1foo = (1, 2, 3)
2
2
3bar =
3bar =
4− ( 1
4+ ( 1,
5− , 2
5+ 2,
6− , 3
6+ 3
7+ )
8+
9+handleStuff =
10+ ( let foo = foo
11+ in foo,
12+ let bar = bar
13+ in bar
7 )
14 )
data/examples/declaration/value/function/tuples.hs+7
@@ -4,3 +4,10 @@ bar = (
4 2,
4 2,
5 3
5 3
6 )
6 )
7+
8+handleStuff =
9+ ( let foo = foo
10+ in foo
11+ , let bar = bar
12+ in bar
13+ )
data/examples/declaration/value/function/type-applications-and-splice-out.hsnew file+4
@@ -0,0 +1,4 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+{-# LANGUAGE TypeApplications #-}
3+
4+staticKey name = [|sing @ $(symFQN name)|]
data/examples/declaration/value/function/type-applications-and-splice.hsnew file+4
@@ -0,0 +1,4 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+{-# LANGUAGE TypeApplications #-}
3+
4+staticKey name = [| sing @ $(symFQN name) |]
data/examples/declaration/value/function/type-applications-out.hs+6
@@ -8,3 +8,9 @@ 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,3 +6,8 @@ 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/declaration/value/function/typed-expressions-out.hs+2−2
@@ -1,5 +1,5 @@
1foo x = x :: Int
1foo x = x :: Int
2
2
3bar x =
3bar x =
4− Just x
4+ Just x ::
5− :: Maybe String
5+ Maybe String
data/examples/declaration/value/function/typed-hole-out.hsnew file+5
@@ -0,0 +1,5 @@
1+foo = 1 `_` 2
2+
3+bar = 1 `_a` 2
4+
5+baz = _ `something` _
data/examples/declaration/value/function/typed-hole.hsnew file+5
@@ -0,0 +1,5 @@
1+foo = 1 `_` 2
2+
3+bar = 1 `_a` 2
4+
5+baz = _ `something` _
data/examples/declaration/value/function/unboxed-string-lit-out.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# LANGUAGE MagicHash #-}
2+
3+main = new "p"#
data/examples/declaration/value/function/unboxed-string-lit.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# LANGUAGE MagicHash #-}
2+
3+main = new "p"#
data/examples/declaration/value/function/unboxed-sums-out.hs+2−1
@@ -5,5 +5,6 @@ foo = (# 1 | #)
5bar = (# | | 2 | #)
5bar = (# | | 2 | #)
6
6
7baz =
7baz =
8+ (#
8− (# | | | 10 | | | | |
9+ | | | 10 | | | | |
9 #)
10 #)
data/examples/declaration/value/function/unboxed-tuples-out.hs+4−3
@@ -3,7 +3,8 @@
3foo = (# 1, 2, 3 #)
3foo = (# 1, 2, 3 #)
4
4
5bar =
5bar =
6+ (#
6− (# 1
7+ 1,
7− , 2
8+ 2,
8− , 3
9+ 3
9 #)
10 #)
data/examples/declaration/value/function/where-nested-out.hsnew file+12
@@ -0,0 +1,12 @@
1+foo = bar
2+ where
3+ f1 = f1
4+ where
5+ f1 = 3
6+ f2 = f2
7+ where
8+ f2 = 3
9+
10+foo2 = bar
11+ where
12+ f1 = f1 where { f1 = 3; f1' = 4 }; f2 = f2 where f2 = 3; f2' = 4
data/examples/declaration/value/function/where-nested.hsnew file+12
@@ -0,0 +1,12 @@
1+foo = bar
2+ where
3+ f1 = f1
4+ where
5+ f1 = 3
6+ f2 = f2
7+ where
8+ f2 = 3
9+
10+foo2 = bar
11+ where
12+ { f1 = f1 where { f1 = 3; f1' = 4 }; f2 = f2 where { f2 = 3; f2' = 4 } }
data/examples/declaration/value/function/where-out.hs+5−3
@@ -1,7 +1,5 @@
1foo :: Int -> Int
1foo :: Int -> Int
2−foo x = f x
2+foo x = f x where f z = z
3− where
4− f z = z
5
3
6bar :: Int -> Int
4bar :: Int -> Int
7bar x = f x
5bar x = f x
@@ -15,3 +13,7 @@ baz x = q
15 y = x
13 y = x
16 z = y
14 z = y
17 q = z
15 q = z
16+
17+emptyWhere :: Int
18+emptyWhere = 5
19+ where
data/examples/declaration/value/function/where.hs+4
@@ -13,3 +13,7 @@ baz x = q
13 y = x
13 y = x
14 z = y
14 z = y
15 q = z
15 q = z
16+
17+emptyWhere :: Int
18+emptyWhere = 5
19+ where
data/examples/declaration/value/other/comments-get-before-op-out.hsnew file+10
@@ -0,0 +1,10 @@
1+main :: IO ()
2+main = do
3+ migrateSchema
4+ [ migration1,
5+ migration1,
6+ migration3
7+ -- When adding migrations here, don't forget to update
8+ -- 'schemaVersion' in Galley.Data
9+ ]
10+ `finally` Log.close
data/examples/declaration/value/other/comments-get-before-op.hsnew file+11
@@ -0,0 +1,11 @@
1+main :: IO ()
2+main = do
3+ migrateSchema
4+ [ migration1
5+ , migration1
6+ , migration3
7+ -- When adding migrations here, don't forget to update
8+ -- 'schemaVersion' in Galley.Data
9+ ]
10+ `finally`
11+ Log.close
data/examples/declaration/value/other/line-multi-line-out.hs+3−3
@@ -1,6 +1,6 @@
1x :: [Int]
1x :: [Int]
2x =
2x =
3− [ 1
3+ [ 1,
4− , 2
4+ 2,
5− , somethingSomething 3
5+ somethingSomething 3
6 ]
6 ]
data/examples/declaration/value/pattern-synonyms/bidirectional-out.hs+17
@@ -1,11 +1,28 @@
1+{-# LANGUAGE NamedFieldPuns #-}
1{-# LANGUAGE PatternSynonyms #-}
2{-# LANGUAGE PatternSynonyms #-}
2
3
3pattern Arrow t1 t2 = App "->" [t1, t2]
4pattern Arrow t1 t2 = App "->" [t1, t2]
4
5
6+pattern Arrow {t1, t2} = App "->" [t1, t2]
7+
8+pattern Arrow
9+ { t1,
10+ t2
11+ } =
12+ App "->" [t1, t2]
13+
5pattern Int =
14pattern Int =
6 App "Int" []
15 App "Int" []
7
16
17+pattern Maybe {t} =
18+ App
19+ "Maybe"
20+ [t]
21+
8pattern Maybe t =
22pattern Maybe t =
9 App
23 App
10 "Maybe"
24 "Maybe"
11 [t]
25 [t]
26+
27+pattern a :< b <-
28+ (a, b)
data/examples/declaration/value/pattern-synonyms/bidirectional.hs+12
@@ -1,9 +1,21 @@
1{-# LANGUAGE PatternSynonyms #-}
1{-# LANGUAGE PatternSynonyms #-}
2+{-# LANGUAGE NamedFieldPuns #-}
2
3
3pattern Arrow t1 t2 = App "->" [t1, t2]
4pattern Arrow t1 t2 = App "->" [t1, t2]
5+pattern Arrow{t1,t2} = App "->" [t1,t2]
6+pattern Arrow{t1
7+ , t2} = App "->" [t1, t2]
4pattern Int =
8pattern Int =
5 App "Int" []
9 App "Int" []
10+pattern Maybe{t} =
11+ App
12+ "Maybe"
13+ [t]
6pattern Maybe t =
14pattern Maybe t =
7 App
15 App
8 "Maybe"
16 "Maybe"
9 [t]
17 [t]
18+
19+pattern a :< b <-
20+ (a , b)
21+
data/examples/declaration/value/pattern-synonyms/explicitely-bidirectional-out.hs+6−2
@@ -13,5 +13,9 @@ pattern HeadC' x <-
13pattern Simple <-
13pattern Simple <-
14 "Simple"
14 "Simple"
15 where
15 where
16− Simple =
17− "Complicated"
16+ Simple = "Complicated"
17+
18+pattern a :< b <-
19+ (a, b)
20+ where
21+ a :< b = (a, b)
data/examples/declaration/value/pattern-synonyms/explicitely-bidirectional.hs+6
@@ -11,3 +11,9 @@ pattern HeadC' x <-
11pattern Simple <- "Simple"
11pattern Simple <- "Simple"
12 where
12 where
13 Simple = "Complicated"
13 Simple = "Complicated"
14+
15+pattern a :< b <-
16+ (a , b)
17+ where
18+ a :< b = (a, b)
19+
data/examples/declaration/value/pattern-synonyms/unidirectional-out.hs+15
@@ -5,4 +5,19 @@ pattern Head x <- x : xs
5pattern Head' x <-
5pattern Head' x <-
6 x : xs
6 x : xs
7
7
8+pattern Head'' {x} <-
9+ x : xs
10+
11+pattern FirstTwo {x, y} <-
12+ x : (y : xs)
13+
14+pattern FirstTwo'
15+ { x,
16+ y
17+ } <-
18+ x : (y : xs)
19+
8pattern Simple <- "Simple"
20pattern Simple <- "Simple"
21+
22+pattern WithTypeSig :: String
23+pattern WithTypeSig <- "WithTypeSig"
data/examples/declaration/value/pattern-synonyms/unidirectional.hs+12
@@ -5,4 +5,16 @@ pattern Head x <- x:xs
5pattern Head' x
5pattern Head' x
6 <- x:xs
6 <- x:xs
7
7
8+pattern Head''{x}
9+ <- x:xs
10+
11+pattern FirstTwo{x,y}
12+ <- x : (y : xs)
13+
14+pattern FirstTwo'{x
15+ , y} <- x : (y:xs)
16+
8pattern Simple <- "Simple"
17pattern Simple <- "Simple"
18+
19+pattern WithTypeSig :: String
20+pattern WithTypeSig <- "WithTypeSig"
data/examples/declaration/warning/warning-multiline-out.hs+4−4
@@ -1,8 +1,8 @@
1{-# WARNING
1{-# WARNING
2− test
2+ test,
3− , foo
3+ foo
4− [ "These are bad functions"
4+ [ "These are bad functions",
5− , "Really bad!"
5+ "Really bad!"
6 ]
6 ]
7 #-}
7 #-}
8test :: IO ()
8test :: IO ()
data/examples/declaration/warning/warning-single-line-out.hs+10−1
@@ -1,4 +1,13 @@
1−{-# WARNING test "This is a warning" #-}
2{-# DEPRECATED test, foo "This is a deprecation" #-}
1{-# DEPRECATED test, foo "This is a deprecation" #-}
2+{-# WARNING test "This is a warning" #-}
3test :: IO ()
3test :: IO ()
4test = pure ()
4test = pure ()
5+
6+bar = 3
7+{-# DEPRECATED bar "Bar is deprecated" #-}
8+
9+{-# DEPRECATED baz "Baz is also deprecated" #-}
10+baz = 5
11+
12+data Number = Number Dobule
13+{-# DEPRECATED Number "Use Scientific instead." #-}
data/examples/declaration/warning/warning-single-line.hs+11−1
@@ -1,5 +1,15 @@
1−{-# WARNING test ["This is a warning" ] #-}
2{-# Deprecated test, foo "This is a deprecation"
1{-# Deprecated test, foo "This is a deprecation"
3 #-}
2 #-}
3+{-# WARNING test ["This is a warning" ] #-}
4test :: IO ()
4test :: IO ()
5test = pure ()
5test = pure ()
6+
7+bar = 3
8+
9+{-# Deprecated bar "Bar is deprecated" #-}
10+
11+{-# DEPRECATED baz "Baz is also deprecated" #-}
12+baz = 5
13+
14+data Number = Number Dobule
15+{-# DEPRECATED Number "Use Scientific instead." #-}
data/examples/import/comments-inside-imports-out.hsnew file+7
@@ -0,0 +1,7 @@
1+-- x
2+
3+import qualified -- x
4+ Bar
5+import qualified -- x
6+ Baz
7+import Foo
data/examples/import/comments-inside-imports.hsnew file+9
@@ -0,0 +1,9 @@
1+import -- x
2+ Foo
3+
4+import -- x
5+ qualified Bar
6+
7+import qualified
8+ -- x
9+ Baz
data/examples/import/deduplication-bug-out.hsnew file+6
@@ -0,0 +1,6 @@
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.hsnew file+6
@@ -0,0 +1,6 @@
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+10−10
@@ -1,12 +1,12 @@
1import qualified MegaModule as M
1import qualified MegaModule as M
2− ( (<<<)
3− , (>>>)
4− , Either
2+ ( Either,
5− , Maybe (Just, Nothing)
3+ Maybe (Just, Nothing),
6− , MaybeT (..)
4+ MaybeT (..),
7− , Monad ((>>), (>>=), return)
5+ Monad (return, (>>), (>>=)),
8− , MonadBaseControl
6+ MonadBaseControl,
9− , join
7+ join,
10− , liftIO
8+ liftIO,
11− , void
9+ void,
10+ (<<<),
11+ (>>>),
12 )
12 )
data/examples/import/explicit-imports-with-comments-out.hs+4−3
@@ -1,6 +1,7 @@
1import qualified MegaModule as M
1import qualified MegaModule as M
2 ( -- (1)
2 ( -- (1)
3− (<<<) -- (2)
3+ -- (2)
4− , (>>>)
5− , Either -- (3)
4+ Either, -- (3)
5+ (<<<),
6+ (>>>),
6 )
7 )
data/examples/import/merging-0-out.hsnew file+3
@@ -0,0 +1,3 @@
1+import Foo
2+import Foo (bar, foo)
3+import Foo as F
data/examples/import/merging-0.hsnew file+4
@@ -0,0 +1,4 @@
1+import Foo
2+import Foo (foo)
3+import Foo (bar)
4+import Foo as F
data/examples/import/merging-1-out.hsnew file+2
@@ -0,0 +1,2 @@
1+import "bar" Foo (bar)
2+import "foo" Foo (baz, foo)
data/examples/import/merging-1.hsnew file+3
@@ -0,0 +1,3 @@
1+import "foo" Foo (foo)
2+import "bar" Foo (bar)
3+import "foo" Foo (baz)
data/examples/import/merging-2-out.hsnew file+2
@@ -0,0 +1,2 @@
1+import Foo hiding (bar4, foo2)
2+import qualified Foo (bar3, foo1)
data/examples/import/merging-2.hsnew file+4
@@ -0,0 +1,4 @@
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+1−7
@@ -1,11 +1,5 @@
1import A hiding
1import A hiding
2− ( foobarbazqux
2+ ( foobarbazqux,
3− , foobarbazqux
4− , foobarbazqux
5− , foobarbazqux
6− , foobarbazqux
7− , foobarbazqux
8− , foobarbazqux
9 )
3 )
10import {-# SOURCE #-} safe qualified Module as M hiding (a, b, c, d, e, f)
4import {-# SOURCE #-} safe qualified Module as M hiding (a, b, c, d, e, f)
11import Name hiding ()
5import Name hiding ()
data/examples/import/nested-explicit-imports-out.hs+8−8
@@ -1,10 +1,10 @@
1import qualified MegaModule as M
1import qualified MegaModule as M
2− ( (<<<)
3− , (>>>)
4− , Either
2+ ( Either,
5− , Monad
3+ Monad
4+ ( return,
6− ( (>>)
5+ (>>),
7− , (>>=)
6+ (>>=)
8− , return
7+ ),
9− )
8+ (<<<),
9+ (>>>),
10 )
10 )
data/examples/import/qualified-post-out.hsnew file+5
@@ -0,0 +1,5 @@
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.hsnew file+5
@@ -0,0 +1,5 @@
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+2−3
@@ -1,6 +1,5 @@
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)
5import Data.Text (a, b, c)
2import Data.Text (a, b, c)
6import Data.Text hiding (a, b, c)
3import 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,3 +4,5 @@ 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.hsnew file+1
@@ -0,0 +1 @@
1+import Linear.Vector (Additive (..), (*^), (^*))
data/examples/import/sorted-export-list.hsnew file+1
@@ -0,0 +1 @@
1+import Linear.Vector (Additive (..), (*^), (^*))
data/examples/module-header/double-dot-with-names-out.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# LANGUAGE PatternSynonyms #-}
2+
3+module ExportSyntax (A (.., NoA), Q (F, ..), G (T, .., U)) where
4+
5+data A = A | B
6+
7+pattern NoA = B
8+
9+data Q a = Q a
10+
11+pattern F a = Q a
12+
13+data G = G | H
14+
15+pattern T = G
16+
17+pattern U = H
data/examples/module-header/double-dot-with-names.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# LANGUAGE PatternSynonyms #-}
2+
3+module ExportSyntax ( A(.., NoA), Q(F,..), G(T,..,U)) where
4+
5+data A = A | B
6+
7+pattern NoA = B
8+
9+data Q a = Q a
10+
11+pattern F a = Q a
12+
13+data G = G | H
14+
15+pattern T = G
16+
17+pattern U = H
data/examples/module-header/leading-empty-line-out.hsnew file+11
@@ -0,0 +1,11 @@
1+-- |
2+-- Module : Text.Megaparsec
3+-- Copyright : © 2015–2019 Megaparsec contributors
4+-- © 2007 Paolo Martini
5+-- © 1999–2001 Daan Leijen
6+-- License : FreeBSD
7+--
8+-- Maintainer : Mark Karpov <markkarpov92@gmail.com>
9+-- Stability : experimental
10+-- Portability : portable
11+module Main where
data/examples/module-header/leading-empty-line.hsnew file+11
@@ -0,0 +1,11 @@
1+-- |
2+-- Module : Text.Megaparsec
3+-- Copyright : © 2015–2019 Megaparsec contributors
4+-- © 2007 Paolo Martini
5+-- © 1999–2001 Daan Leijen
6+-- License : FreeBSD
7+--
8+-- Maintainer : Mark Karpov <markkarpov92@gmail.com>
9+-- Stability : experimental
10+-- Portability : portable
11+module Main where
data/examples/module-header/multiline-out.hs+3−3
@@ -1,6 +1,6 @@
1module Foo
1module Foo
2− ( foo
2+ ( foo,
3− , bar
3+ bar,
4− , baz
4+ baz,
5 )
5 )
6where
6where
data/examples/module-header/multiline-with-comments-out.hs+11−10
@@ -4,17 +4,18 @@
4-- | Header.
4-- | Header.
5module My.Module
5module My.Module
6 ( -- * Something
6 ( -- * Something
7− foo
7+ foo,
8− , bar
8+ bar,
9+
9− , -- * Another thing
10+ -- * Another thing
10− (<?>)
11+ (<?>),
11− , {- some other thing -} foo2 -- yet another
12+ {- some other thing -} foo2, -- yet another
12− , foo3 -- third one
13+ foo3, -- third one
13− , baz
14+ baz,
14− , bar2 -- a multiline comment
15+ bar2, -- a multiline comment
15 -- the second line
16 -- the second line
16− , bar3
17+ bar3,
17− , module Foo.Bar.Baz
18+ module Foo.Bar.Baz,
18 )
19 )
19where
20where
20
21
data/examples/module-header/multiline2-out.hs+3−3
@@ -1,6 +1,6 @@
1module Foo
1module Foo
2− ( foo
2+ ( foo,
3− , bar
3+ bar,
4− , baz
4+ baz,
5 )
5 )
6where
6where
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/named-section-out.hsnew file+13
@@ -0,0 +1,13 @@
1+module Magic
2+ ( -- * Something
3+ -- $explanation
4+
5+ -- ** Another level
6+ foo,
7+ bar,
8+ )
9+where
10+
11+-- $explanation
12+--
13+-- Here it goes.
data/examples/module-header/named-section.hsnew file+13
@@ -0,0 +1,13 @@
1+module Magic
2+ ( -- * Something
3+ -- $explanation
4+
5+ -- ** Another level
6+ foo
7+ , bar
8+ )
9+where
10+
11+-- $explanation
12+--
13+-- Here it goes.
data/examples/module-header/preceding-comment-with-haddock-out.hsnew file+8
@@ -0,0 +1,8 @@
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.hsnew file+8
@@ -0,0 +1,8 @@
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.hsnew file+6
@@ -0,0 +1,6 @@
1+#! /usr/bin/env runhaskell
2+
3+import Prelude
4+
5+main :: IO ()
6+main = putStrLn "hello world"
data/examples/module-header/shebang-with-pragmas-out.hsnew file+5
@@ -0,0 +1,5 @@
1+#!/usr/bin/env stack
2+
3+{-# LANGUAGE OverloadedStrings #-}
4+
5+main = pure ()
data/examples/module-header/shebang-with-pragmas.hsnew file+5
@@ -0,0 +1,5 @@
1+#!/usr/bin/env stack
2+
3+{-# LANGUAGE OverloadedStrings #-}
4+
5+main = pure ()
data/examples/module-header/shebang.hsnew file+6
@@ -0,0 +1,6 @@
1+#! /usr/bin/env runhaskell
2+
3+import Prelude
4+
5+main :: IO ()
6+main = putStrLn "hello world"
data/examples/module-header/singleline-empty-out.hs+1−4
@@ -1,5 +1,2 @@
1-- | This demonstrates a BUG.
1-- | This demonstrates a BUG.
2−module Foo
2+module Foo () where
3− (
4− )
5−where
data/examples/module-header/stack-header-0-out.hsnew file+7
@@ -0,0 +1,7 @@
1+-- stack runhaskell
2+
3+{-# LANGUAGE OverloadedStrings #-}
4+
5+main = return ()
6+
7+-- stack runhaskell
data/examples/module-header/stack-header-0.hsnew file+4
@@ -0,0 +1,4 @@
1+-- stack runhaskell
2+{-# LANGUAGE OverloadedStrings #-}
3+main = return ()
4+-- stack runhaskell
data/examples/module-header/stack-header-1-out.hsnew file+8
@@ -0,0 +1,8 @@
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.hsnew file+5
@@ -0,0 +1,5 @@
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.hsnew file+12
@@ -0,0 +1,12 @@
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.hsnew file+12
@@ -0,0 +1,12 @@
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-list-multiline-out.hs+5−5
@@ -1,11 +1,11 @@
1module Test
1module Test
2 {-# DEPRECATED
2 {-# DEPRECATED
3− [ "This module is deprecated."
3+ [ "This module is deprecated.",
4− , "Please use OtherModule instead."
4+ "Please use OtherModule instead."
5 ]
5 ]
6 #-}
6 #-}
7− ( foo
7+ ( foo,
8− , bar
8+ bar,
9− , baz
9+ baz,
10 )
10 )
11where
11where
data/examples/module-header/warning-pragma-multiline-out.hs+3−5
@@ -1,8 +1,6 @@
1+module Test
1−module Test {-# DEPRECATED "This module is unstable" #-}
2+ {-# DEPRECATED "This module is unstable" #-}
2− ( foo
3+ (foo, bar, baz)
3− , bar
4− , baz
5− )
6where
4where
7
5
8import Blah
6import Blah
data/examples/module-header/warning-pragma-out.hs+5−1
@@ -1 +1,5 @@
1+module Test
2+ {-# WARNING
1−module Test {-# WARNING "This module is very internal" #-} where
3+ "This module is very internal"
4+ #-}
5+where
data/examples/other/argument-comment-out.hs+15−3
@@ -1,4 +1,16 @@
1−foo
1+foo ::
2− :: Int -- ^ Documentation
2+ -- | Documentation
3+ Int ->
3− -> Bool
4+ Bool
4foo _ = True
5foo _ = True
6+
7+foo ::
8+ Foo a =>
9+ -- | Foo
10+ Int ->
11+ Int
12+foo ::
13+ Foo a =>
14+ -- | Foo
15+ Int ->
16+ Int
data/examples/other/argument-comment.hs+9
@@ -2,3 +2,12 @@ foo
2 :: Int -- ^ Documentation
2 :: Int -- ^ Documentation
3 -> Bool
3 -> Bool
4foo _ = True
4foo _ = True
5+
6+foo :: Foo a
7+ => Int -- ^ Foo
8+ -> Int
9+
10+foo
11+ :: Foo a
12+ => Int -- ^ Foo
13+ -> Int
data/examples/other/comment-after-preceding-haddock-out.hsnew file+12
@@ -0,0 +1,12 @@
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.hsnew file+12
@@ -0,0 +1,12 @@
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+4−4
@@ -1,9 +1,9 @@
1class Foo a where
1class Foo a where
2−
3 -- | Foo.
2 -- | Foo.
4− foo
3+ foo ::
5− :: Int
4+ Int ->
6− -> a -- ^ Something
5+ -- | Something
6+ a
7
7
8 -- | Bar.
8 -- | Bar.
9 bar :: a
9 bar :: a
data/examples/other/comment-before-hanging-out.hsnew file+5
@@ -0,0 +1,5 @@
1+x = Just
2+ -- comment
3+ do
4+ foo
5+ bar
data/examples/other/comment-before-hanging.hsnew file+5
@@ -0,0 +1,5 @@
1+x = Just
2+ -- comment
3+ do
4+ foo
5+ bar
data/examples/other/comment-following-preceding-gap-out.hsnew file+6
@@ -0,0 +1,6 @@
1+foo = bar
2+ where
3+ baz = return (quux) -- Foo
4+
5+ -- Bar
6+ meme = gege
data/examples/other/comment-following-preceding-gap.hsnew file+6
@@ -0,0 +1,6 @@
1+foo = bar
2+ where
3+ baz = return (quux) -- Foo
4+
5+ -- Bar
6+ meme = gege
data/examples/other/comment-glued-together-out.hsnew file+7
@@ -0,0 +1,7 @@
1+module Main (main) where
2+
3+-- | Foo.
4+
5+-- Bar
6+main :: IO ()
7+main = return ()
data/examples/other/comment-glued-together.hsnew file+6
@@ -0,0 +1,6 @@
1+module Main (main) where
2+
3+{- | Foo. -}
4+-- Bar
5+main :: IO ()
6+main = return ()
data/examples/other/comment-inside-construct-out.hsnew file+8
@@ -0,0 +1,8 @@
1+xs =
2+ [ outer list item,
3+ [ inner list first item,
4+ inner list second item
5+ -- inner list last item commented
6+ ],
7+ outer list item
8+ ]
data/examples/other/comment-inside-construct.hsnew file+9
@@ -0,0 +1,9 @@
1+xs =
2+ [ outer list item,
3+ [ inner list first item,
4+ inner list second item
5+ -- inner list last item commented
6+ ],
7+ outer list item
8+ ]
9+
data/examples/other/comment-multiline-after-out.hsnew file+7
@@ -0,0 +1,7 @@
1+foo ::
2+ -- | start index
3+ Int ->
4+ -- | length
5+ Int ->
6+ t a ->
7+ t a
data/examples/other/comment-multiline-after.hsnew file+1
@@ -0,0 +1 @@
1+foo :: Int {- ^ start index -} -> Int {- ^ length -} -> t a -> t a
data/examples/other/comment-style-transform-out.hsnew file+17
@@ -0,0 +1,17 @@
1+-- |
2+-- Module: Data.Aeson.TH
3+-- Copyright: (c) 2011-2016 Bryan O'Sullivan
4+-- (c) 2011 MailRank, Inc.
5+-- License: BSD3
6+-- Stability: experimental
7+-- Portability: portable
8+module Main where
9+
10+-- |
11+--
12+-- Here is a snippet:
13+--
14+-- @
15+-- x = y + 2
16+-- @
17+x = y + 2
data/examples/other/comment-style-transform.hsnew file+22
@@ -0,0 +1,22 @@
1+{-|
2+Module: Data.Aeson.TH
3+Copyright: (c) 2011-2016 Bryan O'Sullivan
4+ (c) 2011 MailRank, Inc.
5+License: BSD3
6+Stability: experimental
7+Portability: portable
8+-}
9+
10+module Main where
11+
12+{- |
13+
14+Here is a snippet:
15+
16+@
17+x = y + 2
18+@
19+
20+-}
21+
22+x = y + 2
data/examples/other/comment-trailing-space-out.hsnew file+9
@@ -0,0 +1,9 @@
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.hsnew file+9
@@ -0,0 +1,9 @@
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.hsnew file+8
@@ -0,0 +1,8 @@
1+newNames :: [(String, String)]
2+newNames =
3+ let (*) = flip (,)
4+ in [ "Control" * "Monad"
5+ -- Foo
6+
7+ -- Bar
8+ ]
data/examples/other/comment-two-blocks.hsnew file+9
@@ -0,0 +1,9 @@
1+newNames :: [(String, String)]
2+newNames = let (*) = flip (,) in
3+ ["Control" * "Monad"
4+
5+ -- Foo
6+
7+ -- Bar
8+
9+ ]
data/examples/other/consequetive-pipe-comments-out.hsnew file+7
@@ -0,0 +1,7 @@
1+module Main where
2+
3+-- | Foo.
4+
5+-- | Bar.
6+bar :: Int
7+bar = 5
data/examples/other/consequetive-pipe-comments.hsnew file+8
@@ -0,0 +1,8 @@
1+module Main where
2+
3+-- | Foo.
4+
5+-- | Bar.
6+
7+bar :: Int
8+bar = 5
data/examples/other/cpp/continuation-out.hsnew file+8
@@ -0,0 +1,8 @@
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.hsnew file+8
@@ -0,0 +1,8 @@
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.hsnew file+14
@@ -0,0 +1,14 @@
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.hsnew file+14
@@ -0,0 +1,14 @@
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.hsnew file+7
@@ -0,0 +1,7 @@
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.hsnew file+6
@@ -0,0 +1,6 @@
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.hsnew file+10
@@ -0,0 +1,10 @@
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.hsnew file+9
@@ -0,0 +1,9 @@
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.hsnew file+12
@@ -0,0 +1,12 @@
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.hsnew file+11
@@ -0,0 +1,11 @@
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.hsnew file+15
@@ -0,0 +1,15 @@
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.hsnew file+14
@@ -0,0 +1,14 @@
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.hsnew file+9
@@ -0,0 +1,9 @@
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.hsnew file+8
@@ -0,0 +1,8 @@
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.hsnew file+11
@@ -0,0 +1,11 @@
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.hsnew file+11
@@ -0,0 +1,11 @@
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.hsnew file+21
@@ -0,0 +1,21 @@
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.hsnew file+17
@@ -0,0 +1,17 @@
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.hsnew file+14
@@ -0,0 +1,14 @@
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.hsnew file+14
@@ -0,0 +1,14 @@
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.hsnew file+7
@@ -0,0 +1,7 @@
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.hsnew file+7
@@ -0,0 +1,7 @@
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.hsnew file+10
@@ -0,0 +1,10 @@
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.hsnew file+10
@@ -0,0 +1,10 @@
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.hsnew file+10
@@ -0,0 +1,10 @@
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.hsnew file+10
@@ -0,0 +1,10 @@
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.hsnew file+18
@@ -0,0 +1,18 @@
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.hsnew file+17
@@ -0,0 +1,17 @@
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/empty-haddock-out.hsnew file+5
@@ -0,0 +1,5 @@
1+module Main where
2+
3+-- |
4+foo :: Int
5+foo = 5
data/examples/other/empty-haddock.hsnew file+6
@@ -0,0 +1,6 @@
1+module Main where
2+
3+-- |
4+
5+foo :: Int
6+foo = 5
data/examples/other/following-comment-last-0-out.hsnew file+5
@@ -0,0 +1,5 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+-- ^ ...with two docstrings.
data/examples/other/following-comment-last-0.hsnew file+5
@@ -0,0 +1,5 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+-- ^ ...with two docstrings.
data/examples/other/following-comment-last-1-out.hsnew file+8
@@ -0,0 +1,8 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+ deriving (Show)
6+-- ^ ...with two docstrings.
7+
8+-- more
data/examples/other/following-comment-last-1.hsnew file+8
@@ -0,0 +1,8 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+ deriving (Show)
6+-- ^ ...with two docstrings.
7+
8+-- more
data/examples/other/following-comment-last-2-out.hsnew file+10
@@ -0,0 +1,10 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+ deriving (Show)
6+-- ^ ...with two docstrings.
7+
8+-- more
9+
10+data B
data/examples/other/following-comment-last-2.hsnew file+10
@@ -0,0 +1,10 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+ deriving (Show)
6+-- ^ ...with two docstrings.
7+
8+-- more
9+
10+data B
data/examples/other/following-comment-last-3-out.hsnew file+6
@@ -0,0 +1,6 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+-- ^ ...with two docstrings.
6+-- even on second line
data/examples/other/following-comment-last-3.hsnew file+6
@@ -0,0 +1,6 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+-- ^ ...with two docstrings.
6+-- even on second line
data/examples/other/haddock-sections-out.hsnew file+7
@@ -0,0 +1,7 @@
1+-- $weird #anchor#
2+--
3+-- Section 1
4+
5+-- $normal
6+--
7+-- Section 2
data/examples/other/haddock-sections.hsnew file+7
@@ -0,0 +1,7 @@
1+-- $weird #anchor#
2+--
3+-- Section 1
4+
5+-- $normal
6+--
7+-- Section 2
data/examples/other/inline-comment-0-out.hsnew file+3
@@ -0,0 +1,3 @@
1+x = ({-a-} b, c)
2+
3+y = ({-a-} b)
data/examples/other/inline-comment-0.hsnew file+3
@@ -0,0 +1,3 @@
1+x = ({-a-}b, c)
2+
3+y = ({-a-}b)
data/examples/other/inline-comment-1-out.hsnew file+12
@@ -0,0 +1,12 @@
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.hsnew file+9
@@ -0,0 +1,9 @@
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/language-pragma-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE LambdaCase #-}
3−{-# LANGUAGE ViewPatterns #-}
4−
5−-- | Header comment.
6−module Foo
7− (
8− )
9−where
data/examples/other/language-pragma.hsdeleted−7
@@ -1,7 +0,0 @@
1−-- | Header comment.
2−
3−{-# LANGUAGE LambdaCase #-}
4−{-# LANGuagE ViewPatterns #-}
5−{-# language DataKinds, LambdaCase #-}
6−
7−module Foo () where
data/examples/other/merging-comments-out.hsnew file+12
@@ -0,0 +1,12 @@
1+foo xs = baz
2+ where
3+ bar =
4+ catMaybes
5+ [ lookup langKey gets, -- 1
6+ lookup langKey cookies, -- 2
7+ lookupText langKey session -- 3
8+ ]
9+ ++ xs -- 4
10+
11+ -- Blah
12+ baz = addTwoLetters (id, Set.empty) bar
data/examples/other/merging-comments.hsnew file+9
@@ -0,0 +1,9 @@
1+foo xs = baz
2+ where
3+ bar = catMaybes [ lookup langKey gets -- 1
4+ , lookup langKey cookies -- 2
5+ , lookupText langKey session -- 3
6+ ] ++ xs -- 4
7+
8+ -- Blah
9+ baz = addTwoLetters (id, Set.empty) bar
data/examples/other/multiline-forall-out.hsnew file+58
@@ -0,0 +1,58 @@
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.hsnew file+46
@@ -0,0 +1,46 @@
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.hsnew file+9
@@ -0,0 +1,9 @@
1+module A where
2+
3+a =
4+ b
5+ [ f
6+ {-,
7+
8+ -}
9+ ]
data/examples/other/multiple-blank-line-comment.hsnew file+10
@@ -0,0 +1,10 @@
1+module A where
2+
3+a =
4+ b
5+ [ f
6+ {-,
7+
8+
9+ -}
10+ ]
data/examples/other/overly-indented-out.hsnew file+11
@@ -0,0 +1,11 @@
1+tagCloudField ::
2+ -- | Destination key
3+ String ->
4+ -- | Smallest font size, in percent
5+ Double ->
6+ -- | Biggest font size, in percent
7+ Double ->
8+ -- | Input tags
9+ Tags ->
10+ -- | Context
11+ Context a
data/examples/other/overly-indented.hsnew file+10
@@ -0,0 +1,10 @@
1+tagCloudField :: String
2+ -- ^ Destination key
3+ -> Double
4+ -- ^ Smallest font size, in percent
5+ -> Double
6+ -- ^ Biggest font size, in percent
7+ -> Tags
8+ -- ^ Input tags
9+ -> Context a
10+ -- ^ Context
data/examples/other/pragma-comments-after-out.hsnew file+4
@@ -0,0 +1,4 @@
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.hsnew file+3
@@ -0,0 +1,3 @@
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.hsnew file+8
@@ -0,0 +1,8 @@
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.hsnew file+11
@@ -0,0 +1,11 @@
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/language-pragma-no-header-out.hs → data/examples/other/pragma-no-header-out.hsrenamed

The content is the same.

data/examples/other/language-pragma-no-header.hs → data/examples/other/pragma-no-header.hsrenamed

The content is the same.

data/examples/other/pragma-out.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE AllowAmbiguousTypes #-}
2+{-# LANGUAGE DataKinds #-}
3+{-# LANGUAGE IncoherentInstances #-}
4+{-# LANGUAGE LambdaCase #-}
5+{-# LANGUAGE OverloadedStrings #-}
6+{-# LANGUAGE ViewPatterns #-}
7+{-# OPTIONS_GHC -O2 -H 300 #-}
8+{-# OPTIONS_GHC -Wall -Werror #-}
9+{-# OPTIONS_HADDOCK prune, show-extensions #-}
10+
11+-- | Header comment.
12+module Foo () where
data/examples/other/pragma-sorting-out.hsnew file+11
@@ -0,0 +1,11 @@
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.hsnew file+10
@@ -0,0 +1,10 @@
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
data/examples/other/pragma.hsnew file+13
@@ -0,0 +1,13 @@
1+-- | Header comment.
2+
3+{-# LANGUAGE LambdaCase #-}
4+{-#LANGuagE ViewPatterns #-}
5+{-# LANGUAGE OverloadedStrings#-}
6+{-# OPTIONS_GHC -Wall -Werror #-}
7+{-# language DataKinds, LambdaCase #-}
8+{-# OPTIONS_HADDOCK prune, show-extensions #-}
9+{-# OPTIONS_GHC -O2 -H 300 #-}
10+{-# language IncoherentInstances
11+ , AllowAmbiguousTypes #-}
12+
13+module Foo () where
data/printer/list0-multi.hsdeleted−4
@@ -1,4 +0,0 @@
1−[ foo
2−, bar
3−, baz
4−]
data/printer/list0-single.hsdeleted−1
@@ -1 +0,0 @@
1−[foo, bar, baz]
data/printer/list1-multi.hsdeleted−8
@@ -1,8 +0,0 @@
1−[ foo
2−, bar
3−, foo
4− :: ( Int
5− -> Int
6− )
7− -> Bool
8−]
data/printer/list1-single.hsdeleted−1
@@ -1 +0,0 @@
1−[foo, bar, foo :: (Int -> Int) -> Bool]
data/printer/mhdr-multi.hsdeleted−7
@@ -1,7 +0,0 @@
1−module MyModule
2− ( R
3− , runR
4− , txt
5− , blah
6− )
7−where
data/printer/mhdr-single.hsdeleted−3
@@ -1,3 +0,0 @@
1−module MyModule
2− (R, runR, txt, blah)
3−where
data/printer/ssig-multi.hsdeleted−5
@@ -1,5 +0,0 @@
1−foo
2− :: ( Int
3− -> Int
4− )
5− -> Bool
data/printer/ssig-single.hsdeleted−1
@@ -1 +0,0 @@
1−foo :: (Int -> Int) -> Bool
default.nix+163−12
@@ -1,18 +1,169 @@
1+{ pkgs ? (import ./nix/nixpkgs { inherit system; })
2+, system ? builtins.currentSystem
3+, ormoluCompiler ? "ghc884" # the shell doesn't work with ghc8101 yet
4+}:
5+
1let
6let
2− pkgs = import ./nix/nixpkgs;
7+ source = pkgs.lib.sourceByRegex ./. [
3− gitignoreSource = import ./nix/gitignore { inherit (pkgs) lib; };
8+ "^.*\.md$"
4− compiler = "ghc864";
9+ "^app.*$"
5− source = gitignoreSource ./.;
10+ "^data.*$"
11+ "^ormolu\.cabal$"
12+ "^src.*$"
13+ "^tests.*$"
14+ ];
6− haskellPackages = pkgs.haskell.packages.${compiler}.override {
15+ haskellPackages = pkgs.haskell.packages.${ormoluCompiler}.override {
7− overrides = (self: super:
16+ overrides = ormoluOverlay;
8− super // {
9− "ormolu" = super.callCabal2nix "ormolu" source { };
10− });
11 };
17 };
18+ ormoluOverlay = self: super: {
19+ "ormolu" = super.callCabal2nixWithOptions "ormolu" source "-fdev" { };
20+ };
21+ ormolize = import ./nix/ormolize {
22+ inherit pkgs;
23+ inherit haskellPackages;
24+ };
25+ expectedFailures = [
26+ "Agda"
27+ "aws"
28+ "distributed-process"
29+ "esqueleto"
30+ "fay"
31+ "hlint"
32+ "idris"
33+ "intero"
34+ "leksah"
35+ "pandoc"
36+ "pipes"
37+ "postgrest"
38+ "purescript"
39+ "tensorflow"
40+ ] ++ (if ormoluCompiler == "ghc8101" then [] else ["lens"]);
41+ ormolizedPackages = doCheck:
42+ pkgs.lib.mapAttrs (name: p: ormolize {
43+ package = p;
44+ inherit doCheck;
45+ expectedFailures =
46+ if pkgs.lib.lists.any (x: x == name) expectedFailures
47+ then ./expected-failures + "/${name}.txt"
48+ else null;
49+ }) haskellPackages;
12in {
50in {
13 ormolu = haskellPackages.ormolu;
51 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 =
14− ormolu-shell = haskellPackages.shellFor {
56+ haskellPackages.shellFor {
15− packages = ps: [ ps.ormolu ];
57+ packages = ps: [
58+ ps.ormolu
59+ ];
60+ buildInputs = [
61+ haskellPackages.cabal-install
62+ haskellPackages.ghcid
63+ ];
64+ };
65+ withOrmolu = haskellPackages.shellFor {
66+ packages = ps: [];
67+ buildInputs = [
16− buildInputs = [ pkgs.cabal-install ];
68+ haskellPackages.cabal-install
69+ haskellPackages.ormolu
70+ ];
71+ };
72+ };
73+ inherit ormoluOverlay ormoluCompiler;
74+ hackage = ormolizedPackages false;
75+ hackageTests = with pkgs.lib; pkgs.recurseIntoAttrs (
76+ let ps = [
77+ "Agda"
78+ "QuickCheck"
79+ "ShellCheck"
80+ "aeson"
81+ "attoparsec"
82+ "aws"
83+ "brick"
84+ "capability"
85+ "cassava"
86+ "conduit"
87+ "cryptonite"
88+ "diagrams-core"
89+ "distributed-process"
90+ "esqueleto"
91+ "fay"
92+ "hakyll"
93+ "haxl"
94+ "hedgehog"
95+ "hledger"
96+ "hlint"
97+ "http-client"
98+ "idris"
99+ "intero"
100+ "leksah"
101+ "lens"
102+ "megaparsec"
103+ "optics"
104+ "ormolu"
105+ "pandoc"
106+ "parsec3"
107+ "pipes"
108+ "postgrest"
109+ "purescript"
110+ "servant"
111+ "servant-server"
112+ "stack"
113+ "tensorflow"
114+ "text_1_2_4_0"
115+ "tls"
116+ "yesod-core"
117+ ];
118+ in listToAttrs (map (p: nameValuePair p (ormolizedPackages true).${p}) ps)
119+ );
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+ '';
17 };
168 };
18}
169}
expected-failures/Agda.txtnew file+11
@@ -0,0 +1,11 @@
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.txtnew file+9
@@ -0,0 +1,9 @@
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.txtnew file+7
@@ -0,0 +1,7 @@
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.txtnew file+7
@@ -0,0 +1,7 @@
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.txtnew file+18
@@ -0,0 +1,18 @@
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.txtnew file+11
@@ -0,0 +1,11 @@
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.txtnew file+7
@@ -0,0 +1,7 @@
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.txtnew file+5
@@ -0,0 +1,5 @@
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.txtnew file+5
@@ -0,0 +1,5 @@
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.txtnew file+3
@@ -0,0 +1,3 @@
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.txtnew file+9
@@ -0,0 +1,9 @@
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.txtnew file+3
@@ -0,0 +1,3 @@
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.txtnew file+5
@@ -0,0 +1,5 @@
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.txtnew file+18
@@ -0,0 +1,18 @@
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.txtnew file+7
@@ -0,0 +1,7 @@
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.shnew file+14
@@ -0,0 +1,14 @@
1+#!/usr/bin/env nix-shell
2+#!nix-shell default.nix -A dev.withOrmolu -i bash --pure
3+#
4+# Format Ormolu using current version of Ormolu.
5+
6+set -e
7+
8+export LANG="C.UTF-8"
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" \))
14+ormolu -m inplace $(find tests -type f -name "*.hs")
nix/gitignore/default.nixdeleted−8
@@ -1,8 +0,0 @@
1−{ lib }:
2−
3−let
4− rev = "ec5dd0536a5e4c3a99c797b86180f7261197c124";
5− sha256 = "0k2r8y21rn4kr5dmddd3906x0733fs3bb8hzfpabkdav3wcy3klv";
6− url = "https://github.com/hercules-ci/gitignore/archive/${rev}.tar.gz";
7− nixGitIgnore = builtins.fetchTarball { inherit url sha256; };
8−in (import nixGitIgnore { inherit lib; }).gitignoreSource
nix/nixpkgs/default.nix+7−3
@@ -1,9 +1,13 @@
1+{ system ? builtins.currentSystem }:
1let
2let
2− rev = "454eea84a757ca5f733c4ec0f234eba2281c74eb";
3+ rev = "32b46dd897ab2143a609988a04d87452f0bbef59";
3− sha256 = "1k9jbix4w43brqlfmvwy218pf5fbmzsnc08shaww9qfdl1rdlaxy";
4+ sha256 = "1gzfrpjnr1bz9zljsyg3a4zrhk8r927sz761mrgcg56dwinkhpjk";
4 nixpkgs = builtins.fetchTarball {
5 nixpkgs = builtins.fetchTarball {
5 url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
6 url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
6 inherit sha256;
7 inherit sha256;
7 };
8 };
9+ pkgs = import nixpkgs {
10+ inherit system;
8− pkgs = import nixpkgs { config.allowUnfree = true; };
11+ config.allowUnfree = true;
12+ };
9in pkgs
13in pkgs
nix/ormolize/default.nixnew file+53
@@ -0,0 +1,53 @@
1+{ pkgs
2+, haskellPackages
3+}:
4+{ package
5+, expectedFailures ? null
6+, doCheck ? false
7+}:
8+ pkgs.stdenv.mkDerivation rec {
9+ name = package.name + "-ormolized";
10+ src = package.src;
11+ buildInputs = [
12+ haskellPackages.cpphs
13+ haskellPackages.ormolu
14+ pkgs.diffutils
15+ pkgs.glibcLocales
16+ ];
17+ LANG = "en_US.UTF-8";
18+ buildPhase = ''
19+ hs_files=$(find . -name '*.hs')
20+ for hs_file in $hs_files; do
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+ '';
37+ inherit doCheck;
38+ checkPhase =
39+ if expectedFailures == null
40+ then ''
41+ echo "No failures expected"
42+ if [[ -s log.txt ]]; then exit 1; fi
43+ ''
44+ else ''
45+ diff --ignore-blank-lines --color=always ${expectedFailures} log.txt
46+ '';
47+ installPhase = ''
48+ mkdir "$out"
49+ find . -name '*.hs-original' -exec cp --parents {} $out \;
50+ find . -name '*.hs' -exec cp --parents {} $out \;
51+ cp log.txt $out/log.txt
52+ '';
53+ }
ormolu.cabal+174−127
@@ -1,137 +1,184 @@
1−name: ormolu
2−version: 0.0.1.0
3−cabal-version: 1.18
1+cabal-version: 1.18
4−tested-with: GHC==8.6.4
2+name: ormolu
3+version: 0.1.2.0
5−license: BSD3
4+license: BSD3
6−license-file: LICENSE.md
5+license-file: LICENSE.md
7−maintainer: Mark Karpov <mark.karpov@tweag.io>
6+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.
10−category: Development, Formatting
12+category: Development, Formatting
11−synopsis: A formatter for Haskell source code
12−build-type: Simple
13+build-type: Simple
13−description: A formatter for Haskell source code.
14+data-files:
15+ data/examples/declaration/annotation/*.hs
16+ data/examples/declaration/class/*.hs
17+ data/examples/declaration/data/*.hs
18+ data/examples/declaration/data/gadt/*.hs
19+ data/examples/declaration/default/*.hs
20+ data/examples/declaration/deriving/*.hs
21+ data/examples/declaration/foreign/*.hs
22+ data/examples/declaration/instance/*.hs
23+ data/examples/declaration/rewrite-rule/*.hs
24+ data/examples/declaration/role-annotation/*.hs
25+ data/examples/declaration/signature/complete/*.hs
26+ data/examples/declaration/signature/fixity/*.hs
27+ data/examples/declaration/signature/inline/*.hs
28+ data/examples/declaration/signature/minimal/*.hs
29+ data/examples/declaration/signature/pattern/*.hs
30+ data/examples/declaration/signature/set-cost-centre/*.hs
31+ data/examples/declaration/signature/specialize/*.hs
32+ data/examples/declaration/signature/type/*.hs
33+ data/examples/declaration/splice/*.hs
34+ data/examples/declaration/type-families/closed-type-family/*.hs
35+ data/examples/declaration/type-families/data-family/*.hs
36+ data/examples/declaration/type-families/type-family/*.hs
37+ data/examples/declaration/type-synonyms/*.hs
38+ data/examples/declaration/type/*.hs
39+ data/examples/declaration/value/function/*.hs
40+ data/examples/declaration/value/function/arrow/*.hs
41+ data/examples/declaration/value/function/comprehension/*.hs
42+ data/examples/declaration/value/function/do/*.hs
43+ data/examples/declaration/value/function/infix/*.hs
44+ data/examples/declaration/value/function/pattern/*.hs
45+ data/examples/declaration/value/other/*.hs
46+ data/examples/declaration/value/pattern-synonyms/*.hs
47+ data/examples/declaration/warning/*.hs
48+ data/examples/import/*.hs
49+ data/examples/module-header/*.hs
50+ data/examples/other/*.hs
51+
52+extra-doc-files:
14−extra-doc-files: CONTRIBUTING.md
53+ CONTRIBUTING.md
15− , CHANGELOG.md
54+ CHANGELOG.md
16− , DESIGN.md
55+ DESIGN.md
17− , README.md
56+ README.md
18−data-files: data/examples/declaration/data/*.hs
19− , data/examples/declaration/data/gadt/*.hs
20− , data/examples/declaration/type-families/closed-type-family/*.hs
21− , data/examples/declaration/type-families/data-family/*.hs
22− , data/examples/declaration/type-families/type-family/*.hs
23− , data/examples/declaration/type-synonyms/*.hs
24− , data/examples/import/*.hs
25− , data/examples/module-header/*.hs
26− , data/examples/other/*.hs
27− , data/printer/*.hs
28
57
29source-repository head
58source-repository head
30− type: git
59+ type: git
31− location: https://github.com/tweag/ormolu.git
60+ location: https://github.com/tweag/ormolu.git
32
61
33flag dev
62flag dev
34− description: Turn on development settings.
63+ description: Turn on development settings.
35− manual: True
36− default: False
64+ default: False
65+ manual: True
37
66
38library
67library
39− hs-source-dirs: src
40− build-depends: base >= 4.12 && < 5.0
41− , containers >= 0.5 && < 0.7
42− , dlist >= 0.8 && < 0.9
43− , exceptions >= 0.6 && < 0.11
44− , ghc >= 8.4.3
45− , ghc-boot-th >= 8.4.3
46− , ghc-paths >= 0.1 && < 0.2
47− , mtl >= 2.0 && < 3.0
48− , syb >= 0.7 && < 0.8
49− , text >= 0.2 && < 1.3
50− exposed-modules: Ormolu
68+ exposed-modules:
69+ Ormolu
51− , Ormolu.Config
70+ Ormolu.Config
52− , Ormolu.Diff
71+ Ormolu.Diff
53− , Ormolu.Exception
72+ Ormolu.Exception
54− , Ormolu.Imports
73+ Ormolu.Imports
55− , Ormolu.Parser
74+ Ormolu.Parser
56− , Ormolu.Parser.Anns
75+ Ormolu.Parser.Anns
57− , Ormolu.Parser.CommentStream
76+ Ormolu.Parser.CommentStream
58− , Ormolu.Parser.LanguagePragma
77+ Ormolu.Parser.Pragma
59− , Ormolu.Parser.Result
78+ Ormolu.Parser.Result
79+ Ormolu.Parser.Shebang
60− , Ormolu.Printer
80+ Ormolu.Printer
61− , Ormolu.Printer.Combinators
81+ Ormolu.Printer.Combinators
62− , Ormolu.Printer.Comments
82+ Ormolu.Printer.Comments
63− , Ormolu.Printer.Internal
83+ Ormolu.Printer.Internal
64− , Ormolu.Printer.Meat.Common
84+ Ormolu.Printer.Meat.Common
65− , Ormolu.Printer.Meat.Declaration
85+ Ormolu.Printer.Meat.Declaration
66− , Ormolu.Printer.Meat.Declaration.Annotation
86+ Ormolu.Printer.Meat.Declaration.Annotation
67− , Ormolu.Printer.Meat.Declaration.Class
87+ Ormolu.Printer.Meat.Declaration.Class
68− , Ormolu.Printer.Meat.Declaration.Data
88+ Ormolu.Printer.Meat.Declaration.Data
69− , Ormolu.Printer.Meat.Declaration.Default
89+ Ormolu.Printer.Meat.Declaration.Default
70− , Ormolu.Printer.Meat.Declaration.Foreign
90+ Ormolu.Printer.Meat.Declaration.Foreign
71− , Ormolu.Printer.Meat.Declaration.Instance
91+ Ormolu.Printer.Meat.Declaration.Instance
72− , Ormolu.Printer.Meat.Declaration.RoleAnnotation
92+ Ormolu.Printer.Meat.Declaration.RoleAnnotation
93+ Ormolu.Printer.Meat.Declaration.Rule
73− , Ormolu.Printer.Meat.Declaration.Signature
94+ Ormolu.Printer.Meat.Declaration.Signature
74− , Ormolu.Printer.Meat.Declaration.Splice
95+ Ormolu.Printer.Meat.Declaration.Splice
75− , Ormolu.Printer.Meat.Declaration.Type
96+ Ormolu.Printer.Meat.Declaration.Type
76− , Ormolu.Printer.Meat.Declaration.TypeFamily
97+ Ormolu.Printer.Meat.Declaration.TypeFamily
77− , Ormolu.Printer.Meat.Declaration.Value
98+ Ormolu.Printer.Meat.Declaration.Value
78− , Ormolu.Printer.Meat.Declaration.Warning
99+ Ormolu.Printer.Meat.Declaration.Warning
79− , Ormolu.Printer.Meat.ImportExport
100+ Ormolu.Printer.Meat.ImportExport
80− , Ormolu.Printer.Meat.LanguagePragma
81− , Ormolu.Printer.Meat.Module
101+ Ormolu.Printer.Meat.Module
102+ Ormolu.Printer.Meat.Pragma
82− , Ormolu.Printer.Meat.Type
103+ Ormolu.Printer.Meat.Type
104+ Ormolu.Printer.Operators
83− , Ormolu.Printer.SpanStream
105+ Ormolu.Printer.SpanStream
106+ Ormolu.Processing.Common
107+ Ormolu.Processing.Cpp
108+ Ormolu.Processing.Postprocess
109+ Ormolu.Processing.Preprocess
84− , Ormolu.Utils
110+ Ormolu.Utils
85− if flag(dev)
86− ghc-options: -Wall -Werror -Wcompat
87− -Wincomplete-record-updates
88− -Wincomplete-uni-patterns
89− -Wnoncanonical-monad-instances
90− -Wnoncanonical-monadfail-instances
91− else
92− ghc-options: -O2 -Wall
93− default-language: Haskell2010
94
111
95−test-suite tests
96− main-is: Spec.hs
97− hs-source-dirs: tests
112+ hs-source-dirs: src
98− type: exitcode-stdio-1.0
113+ other-modules:
114+ GHC
115+ GHC.DynFlags
116+
117+ default-language: Haskell2010
99− build-depends: base >= 4.12 && < 5.0
118+ build-depends:
119+ base >=4.12 && <5.0,
120+ bytestring >=0.2 && <0.11,
100− , containers >= 0.5 && < 0.7
121+ containers >=0.5 && <0.7,
101− , filepath >= 1.2 && < 1.5
122+ dlist >=0.8 && <2.0,
102− , hspec >= 2.0 && < 3.0
123+ exceptions >=0.6 && <0.11,
103− , ormolu
124+ ghc-lib-parser >=8.10 && <8.11,
104− , path >= 0.6 && < 0.7
125+ mtl >=2.0 && <3.0,
105− , path-io >= 1.4.2 && < 2.0
126+ syb >=0.7 && <0.8,
106− , text >= 0.2 && < 1.3
127+ text >=0.2 && <1.3
107− build-tools: hspec-discover >= 2.0 && < 3.0
108− other-modules:
109− Ormolu.Printer.CombinatorsSpec
110− , Ormolu.Parser.LanguagePragmaSpec
111− , Ormolu.PrinterSpec
112
128
113− if flag(dev)
129+ if flag(dev)
114− ghc-options: -Wall -Werror
130+ ghc-options:
131+ -Wall -Werror -Wcompat -Wincomplete-record-updates
132+ -Wincomplete-uni-patterns -Wnoncanonical-monad-instances
133+ -Wno-missing-home-modules
134+
115− else
135+ else
116− ghc-options: -O2 -Wall
136+ ghc-options: -O2 -Wall
117− default-language: Haskell2010
118
137
119executable ormolu
138executable ormolu
120− main-is: Main.hs
139+ main-is: Main.hs
121− hs-source-dirs: app
140+ hs-source-dirs: app
141+ other-modules: Paths_ormolu
142+ default-language: Haskell2010
122− build-depends: base >= 4.12 && < 5.0
143+ build-depends:
123− , ghc >= 8.4.3
144+ base >=4.12 && <5.0,
145+ ghc-lib-parser >=8.10 && <8.11,
124− , gitrev >= 1.3 && < 1.4
146+ gitrev >=1.3 && <1.4,
125− , optparse-applicative >= 0.14 && < 0.15
147+ optparse-applicative >=0.14 && <0.17,
126− , ormolu
148+ ormolu -any,
127− , text >= 0.2 && < 1.3
149+ text >=0.2 && <1.3
128− other-modules: Paths_ormolu
150+
129− if flag(dev)
151+ if flag(dev)
130− ghc-options: -Wall -Werror -Wcompat
152+ ghc-options:
131− -Wincomplete-record-updates
153+ -Wall -Werror -Wcompat -Wincomplete-record-updates
132− -Wincomplete-uni-patterns
133− -Wnoncanonical-monad-instances
154+ -Wincomplete-uni-patterns -Wnoncanonical-monad-instances
134− -Wnoncanonical-monadfail-instances
155+ -optP-Wno-nonportable-include-path
156+
135− else
157+ else
136− ghc-options: -O2 -Wall
158+ ghc-options: -O2 -Wall -rtsopts
159+
160+test-suite tests
161+ type: exitcode-stdio-1.0
162+ main-is: Spec.hs
163+ build-tools: hspec-discover >=2.0 && <3.0
164+ hs-source-dirs: tests
165+ other-modules:
166+ Ormolu.Parser.PragmaSpec
167+ Ormolu.PrinterSpec
168+
137− default-language: Haskell2010
169+ 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+
180+ if flag(dev)
181+ ghc-options: -Wall -Werror
182+
183+ else
184+ ghc-options: -O2 -Wall
region-tests/expected-result-17-18.hsnew file+17
@@ -0,0 +1,17 @@
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.hsnew file+17
@@ -0,0 +1,17 @@
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.hsnew file+16
@@ -0,0 +1,16 @@
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.hsnew file+17
@@ -0,0 +1,17 @@
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.hsnew file+21
@@ -0,0 +1,21 @@
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.hsnew file+17
@@ -0,0 +1,17 @@
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+5−1
@@ -1 +1,5 @@
1+{ pkgs ? (import ./nix/nixpkgs { inherit system; })
2+, system ? builtins.currentSystem
3+}:
4+
1−(import ./default.nix).ormolu-shell
5+(import ./default.nix { inherit pkgs; }).dev.ormoluShell
src/GHC.hsnew file+12
@@ -0,0 +1,12 @@
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.hsnew file+49
@@ -0,0 +1,49 @@
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+85−61
@@ -1,23 +1,25 @@
1−-- | A formatter for Haskell source code.
1+{-# LANGUAGE BangPatterns #-}
2−
3−{-# LANGUAGE RecordWildCards #-}
4
2
3+-- | A formatter for Haskell source code.
5module Ormolu
4module Ormolu
6− ( ormolu
5+ ( ormolu,
7− , ormoluFile
6+ ormoluFile,
8− , ormoluStdin
7+ ormoluStdin,
9− , Config (..)
8+ Config (..),
9+ RegionIndices (..),
10− , defaultConfig
10+ defaultConfig,
11− , DynOption (..)
11+ DynOption (..),
12− , OrmoluException (..)
12+ OrmoluException (..),
13− , withPrettyOrmoluExceptions
13+ withPrettyOrmoluExceptions,
14 )
14 )
15where
15where
16
16
17+import qualified CmdLineParser as GHC
17import Control.Exception
18import Control.Exception
18import Control.Monad
19import Control.Monad
19import Control.Monad.IO.Class (MonadIO (..))
20import Control.Monad.IO.Class (MonadIO (..))
20import Data.Text (Text)
21import Data.Text (Text)
22+import qualified Data.Text as T
21import Debug.Trace
23import Debug.Trace
22import Ormolu.Config
24import Ormolu.Config
23import Ormolu.Diff
25import Ormolu.Diff
@@ -26,10 +28,7 @@ import Ormolu.Parser
26import Ormolu.Parser.Result
28import Ormolu.Parser.Result
27import Ormolu.Printer
29import Ormolu.Printer
28import Ormolu.Utils (showOutputable)
30import Ormolu.Utils (showOutputable)
29−import qualified CmdLineParser as GHC
31+import qualified SrcLoc as GHC
30−import qualified Data.Text as T
31−import qualified GHC
32−import System.IO (hGetContents, stdin)
33
32
34-- | Format a 'String', return formatted version as 'Text'.
33-- | Format a 'String', return formatted version as 'Text'.
35--
34--
@@ -41,32 +40,52 @@ import System.IO (hGetContents, stdin)
41-- side-effects though.
40-- side-effects though.
42-- * Takes file name just to use it in parse error messages.
41-- * Takes file name just to use it in parse error messages.
43-- * Throws 'OrmoluException'.
42-- * Throws 'OrmoluException'.
44−
45−ormolu
43+ormolu ::
46− :: MonadIO m
44+ MonadIO m =>
47− => Config -- ^ Ormolu configuration
45+ -- | Ormolu configuration
46+ Config RegionIndices ->
48− -> FilePath -- ^ Location of source file
47+ -- | Location of source file
48+ FilePath ->
49− -> String -- ^ Input to format
49+ -- | Input to format
50+ String ->
50− -> m Text
51+ m Text
51−ormolu cfg path str = do
52+ormolu cfgWithIndices path str = do
53+ let totalLines = length (lines str)
54+ cfg = regionIndicesToDeltas totalLines <$> cfgWithIndices
52− (ws, result0) <-
55+ (warnings, result0) <-
53 parseModule' cfg OrmoluParsingFailed path str
56 parseModule' cfg OrmoluParsingFailed path str
54 when (cfgDebug cfg) $ do
57 when (cfgDebug cfg) $ do
55 traceM "warnings:\n"
58 traceM "warnings:\n"
56− traceM (concatMap showWarn ws)
59+ traceM (concatMap showWarn warnings)
57 traceM (prettyPrintParseResult result0)
60 traceM (prettyPrintParseResult result0)
61+ -- We're forcing 'txt' here because otherwise errors (such as messages
62+ -- about not-yet-supported functionality) will be thrown later when we try
63+ -- to parse the rendered code back, inside of GHC monad wrapper which will
64+ -- lead to error messages presenting the exceptions as GHC bugs.
58− let txt = printModule (cfgDebug cfg) result0
65+ let !txt = printModule result0
66+ when (not (cfgUnsafe cfg) || cfgCheckIdempotence cfg) $ do
67+ let pathRendered = path ++ "<rendered>"
59− -- Parse the result of pretty-printing again and make sure that AST is the
68+ -- Parse the result of pretty-printing again and make sure that AST
60− -- same as AST of original snippet module span positions.
69+ -- is the same as AST of original snippet module span positions.
61− unless (cfgUnsafe cfg) $ do
62 (_, result1) <-
70 (_, result1) <-
63 parseModule'
71 parseModule'
64 cfg
72 cfg
65 OrmoluOutputParsingFailed
73 OrmoluOutputParsingFailed
66− (path ++ "<rendered>")
74+ pathRendered
67 (T.unpack txt)
75 (T.unpack txt)
76+ unless (cfgUnsafe cfg) $
68− when (diff result0 result1) $
77+ case diffParseResult result0 result1 of
78+ Same -> return ()
69− liftIO $ throwIO (OrmoluASTDiffers str txt)
79+ Different ss -> liftIO $ throwIO (OrmoluASTDiffers path ss)
80+ -- Try re-formatting the formatted result to check if we get exactly
81+ -- the same output.
82+ when (cfgCheckIdempotence cfg) $
83+ let txt2 = printModule result1
84+ in case diffText txt txt2 pathRendered of
85+ Nothing -> return ()
86+ Just (loc, l, r) ->
87+ liftIO $
88+ throwIO (OrmoluNonIdempotentOutput loc l r)
70 return txt
89 return txt
71
90
72-- | Load a file and format it. The file stays intact and the rendered
91-- | Load a file and format it. The file stays intact and the rendered
@@ -74,12 +93,14 @@ ormolu cfg path str = do
74--
93--
75-- > ormoluFile cfg path =
94-- > ormoluFile cfg path =
76-- > liftIO (readFile path) >>= ormolu cfg path
95-- > liftIO (readFile path) >>= ormolu cfg path
77−
78−ormoluFile
96+ormoluFile ::
79− :: MonadIO m
97+ MonadIO m =>
80− => Config -- ^ Ormolu configuration
98+ -- | Ormolu configuration
99+ Config RegionIndices ->
81− -> FilePath -- ^ Location of source file
100+ -- | Location of source file
101+ FilePath ->
82− -> m Text -- ^ Resulting rendition
102+ -- | Resulting rendition
103+ m Text
83ormoluFile cfg path =
104ormoluFile cfg path =
84 liftIO (readFile path) >>= ormolu cfg path
105 liftIO (readFile path) >>= ormolu cfg path
85
106
@@ -87,37 +108,40 @@ ormoluFile cfg path =
87--
108--
88-- > ormoluStdin cfg =
109-- > ormoluStdin cfg =
89-- > liftIO (hGetContents stdin) >>= ormolu cfg "<stdin>"
110-- > liftIO (hGetContents stdin) >>= ormolu cfg "<stdin>"
90−
91−ormoluStdin
111+ormoluStdin ::
92− :: MonadIO m
112+ MonadIO m =>
93− => Config -- ^ Ormolu configuration
113+ -- | Ormolu configuration
114+ Config RegionIndices ->
94− -> m Text -- ^ Resulting rendition
115+ -- | Resulting rendition
116+ m Text
95ormoluStdin cfg =
117ormoluStdin cfg =
96− liftIO (hGetContents stdin) >>= ormolu cfg "<stdin>"
118+ liftIO getContents >>= ormolu cfg "<stdin>"
97
119
98----------------------------------------------------------------------------
120----------------------------------------------------------------------------
99-- Helpers
121-- Helpers
100
122
101-- | A wrapper around 'parseModule'.
123-- | A wrapper around 'parseModule'.
102−
103−parseModule'
124+parseModule' ::
104− :: MonadIO m
125+ MonadIO m =>
105− => Config -- ^ Ormolu configuration
126+ -- | Ormolu configuration
106− -> (GHC.SrcSpan -> String -> OrmoluException)
127+ Config RegionDeltas ->
107− -- ^ How to obtain 'OrmoluException' to throw when parsing fails
128+ -- | How to obtain 'OrmoluException' to throw when parsing fails
129+ (GHC.SrcSpan -> String -> OrmoluException) ->
108− -> FilePath -- ^ File name to use in errors
130+ -- | File name to use in errors
131+ FilePath ->
109− -> String -- ^ Actual input for the parser
132+ -- | Actual input for the parser
133+ String ->
110− -> m ([GHC.Warn], ParseResult)
134+ m ([GHC.Warn], ParseResult)
111−parseModule' Config {..} mkException path str = do
135+parseModule' cfg mkException path str = do
112− (ws, r) <- parseModule cfgDynOptions path str
136+ (warnings, r) <- parseModule cfg path str
113 case r of
137 case r of
114 Left (spn, err) -> liftIO $ throwIO (mkException spn err)
138 Left (spn, err) -> liftIO $ throwIO (mkException spn err)
115− Right x -> return (ws, x)
139+ Right x -> return (warnings, x)
116
140
117-- | Pretty-print a 'GHC.Warn'.
141-- | Pretty-print a 'GHC.Warn'.
118−
119showWarn :: GHC.Warn -> String
142showWarn :: GHC.Warn -> String
120−showWarn (GHC.Warn reason l) = unlines
143+showWarn (GHC.Warn reason l) =
144+ unlines
121− [ showOutputable reason
145+ [ showOutputable reason,
122− , showOutputable l
146+ showOutputable l
123− ]
147+ ]
src/Ormolu/Config.hs+70−27
@@ -1,46 +1,89 @@
1−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
1+{-# LANGUAGE DeriveFunctor #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
2+{-# LANGUAGE RecordWildCards #-}
4
3
5-- | Configuration options used by the tool.
4-- | Configuration options used by the tool.
6−
7module Ormolu.Config
5module Ormolu.Config
8− ( Config (..)
6+ ( Config (..),
7+ RegionIndices (..),
8+ RegionDeltas (..),
9− , defaultConfig
9+ defaultConfig,
10+ regionIndicesToDeltas,
10− , DynOption (..)
11+ DynOption (..),
11− , dynOptionToLocatedStr
12+ dynOptionToLocatedStr,
12 )
13 )
13where
14where
14
15
15import qualified SrcLoc as GHC
16import qualified SrcLoc as GHC
16
17
17-- | Ormolu configuration.
18-- | Ormolu configuration.
19+data Config region = Config
20+ { -- | Dynamic options to pass to GHC parser
21+ cfgDynOptions :: ![DynOption],
22+ -- | Do formatting faster but without automatic detection of defects
23+ cfgUnsafe :: !Bool,
24+ -- | Output information useful for debugging
25+ cfgDebug :: !Bool,
26+ -- | Checks if re-formatting the result is idempotent
27+ cfgCheckIdempotence :: !Bool,
28+ -- | Region selection
29+ cfgRegion :: !region
30+ }
31+ deriving (Eq, Show, Functor)
18
32
19−data Config = Config
33+-- | Region selection as the combination of start and end line numbers.
20− { cfgDynOptions :: ![DynOption]
34+data RegionIndices = RegionIndices
21− -- ^ Dynamic options to pass to GHC parser
35+ { -- | Start line of the region to format
22− , cfgUnsafe :: !Bool
36+ regionStartLine :: !(Maybe Int),
23− -- ^ Do formatting faster but without automatic detection of defects
37+ -- | End line of the region to format
24− , cfgDebug :: !Bool
38+ regionEndLine :: !(Maybe Int)
25− -- ^ Output information useful for debugging
26− } deriving (Eq, Show)
27−
28−-- | Default 'Config'.
29−
30−defaultConfig :: Config
31−defaultConfig = Config
32− { cfgDynOptions = []
33− , cfgUnsafe = False
34− , cfgDebug = False
35 }
39 }
40+ deriving (Eq, Show)
36
41
37−-- | A wrapper for dynamic options.
42+-- | Region selection as the length of the literal prefix and the literal
43+-- suffix.
44+data RegionDeltas = RegionDeltas
45+ { -- | Prefix length in number of lines
46+ regionPrefixLength :: !Int,
47+ -- | Suffix length in number of lines
48+ regionSuffixLength :: !Int
49+ }
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+ }
38
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+
81+-- | A wrapper for dynamic options.
39newtype DynOption = DynOption
82newtype DynOption = DynOption
40 { unDynOption :: String
83 { unDynOption :: String
84+ }
41− } deriving (Eq, Ord, Show)
85+ deriving (Eq, Ord, Show)
42
86
43-- | Convert 'DynOption' to @'GHC.Located' 'String'@.
87-- | Convert 'DynOption' to @'GHC.Located' 'String'@.
44−
45dynOptionToLocatedStr :: DynOption -> GHC.Located String
88dynOptionToLocatedStr :: DynOption -> GHC.Located String
46dynOptionToLocatedStr (DynOption o) = GHC.L GHC.noSrcSpan o
89dynOptionToLocatedStr (DynOption o) = GHC.L GHC.noSrcSpan o
src/Ormolu/Diff.hs+142−41
@@ -1,57 +1,158 @@
1−{-# LANGUAGE DeriveDataTypeable #-}
2−{-# LANGUAGE RankNTypes #-}
1+{-# LANGUAGE RankNTypes #-}
3−{-# LANGUAGE RecordWildCards #-}
4
2
5-- | Diffing GHC ASTs modulo span positions.
3-- | Diffing GHC ASTs modulo span positions.
6−
7module Ormolu.Diff
4module Ormolu.Diff
8− ( diff
5+ ( Diff (..),
6+ diffParseResult,
7+ diffText,
9 )
8 )
10where
9where
11
10
12−import BasicTypes (SourceText)
11+import Data.ByteString (ByteString)
13import Data.Generics
12import Data.Generics
13+import Data.Text (Text)
14+import qualified Data.Text as T
15+import qualified FastString as GHC
14import GHC
16import GHC
15−import Ormolu.Imports (sortImports)
17+import Ormolu.Imports (normalizeImports)
18+import Ormolu.Parser.CommentStream
16import Ormolu.Parser.Result
19import Ormolu.Parser.Result
20+import Ormolu.Utils
21+
22+-- | Result of comparing two 'ParseResult's.
23+data Diff
24+ = -- | Two parse results are the same
25+ Same
26+ | -- | Two parse results differ
27+ Different [SrcSpan]
28+
29+instance Semigroup Diff where
30+ Same <> a = a
31+ a <> Same = a
32+ Different xs <> Different ys = Different (xs ++ ys)
17
33
18−-- | Return 'False' if two annotated ASTs are the same modulo span
34+instance Monoid Diff where
19−-- positions.
35+ mempty = Same
20
36
37+-- | Return 'Diff' of two 'ParseResult's.
21−diff :: ParseResult -> ParseResult -> Bool
38+diffParseResult :: ParseResult -> ParseResult -> Diff
39+diffParseResult
40+ ParseResult
22−diff ParseResult { prCommentStream = cstream0
41+ { prCommentStream = cstream0,
23− , prParsedSource = ps0
42+ prParsedSource = hs0
24− }
43+ }
44+ ParseResult
25− ParseResult { prCommentStream = cstream1
45+ { prCommentStream = cstream1,
26− , prParsedSource = ps1
46+ prParsedSource = hs1
27− } =
47+ } =
28− not (matchIgnoringSrcSpans cstream0 cstream1)
48+ matchIgnoringSrcSpans cstream0 cstream1
29− || not (matchIgnoringSrcSpans ps0 ps1)
49+ <> matchIgnoringSrcSpans
50+ hs0 {hsmodImports = normalizeImports (hsmodImports hs0)}
51+ hs1 {hsmodImports = normalizeImports (hsmodImports hs1)}
30
52
31-- | Compare two values for equality disregarding differences in 'SrcSpan's
53-- | Compare two values for equality disregarding differences in 'SrcSpan's
32-- and the ordering of import lists.
54-- and the ordering of import lists.
33−
34−matchIgnoringSrcSpans :: Data a => a -> a -> Bool
55+matchIgnoringSrcSpans :: Data a => a -> a -> Diff
35matchIgnoringSrcSpans = genericQuery
56matchIgnoringSrcSpans = genericQuery
36 where
57 where
37− genericQuery :: GenericQ (GenericQ Bool)
58+ genericQuery :: GenericQ (GenericQ Diff)
59+ genericQuery x y
60+ -- 'ByteString' implements 'Data' instance manually and does not
61+ -- implement 'toConstr', so we have to deal with it in a special way.
62+ | Just x' <- cast x,
63+ Just y' <- cast y =
64+ if x' == (y' :: ByteString)
65+ then Same
66+ else Different []
67+ | typeOf x == typeOf y,
38− genericQuery x y = (toConstr x == toConstr y)
68+ toConstr x == toConstr y =
69+ mconcat $
70+ gzipWithQ
39− && and (gzipWithQ (genericQuery
71+ ( genericQuery
40− `extQ` srcSpanEq
72+ `extQ` srcSpanEq
41− `extQ` hsModuleEq
73+ `extQ` commentEq
42− `extQ` sourceTextEq) x y)
74+ `extQ` sourceTextEq
43−
75+ `extQ` hsDocStringEq
76+ `extQ` importDeclQualifiedStyleEq
77+ `ext2Q` forLocated
78+ )
79+ x
80+ y
81+ | otherwise = Different []
44− srcSpanEq :: SrcSpan -> GenericQ Bool
82+ srcSpanEq :: SrcSpan -> GenericQ Diff
45− srcSpanEq _ _ = True
83+ srcSpanEq _ _ = Same
46−
84+ commentEq :: Comment -> GenericQ Diff
47− hsModuleEq :: HsModule GhcPs -> GenericQ Bool
85+ commentEq (Comment _ x) d =
48− hsModuleEq hs0 hs1' =
49− case cast hs1' :: Maybe (HsModule GhcPs) of
86+ case cast d :: Maybe Comment of
50− Nothing -> False
87+ Nothing -> Different []
51− Just hs1 ->
88+ Just (Comment _ y) ->
52− matchIgnoringSrcSpans
89+ if x == y
53− hs0 { hsmodImports = sortImports (hsmodImports hs0) }
90+ then Same
54− hs1 { hsmodImports = sortImports (hsmodImports hs1) }
91+ else Different []
55−
56− sourceTextEq :: SourceText -> GenericQ Bool
92+ sourceTextEq :: SourceText -> GenericQ Diff
57− sourceTextEq _ _ = True
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
102+ hsDocStringEq str0 str1' =
103+ case cast str1' :: Maybe HsDocString of
104+ Nothing -> Different []
105+ Just str1 ->
106+ if splitDocString str0 == splitDocString str1
107+ then Same
108+ else Different []
109+ forLocated ::
110+ (Data e0, Data e1) =>
111+ GenLocated e0 e1 ->
112+ GenericQ Diff
113+ forLocated x@(L mspn _) y =
114+ maybe id appendSpan (cast mspn) (genericQuery x y)
115+ appendSpan :: SrcSpan -> Diff -> Diff
116+ appendSpan s (Different ss) | fresh && helpful = Different (s : ss)
117+ where
118+ fresh = not $ any (`isSubspanOf` s) ss
119+ helpful = isGoodSrcSpan s
120+ appendSpan _ d = d
121+
122+-- | Diff two texts and return the location they start to differ, alongside
123+-- with excerpts around that location.
124+diffText ::
125+ -- | Text before
126+ Text ->
127+ -- | Text after
128+ Text ->
129+ -- | Path to use to construct 'GHC.RealSrcLoc'
130+ FilePath ->
131+ Maybe (GHC.RealSrcLoc, Text, Text)
132+diffText left right fp =
133+ case go (0, 0, 0) left right of
134+ Nothing -> Nothing
135+ Just (row, col, loc) ->
136+ Just
137+ ( GHC.mkRealSrcLoc (GHC.mkFastString fp) row col,
138+ getSpan loc left,
139+ getSpan loc right
140+ )
141+ where
142+ go (row, col, loc) t1 t2 =
143+ case (T.uncons t1, T.uncons t2) of
144+ -- both text empty, all good
145+ (Nothing, Nothing) ->
146+ Nothing
147+ -- first chars are the same, adjust position and recurse
148+ (Just (c1, r1), Just (c2, r2))
149+ | c1 == c2 ->
150+ let (row', col', loc') =
151+ if c1 == '\n'
152+ then (row + 1, 0, loc + 1)
153+ else (row, col + 1, loc + 1)
154+ in go (row', col', loc') r1 r2
155+ -- something is different, return the position
156+ _ ->
157+ Just (row, col, loc)
158+ getSpan loc = T.take 20 . T.drop (loc - 10)
src/Ormolu/Exception.hs+62−37
@@ -1,53 +1,72 @@
1{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE LambdaCase #-}
2
2
3-- | 'OrmoluException' type and surrounding definitions.
3-- | 'OrmoluException' type and surrounding definitions.
4−
5module Ormolu.Exception
4module Ormolu.Exception
6− ( OrmoluException (..)
5+ ( OrmoluException (..),
7− , withPrettyOrmoluExceptions
6+ withPrettyOrmoluExceptions,
8 )
7 )
9where
8where
10
9
11import Control.Exception
10import Control.Exception
11+import Data.List.NonEmpty (NonEmpty (..))
12+import qualified Data.List.NonEmpty as NE
12import Data.Text (Text)
13import Data.Text (Text)
14+import qualified GHC
13import Ormolu.Utils (showOutputable)
15import Ormolu.Utils (showOutputable)
16+import qualified Outputable as GHC
14import System.Exit (ExitCode (..), exitWith)
17import System.Exit (ExitCode (..), exitWith)
15import System.IO
18import System.IO
16−import qualified GHC
17
19
18-- | Ormolu exception representing all cases when Ormolu can fail.
20-- | Ormolu exception representing all cases when Ormolu can fail.
19−
20data OrmoluException
21data OrmoluException
21− = OrmoluCppEnabled
22+ = -- | Parsing of original source code failed
22− -- ^ Ormolu does not work with source files that use CPP
23− | OrmoluParsingFailed GHC.SrcSpan String
23+ OrmoluParsingFailed GHC.SrcSpan String
24− -- ^ Parsing of original source code failed
25− | OrmoluOutputParsingFailed GHC.SrcSpan String
26− -- ^ Parsing of formatted source code failed
24+ | -- | Parsing of formatted source code failed
27− | OrmoluASTDiffers String Text
25+ OrmoluOutputParsingFailed GHC.SrcSpan String
28− -- ^ Original and resulting ASTs differ, first argument is the original
26+ | -- | Original and resulting ASTs differ
29− -- source code, second argument is rendered source code
27+ OrmoluASTDiffers FilePath [GHC.SrcSpan]
28+ | -- | Formatted source code is not idempotent
29+ OrmoluNonIdempotentOutput GHC.RealSrcLoc Text Text
30+ | -- | Some GHC options were not recognized
31+ OrmoluUnrecognizedOpts (NonEmpty String)
30 deriving (Eq, Show)
32 deriving (Eq, Show)
31
33
32instance Exception OrmoluException where
34instance Exception OrmoluException where
33 displayException = \case
35 displayException = \case
34− OrmoluCppEnabled -> "CPP is not supported"
35 OrmoluParsingFailed s e ->
36 OrmoluParsingFailed s e ->
36− showParsingErr "Parsing of source code failed:" s e
37+ showParsingErr "The GHC parser (in Haddock mode) failed:" s [e]
37 OrmoluOutputParsingFailed s e ->
38 OrmoluOutputParsingFailed s e ->
38− showParsingErr "Parsing of formatted code failed:" s e ++
39+ showParsingErr "Parsing of formatted code failed:" s [e]
39− "Please, consider reporting the bug."
40+ ++ "Please, consider reporting the bug.\n"
40− OrmoluASTDiffers _ _ -> unlines
41+ OrmoluASTDiffers path ss ->
42+ unlines $
41− [ "AST of input and AST of formatted code differ."
43+ [ "AST of input and AST of formatted code differ."
44+ ]
45+ ++ fmap
46+ withIndent
47+ ( case fmap (\s -> "at " ++ showOutputable s) ss of
48+ [] -> ["in " ++ path]
49+ xs -> xs
50+ )
51+ ++ ["Please, consider reporting the bug."]
52+ OrmoluNonIdempotentOutput loc left right ->
53+ showParsingErr
54+ "Formatting is not idempotent:"
55+ loc
56+ ["before: " ++ show left, "after: " ++ show right]
42− , "Please, consider reporting the bug."
57+ ++ "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
43− ]
62+ ]
44
63
45-- | Inside this wrapper 'OrmoluException' will be caught and displayed
64-- | Inside this wrapper 'OrmoluException' will be caught and displayed
46-- nicely using 'displayException'.
65-- nicely using 'displayException'.
47−
48−withPrettyOrmoluExceptions
66+withPrettyOrmoluExceptions ::
49− :: IO a -- ^ Action that may throw the exception
67+ -- | Action that may throw the exception
68+ IO a ->
50− -> IO a
69+ IO a
51withPrettyOrmoluExceptions m = m `catch` h
70withPrettyOrmoluExceptions m = m `catch` h
52 where
71 where
53 h :: OrmoluException -> IO a
72 h :: OrmoluException -> IO a
@@ -55,20 +74,26 @@ withPrettyOrmoluExceptions m = m `catch` h
55 hPutStrLn stderr (displayException e)
74 hPutStrLn stderr (displayException e)
56 exitWith . ExitFailure $
75 exitWith . ExitFailure $
57 case e of
76 case e of
58− -- Error code 1 is for `error` or `notImplemented`
77+ -- Error code 1 is for 'error' or 'notImplemented'
59− OrmoluCppEnabled -> 2
78+ -- 2 used to be for erroring out on CPP
60− OrmoluParsingFailed _ _ -> 3
79+ OrmoluParsingFailed {} -> 3
61− OrmoluOutputParsingFailed _ _ -> 4
80+ OrmoluOutputParsingFailed {} -> 4
62− OrmoluASTDiffers _ _ -> 5
81+ OrmoluASTDiffers {} -> 5
82+ OrmoluNonIdempotentOutput {} -> 6
83+ OrmoluUnrecognizedOpts {} -> 7
63
84
64----------------------------------------------------------------------------
85----------------------------------------------------------------------------
65-- Helpers
86-- Helpers
66
87
67-- | Show a parse error.
88-- | Show a parse error.
89+showParsingErr :: GHC.Outputable a => String -> a -> [String] -> String
90+showParsingErr msg spn err =
91+ unlines $
92+ [ msg,
93+ withIndent (showOutputable spn)
94+ ]
95+ ++ map withIndent err
68
96
69−showParsingErr :: String -> GHC.SrcSpan -> String -> String
97+-- | Indent with 2 spaces for readability.
70−showParsingErr msg spn err = unlines
98+withIndent :: String -> String
71− [ msg
99+withIndent txt = " " ++ txt
72− , showOutputable spn
73− , err
74− ]
src/Ormolu/Imports.hs+176−62
@@ -1,88 +1,202 @@
1{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE RankNTypes #-}
2{-# LANGUAGE RankNTypes #-}
3+{-# LANGUAGE RecordWildCards #-}
3
4
4-- | Manipulations on import lists.
5-- | Manipulations on import lists.
5−
6module Ormolu.Imports
6module Ormolu.Imports
7− ( sortImports
7+ ( normalizeImports,
8 )
8 )
9where
9where
10
10
11import Data.Bifunctor
11import Data.Bifunctor
12+import Data.Char (isAlphaNum)
12import Data.Function (on)
13import Data.Function (on)
13−import Data.Generics (gcompare)
14+import Data.List (foldl', nubBy, sortBy, sortOn)
14−import Data.List (sortBy)
15+import Data.Map.Strict (Map)
16+import qualified Data.Map.Strict as M
17+import FastString (FastString)
15import GHC hiding (GhcPs, IE)
18import GHC hiding (GhcPs, IE)
16−import HsExtension
19+import GHC.Hs.Extension
17−import HsImpExp (IE (..))
20+import GHC.Hs.ImpExp (IE (..))
18−import Ormolu.Utils (notImplemented)
21+import Ormolu.Utils (notImplemented, showOutputable)
19−
22+
20−-- | Sort imports by module name. This also sorts explicit import lists for
23+-- | Sort and normalize imports.
21−-- each declaration.
22−
23−sortImports :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]
24+normalizeImports :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]
24−sortImports = sortBy compareIdecl . fmap (fmap sortImportLists)
25+normalizeImports =
26+ fmap snd
27+ . M.toAscList
28+ . M.fromListWith combineImports
29+ . fmap (\x -> (importId x, g x))
25 where
30 where
26− sortImportLists :: ImportDecl GhcPs -> ImportDecl GhcPs
31+ g (L l ImportDecl {..}) =
27− sortImportLists decl =
32+ L
33+ l
34+ ImportDecl
28− decl { ideclHiding = second (fmap sortLies) <$> ideclHiding decl
35+ { ideclHiding = second (fmap normalizeLies) <$> ideclHiding,
36+ ..
29− }
37+ }
30−
38+ g _ = notImplemented "XImportDecl"
39+
40+-- | Combine two import declarations. It should be assumed that 'ImportId's
41+-- are equal.
42+combineImports ::
31−-- | Compare two @'LImportDecl' 'GhcPs'@ things.
43+ LImportDecl GhcPs ->
32−
44+ LImportDecl GhcPs ->
33−compareIdecl :: LImportDecl GhcPs -> LImportDecl GhcPs -> Ordering
45+ LImportDecl GhcPs
34−compareIdecl (L _ m0) (L _ m1) =
46+combineImports (L lx ImportDecl {..}) (L _ y) =
35− case (isPrelude n0, isPrelude n1) of
47+ L
36− (False, False) -> n0 `compare` n1
48+ lx
37− (True, False) -> GT
49+ ImportDecl
38− (False, True) -> LT
50+ { ideclHiding = case (ideclHiding, GHC.ideclHiding y) of
39− (True, True) -> m0 `gcompare` m1
51+ (Just (hiding, L l' xs), Just (_, L _ ys)) ->
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+ }
40 where
91 where
41− n0 = unLoc (ideclName m0)
42− n1 = unLoc (ideclName m1)
43− isPrelude = (== "Prelude") . moduleNameString
92+ isPrelude = moduleNameString moduleName == "Prelude"
44−
93+ moduleName = unLoc ideclName
45−-- | Sort located import or export.
94+importId _ = notImplemented "XImportDecl"
46−
47−sortLies :: [LIE GhcPs] -> [LIE GhcPs]
48−sortLies = sortBy (compareIE `on` unLoc) . fmap (fmap sortThings)
49
95
50−-- | Sort imports\/exports inside of 'IEThingWith'.
96+-- | Normalize a collection of import\/export items.
51−
97+normalizeLies :: [LIE GhcPs] -> [LIE GhcPs]
52−sortThings :: IE GhcPs -> IE GhcPs
98+normalizeLies = sortOn (getIewn . unLoc) . M.elems . foldl' combine M.empty
53−sortThings = \case
99+ where
54− IEThingWith NoExt x w xs fl ->
100+ combine ::
55− IEThingWith NoExt x w (sortBy (compareIewn `on` unLoc) xs) fl
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
56− other -> other
113+ other -> other
57−
114+ Just old ->
58−-- | Compare two located imports or exports.
115+ let f = \case
59−
116+ IEVar NoExtField n -> IEVar NoExtField n
60−compareIE :: IE GhcPs -> IE GhcPs -> Ordering
117+ IEThingAbs NoExtField _ -> new
61−compareIE = compareIewn `on` getIewn
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+
152+-- | A wrapper for @'IEWrappedName' 'RdrName'@ that allows us to define an
153+-- 'Ord' instance for it.
154+newtype IEWrappedNameOrd = IEWrappedNameOrd (IEWrappedName RdrName)
155+ deriving (Eq)
156+
157+instance Ord IEWrappedNameOrd where
158+ compare (IEWrappedNameOrd x) (IEWrappedNameOrd y) = compareIewn x y
62
159
63-- | Project @'IEWrappedName' 'RdrName'@ from @'IE' 'GhcPs'@.
160-- | Project @'IEWrappedName' 'RdrName'@ from @'IE' 'GhcPs'@.
64−
65−getIewn :: IE GhcPs -> IEWrappedName RdrName
161+getIewn :: IE GhcPs -> IEWrappedNameOrd
66getIewn = \case
162getIewn = \case
67− IEVar NoExt x -> unLoc x
163+ IEVar NoExtField x -> IEWrappedNameOrd (unLoc x)
68− IEThingAbs NoExt x -> unLoc x
164+ IEThingAbs NoExtField x -> IEWrappedNameOrd (unLoc x)
69− IEThingAll NoExt x -> unLoc x
165+ IEThingAll NoExtField x -> IEWrappedNameOrd (unLoc x)
70− IEThingWith NoExt x _ _ _ -> unLoc x
166+ IEThingWith NoExtField x _ _ _ -> IEWrappedNameOrd (unLoc x)
71− IEModuleContents NoExt _ -> notImplemented "IEModuleContents"
167+ IEModuleContents NoExtField _ -> notImplemented "IEModuleContents"
72− IEGroup NoExt _ _ -> notImplemented "IEGroup"
168+ IEGroup NoExtField _ _ -> notImplemented "IEGroup"
73− IEDoc NoExt _ -> notImplemented "IEDoc"
169+ IEDoc NoExtField _ -> notImplemented "IEDoc"
74− IEDocNamed NoExt _ -> notImplemented "IEDocNamed"
170+ IEDocNamed NoExtField _ -> notImplemented "IEDocNamed"
75− XIE NoExt -> notImplemented "XIE"
171+ XIE x -> noExtCon x
172+
173+-- | Like 'compareIewn' for located wrapped names.
174+compareLIewn :: LIEWrappedName RdrName -> LIEWrappedName RdrName -> Ordering
175+compareLIewn = compareIewn `on` unLoc
76
176
77-- | Compare two @'IEWrapppedName' 'RdrName'@ things.
177-- | Compare two @'IEWrapppedName' 'RdrName'@ things.
78−
79compareIewn :: IEWrappedName RdrName -> IEWrappedName RdrName -> Ordering
178compareIewn :: IEWrappedName RdrName -> IEWrappedName RdrName -> Ordering
80−compareIewn (IEName x) (IEName y) = unLoc x `compare` unLoc y
179+compareIewn (IEName x) (IEName y) = unLoc x `compareRdrName` unLoc y
81compareIewn (IEName _) (IEPattern _) = LT
180compareIewn (IEName _) (IEPattern _) = LT
82compareIewn (IEName _) (IEType _) = LT
181compareIewn (IEName _) (IEType _) = LT
83compareIewn (IEPattern _) (IEName _) = GT
182compareIewn (IEPattern _) (IEName _) = GT
84−compareIewn (IEPattern x) (IEPattern y) = unLoc x `compare` unLoc y
183+compareIewn (IEPattern x) (IEPattern y) = unLoc x `compareRdrName` unLoc y
85compareIewn (IEPattern _) (IEType _) = LT
184compareIewn (IEPattern _) (IEType _) = LT
86compareIewn (IEType _) (IEName _) = GT
185compareIewn (IEType _) (IEName _) = GT
87compareIewn (IEType _) (IEPattern _) = GT
186compareIewn (IEType _) (IEPattern _) = GT
88−compareIewn (IEType x) (IEType y) = unLoc x `compare` unLoc y
187+compareIewn (IEType x) (IEType y) = unLoc x `compareRdrName` 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+189−193
@@ -1,223 +1,219 @@
1+{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE RecordWildCards #-}
2{-# LANGUAGE RecordWildCards #-}
3+{-# OPTIONS_GHC -fno-warn-orphans #-}
2
4
3-- | Parser for Haskell source code.
5-- | Parser for Haskell source code.
4−
5module Ormolu.Parser
6module Ormolu.Parser
6− ( parseModule
7+ ( parseModule,
8+ manualExts,
7 )
9 )
8where
10where
9
11
12+import Bag (bagToList)
13+import qualified CmdLineParser as GHC
10import Control.Exception
14import Control.Exception
11−import Control.Monad
12import Control.Monad.IO.Class
15import Control.Monad.IO.Class
13−import Data.List (isPrefixOf, foldl')
16+import qualified Data.List as L
17+import qualified Data.List.NonEmpty as NE
18+import Data.Ord (Down (Down))
14−import Data.Maybe (catMaybes)
19+import qualified Data.Text as T
15−import GHC hiding (IE, parseModule, parser)
20+import DynFlags as GHC
21+import ErrUtils (Severity (..), errMsgSeverity, errMsgSpan)
22+import qualified FastString as GHC
23+import GHC hiding (IE, UnicodeSyntax)
24+import GHC.DynFlags (baseDynFlags)
16import GHC.LanguageExtensions.Type (Extension (..))
25import GHC.LanguageExtensions.Type (Extension (..))
17−import GHC.Paths (libdir)
26+import qualified HeaderInfo as GHC
27+import qualified HscTypes as GHC
28+import qualified Lexer as GHC
18import Ormolu.Config
29import Ormolu.Config
19import Ormolu.Exception
30import Ormolu.Exception
20import Ormolu.Parser.Anns
31import Ormolu.Parser.Anns
21import Ormolu.Parser.CommentStream
32import Ormolu.Parser.CommentStream
22import Ormolu.Parser.Result
33import Ormolu.Parser.Result
23−import qualified CmdLineParser as GHC
34+import Ormolu.Processing.Preprocess (preprocess)
24−import qualified DynFlags as GHC
35+import Ormolu.Utils (incSpanLine, removeIndentation)
25−import qualified FastString as GHC
26−import qualified HeaderInfo as GHC
27−import qualified Lexer as GHC
28−import qualified Outputable as GHC
36+import qualified Panic as GHC
29import qualified Parser as GHC
37import qualified Parser as GHC
30−import qualified SrcLoc as GHC
31import qualified StringBuffer as GHC
38import qualified StringBuffer as GHC
32
39
33-- | Parse a complete module from string.
40-- | Parse a complete module from string.
41+parseModule ::
42+ MonadIO m =>
43+ -- | Ormolu configuration
44+ Config RegionDeltas ->
45+ -- | File name (only for source location annotations)
46+ FilePath ->
47+ -- | Input for parser
48+ String ->
49+ m
50+ ( [GHC.Warn],
51+ Either (SrcSpan, String) ParseResult
52+ )
53+parseModule Config {..} path rawInput = liftIO $ do
54+ let (literalPrefix, indentedInput, literalSuffix, extraComments) =
55+ preprocess path rawInput cfgRegion
56+ (input, indent) = removeIndentation indentedInput
57+ -- It's important that 'setDefaultExts' is done before
58+ -- 'parsePragmasIntoDynFlags', because otherwise we might enable an
59+ -- extension that was explicitly disabled in the file.
60+ let baseFlags =
61+ GHC.setGeneralFlag'
62+ GHC.Opt_Haddock
63+ (setDefaultExts baseDynFlags)
64+ extraOpts = dynOptionToLocatedStr <$> cfgDynOptions
65+ (warnings, dynFlags) <-
66+ parsePragmasIntoDynFlags baseFlags extraOpts path rawInput >>= \case
67+ Right res -> pure res
68+ Left err ->
69+ let loc =
70+ mkSrcSpan
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
88+ GHC.PFailed pstate ->
89+ case pStateErrors pstate of
90+ Just err -> Left err
91+ Nothing -> error "PFailed does not have an error"
92+ GHC.POk pstate (L _ hsModule) ->
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
102+ in Right
103+ ParseResult
104+ { prParsedSource = hsModule,
105+ prAnns = mkAnns pstate,
106+ prStackHeader = stackHeader,
107+ prShebangs = shebangs,
108+ prPragmas = pragmas,
109+ prCommentStream = comments,
110+ prUseRecordDot = useRecordDot,
111+ prImportQualifiedPost =
112+ GHC.xopt ImportQualifiedPost dynFlags,
113+ prLiteralPrefix = T.pack literalPrefix,
114+ prLiteralSuffix = T.pack literalSuffix,
115+ prIndent = indent
116+ }
117+ return (warnings, r)
34
118
35−parseModule
119+-- | Enable all language extensions that we think should be enabled by
36− :: MonadIO m
120+-- default for ease of use.
37− => [DynOption] -- ^ Dynamic options that affect parsing
121+setDefaultExts :: DynFlags -> DynFlags
38− -> FilePath -- ^ File name (only for source location annotations)
122+setDefaultExts flags = L.foldl' xopt_set flags autoExts
39− -> String -- ^ Input for parser
123+ where
40− -> m ( [GHC.Warn]
124+ autoExts = allExts L.\\ manualExts
41− , Either (SrcSpan, String) ParseResult
125+ allExts = [minBound .. maxBound]
42− )
126+
43−parseModule dynOpts path input' = liftIO $ do
127+-- | Extensions that are not enabled automatically and should be activated
44− let (input, extraComments) = stripLinePragmas input'
128+-- by user.
45− (ws, dynFlags) <- ghcWrapper $ do
129+manualExts :: [Extension]
46− dynFlags0 <- initDynFlagsPure path input
130+manualExts =
47− (dynFlags1, _, ws) <-
131+ [ Arrows, -- steals proc
48− GHC.parseDynamicFilePragma dynFlags0 (dynOptionToLocatedStr <$> dynOpts)
132+ Cpp, -- forbidden
49− return (ws, dynFlags1)
133+ BangPatterns, -- makes certain patterns with ! fail
50− -- NOTE It's better to throw this outside of 'ghcWrapper' because
134+ PatternSynonyms, -- steals the pattern keyword
51− -- otherwise the exception will be wrapped as a GHC panic, which we don't
135+ RecursiveDo, -- steals the rec keyword
52− -- want.
136+ StaticPointers, -- steals static keyword
53− when (GHC.xopt Cpp dynFlags) $
137+ TransformListComp, -- steals the group keyword
54− throwIO OrmoluCppEnabled
138+ UnboxedTuples, -- breaks (#) lens operator
55− let r = case runParser GHC.parseModule dynFlags path input of
139+ MagicHash, -- screws {-# these things #-}
56− GHC.PFailed _ ss m ->
140+ TypeApplications, -- steals (@) operator on some cases
57− Left (ss, GHC.showSDoc dynFlags m)
141+ AlternativeLayoutRule,
58− GHC.POk pstate pmod ->
142+ AlternativeLayoutRuleTransitional,
59− let (comments, exts) = mkCommentStream extraComments pstate
143+ MonadComprehensions,
60− in Right ParseResult
144+ UnboxedSums,
61− { prParsedSource = pmod
145+ UnicodeSyntax, -- gives special meanings to operators like (→)
62− , prAnns = mkAnns pstate
146+ TemplateHaskellQuotes, -- enables TH subset of quasi-quotes, this
63− , prCommentStream = comments
147+ -- apparently interferes with QuasiQuotes in
64− , prExtensions = exts
148+ -- weird ways
65− }
149+ ImportQualifiedPost -- affects how Ormolu renders imports, so the
66− return (ws, r)
150+ -- decision of enabling this style is left to the user
67−
151+ ]
68−----------------------------------------------------------------------------
69−-- Helpers (taken from ghc-exactprint)
70−
71−-- | Requires GhcMonad constraint because there is no pure variant of
72−-- 'parseDynamicFilePragma'. Yet, in constrast to 'initDynFlags', it does
73−-- not (try to) read the file at filepath, but solely depends on the module
74−-- source in the input string.
75−--
76−-- Passes "-hide-all-packages" to the GHC API to prevent parsing of package
77−-- environment files. However this only works if there is no invocation of
78−-- 'setSessionDynFlags' before calling 'initDynFlagsPure'. See GHC tickets
79−-- #15513, #15541.
80−
81−initDynFlagsPure
82− :: GHC.GhcMonad m
83− => FilePath -- ^ Module path
84− -> String -- ^ Module contents
85− -> m GHC.DynFlags -- ^ Dynamic flags for that module
86−initDynFlagsPure fp input = do
87− -- I was told we could get away with using the 'unsafeGlobalDynFlags'. as
88− -- long as 'parseDynamicFilePragma' is impure there seems to be no reason
89− -- to use it.
90− dflags0 <- setDefaultExts <$> GHC.getSessionDynFlags
91− let tokens = GHC.getOptions dflags0 (GHC.stringToStringBuffer input) fp
92− (dflags1, _, _) <- GHC.parseDynamicFilePragma dflags0 tokens
93− -- Turn this on last to avoid T10942
94− let dflags2 = dflags1 `GHC.gopt_set` GHC.Opt_KeepRawTokenStream
95− -- Prevent parsing of .ghc.environment.* "package environment files"
96− (dflags3, _, _) <- GHC.parseDynamicFlagsCmdLine
97− dflags2
98− [GHC.noLoc "-hide-all-packages"]
99− _ <- GHC.setSessionDynFlags dflags3
100− return dflags3
101−
102−-- | Default runner of 'GHC.Ghc' action in 'IO'.
103−
104−ghcWrapper :: GHC.Ghc a -> IO a
105−ghcWrapper
106− = GHC.defaultErrorHandler GHC.defaultFatalMessager GHC.defaultFlushOut
107− . GHC.runGhc (Just libdir)
108
152
109-- | Run a 'GHC.P' computation.
153-- | Run a 'GHC.P' computation.
110−
111−runParser
154+runParser ::
112− :: GHC.P a -- ^ Computation to run
155+ -- | Computation to run
156+ GHC.P a ->
113− -> GHC.DynFlags -- ^ Dynamic flags
157+ -- | Dynamic flags
158+ GHC.DynFlags ->
114− -> FilePath -- ^ Module path
159+ -- | Module path
160+ FilePath ->
115− -> String -- ^ Module contents
161+ -- | Module contents
162+ String ->
116− -> GHC.ParseResult a -- ^ Parse result
163+ -- | Parse result
164+ GHC.ParseResult a
117runParser parser flags filename input = GHC.unP parser parseState
165runParser parser flags filename input = GHC.unP parser parseState
118 where
166 where
119 location = GHC.mkRealSrcLoc (GHC.mkFastString filename) 1 1
167 location = GHC.mkRealSrcLoc (GHC.mkFastString filename) 1 1
120 buffer = GHC.stringToStringBuffer input
168 buffer = GHC.stringToStringBuffer input
121 parseState = GHC.mkPState flags buffer location
169 parseState = GHC.mkPState flags buffer location
122
170
123−-- | Remove GHC style line pragams (@{-# LINE .. #-}@) and convert them into
171+-- | Wrap GHC's 'Severity' to add 'Ord' instance.
124−-- comments.
172+newtype SeverityOrd = SeverityOrd Severity
173+
174+instance Eq SeverityOrd where
175+ s1 == s2 = compare s1 s2 == EQ
176+
177+instance Ord SeverityOrd where
178+ compare (SeverityOrd s1) (SeverityOrd s2) =
179+ compare (f s1) (f s2)
180+ where
181+ f :: Severity -> Int
182+ f SevOutput = 1
183+ f SevFatal = 2
184+ f SevInteractive = 3
185+ f SevDump = 4
186+ f SevInfo = 5
187+ f SevWarning = 6
188+ f SevError = 7
125
189
190+----------------------------------------------------------------------------
191+-- Helpers taken from HLint
192+
193+parsePragmasIntoDynFlags ::
194+ -- | Pre-set 'DynFlags'
195+ DynFlags ->
196+ -- | Extra options (provided by user)
126−stripLinePragmas :: String -> (String, [Located String])
197+ [Located String] ->
127−stripLinePragmas = unlines' . unzip . findLines . lines
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'')
128 where
214 where
129− unlines' (a, b) = (unlines a, catMaybes b)
215+ catchErrors act =
130−
216+ GHC.handleGhcException
131−findLines :: [String] -> [(String, Maybe (Located String))]
217+ reportErr
132−findLines = zipWith checkLine [1..]
218+ (GHC.handleSourceError reportErr act)
133−
219+ reportErr e = return $ Left (show e)
134−checkLine :: Int -> String -> (String, Maybe (Located String))
135−checkLine line s
136− | "{-# LINE" `isPrefixOf` s =
137− let (pragma, res) = getPragma s
138− size = length pragma
139− mSrcLoc = mkSrcLoc (GHC.mkFastString "LINE")
140− ss = mkSrcSpan (mSrcLoc line 1) (mSrcLoc line (size+1))
141− in (res, Just $ L ss pragma)
142− -- Deal with shebang/cpp directives too
143− -- x | "#" `isPrefixOf` s = ("",Just $ Comment ((line, 1), (line, length s)) s)
144− | "#!" `isPrefixOf` s =
145− let mSrcLoc = mkSrcLoc (GHC.mkFastString "SHEBANG")
146− ss = mkSrcSpan (mSrcLoc line 1) (mSrcLoc line (length s))
147− in ("",Just $ L ss s)
148− | otherwise = (s, Nothing)
149−
150−getPragma :: String -> (String, String)
151−getPragma [] = error "Ormolu.Parser.getPragma: input must not be empty"
152−getPragma s@(x:xs)
153− | "#-}" `isPrefixOf` s = ("#-}", " " ++ drop 3 s)
154− | otherwise =
155− let (prag, remline) = getPragma xs
156− in (x:prag, ' ':remline)
157−
158−-- | Enable all language extensions that we think should be enabled by
159−-- default for ease of use.
160−
161−setDefaultExts :: DynFlags -> DynFlags
162−setDefaultExts flags = foldl' GHC.xopt_set flags
163− [ OverlappingInstances
164− , UndecidableInstances
165− , IncoherentInstances
166− , UndecidableSuperClasses
167− , ExtendedDefaultRules
168− , ForeignFunctionInterface
169− , TemplateHaskell
170− , QuasiQuotes
171− , ImplicitParams
172− , ScopedTypeVariables
173− , BangPatterns
174− , TypeFamilies
175− , TypeFamilyDependencies
176− , TypeInType
177− , OverloadedStrings
178− , OverloadedLists
179− , RecordWildCards
180− , RecordPuns
181− , GADTs
182− , GADTSyntax
183− , NPlusKPatterns
184− , ConstraintKinds
185− , PolyKinds
186− , DataKinds
187− , InstanceSigs
188− , StandaloneDeriving
189− , DefaultSignatures
190− , DeriveAnyClass
191− , DerivingStrategies
192− , DerivingVia
193− , FlexibleContexts
194− , FlexibleInstances
195− , MultiParamTypeClasses
196− , FunctionalDependencies
197− , ExistentialQuantification
198− , EmptyDataDecls
199− , KindSignatures
200− , RoleAnnotations
201− , GeneralizedNewtypeDeriving
202− , RecursiveDo
203− , TupleSections
204− , PatternGuards
205− , RankNTypes
206− , TypeOperators
207− , ExplicitNamespaces
208− , PackageImports
209− , ExplicitForAll
210− , LambdaCase
211− , MultiWayIf
212− , BinaryLiterals
213− , NegativeLiterals
214− , HexFloatLiterals
215− , OverloadedLabels
216− , EmptyCase
217− , NamedWildCards
218− , StaticPointers
219− , TypeApplications
220− , NumericUnderscores
221− , QuantifiedConstraints
222− , StarIsType
223− ]
src/Ormolu/Parser/Anns.hs+18−20
@@ -1,37 +1,34 @@
1-- | Ormolu-specific representation of GHC annotations.
1-- | Ormolu-specific representation of GHC annotations.
2−
3module Ormolu.Parser.Anns
2module Ormolu.Parser.Anns
4− ( Anns (..)
3+ ( Anns (..),
5− , emptyAnns
4+ emptyAnns,
6− , mkAnns
5+ mkAnns,
7− , lookupAnns
6+ lookupAnns,
8 )
7 )
9where
8where
10
9
11import Data.Map.Strict (Map)
10import Data.Map.Strict (Map)
12−import Data.Maybe (mapMaybe)
13−import SrcLoc
14import qualified Data.Map.Strict as M
11import qualified Data.Map.Strict as M
12+import Data.Maybe (mapMaybe)
15import qualified GHC
13import qualified GHC
16import qualified Lexer as GHC
14import qualified Lexer as GHC
15+import SrcLoc
17
16
18-- | Ormolu-specific representation of GHC annotations.
17-- | Ormolu-specific representation of GHC annotations.
19−
20newtype Anns = Anns (Map RealSrcSpan [GHC.AnnKeywordId])
18newtype Anns = Anns (Map RealSrcSpan [GHC.AnnKeywordId])
21 deriving (Eq)
19 deriving (Eq)
22
20
23-- | Empty 'Anns'.
21-- | Empty 'Anns'.
24−
25emptyAnns :: Anns
22emptyAnns :: Anns
26emptyAnns = Anns M.empty
23emptyAnns = Anns M.empty
27
24
28-- | Create 'Anns' from 'GHC.PState'.
25-- | Create 'Anns' from 'GHC.PState'.
29−
30−mkAnns
26+mkAnns ::
31− :: GHC.PState
27+ GHC.PState ->
32− -> Anns
28+ Anns
33−mkAnns pstate = Anns $
29+mkAnns pstate =
30+ Anns $
34− M.fromListWith (++) (mapMaybe f (GHC.annotations pstate))
31+ M.fromListWith (++) (mapMaybe f (GHC.annotations pstate))
35 where
32 where
36 f ((spn, kid), _) =
33 f ((spn, kid), _) =
37 case spn of
34 case spn of
@@ -39,10 +36,11 @@ mkAnns pstate = Anns $
39 UnhelpfulSpan _ -> Nothing
36 UnhelpfulSpan _ -> Nothing
40
37
41-- | Lookup 'GHC.AnnKeywordId's corresponding to a given 'SrcSpan'.
38-- | Lookup 'GHC.AnnKeywordId's corresponding to a given 'SrcSpan'.
42−
43−lookupAnns
39+lookupAnns ::
44− :: SrcSpan -- ^ Span to lookup with
40+ -- | Span to lookup with
41+ SrcSpan ->
45− -> Anns -- ^ Collection of annotations
42+ -- | Collection of annotations
43+ Anns ->
46− -> [GHC.AnnKeywordId]
44+ [GHC.AnnKeywordId]
47lookupAnns (RealSrcSpan rspn) (Anns m) = M.findWithDefault [] rspn m
45lookupAnns (RealSrcSpan rspn) (Anns m) = M.findWithDefault [] rspn m
48lookupAnns (UnhelpfulSpan _) _ = []
46lookupAnns (UnhelpfulSpan _) _ = []
src/Ormolu/Parser/CommentStream.hs+184−91
@@ -1,133 +1,226 @@
1−{-# LANGUAGE BangPatterns #-}
2−{-# LANGUAGE DeriveDataTypeable #-}
1+{-# LANGUAGE DeriveDataTypeable #-}
3{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2{-# LANGUAGE GeneralizedNewtypeDeriving #-}
4−{-# LANGUAGE LambdaCase #-}
3+{-# LANGUAGE LambdaCase #-}
5−{-# LANGUAGE TupleSections #-}
6
4
7-- | Functions for working with comment stream.
5-- | Functions for working with comment stream.
8−
9module Ormolu.Parser.CommentStream
6module Ormolu.Parser.CommentStream
7+ ( -- * Comment stream
10− ( CommentStream (..)
8+ CommentStream (..),
11− , Comment (..)
12− , mkCommentStream
9+ mkCommentStream,
13− , isPrevHaddock
14− , showCommentStream
10+ showCommentStream,
11+
12+ -- * Comment
13+ Comment (..),
14+ unComment,
15+ hasAtomsBefore,
16+ isMultilineComment,
15 )
17 )
16where
18where
17
19
18import Data.Char (isSpace)
20import Data.Char (isSpace)
19import Data.Data (Data)
21import Data.Data (Data)
20−import Data.Either (partitionEithers)
22+import qualified Data.List as L
21−import Data.List (isPrefixOf, sortOn, dropWhileEnd)
22import Data.List.NonEmpty (NonEmpty (..))
23import Data.List.NonEmpty (NonEmpty (..))
23−import Data.Maybe (mapMaybe)
24−import Data.Set (Set)
25−import Ormolu.Parser.LanguagePragma
26−import Ormolu.Utils (showOutputable)
27−import SrcLoc
28import qualified Data.List.NonEmpty as NE
24import qualified Data.List.NonEmpty as NE
29−import qualified Data.Set as S
25+import Data.Maybe (mapMaybe)
30import qualified GHC
26import qualified GHC
31import qualified Lexer as GHC
27import qualified Lexer as GHC
28+import Ormolu.Parser.Pragma
29+import Ormolu.Parser.Shebang
30+import Ormolu.Processing.Common
31+import Ormolu.Utils (onTheSameLine, showOutputable)
32+import SrcLoc
33+
34+----------------------------------------------------------------------------
35+-- Comment stream
32
36
33-- | A stream of 'RealLocated' 'Comment's in ascending order with respect to
37-- | A stream of 'RealLocated' 'Comment's in ascending order with respect to
34-- beginning of corresponding spans.
38-- beginning of corresponding spans.
35−
36newtype CommentStream = CommentStream [RealLocated Comment]
39newtype CommentStream = CommentStream [RealLocated Comment]
37 deriving (Eq, Data, Semigroup, Monoid)
40 deriving (Eq, Data, Semigroup, Monoid)
38
41
39−-- | A wrapper for a single comment. The 'NonEmpty' list inside contains
40−-- lines of multiline comment @{- … -}@ or just single item\/line otherwise.
41−
42−newtype Comment = Comment (NonEmpty String)
43− deriving (Eq, Show, Data)
44−
45−-- | Create 'CommentStream' from 'GHC.PState'. We also create a 'Set' of
42+-- | Create 'CommentStream' from 'GHC.PState'. The pragmas and shebangs are
46−-- extensions here, which is not sorted in any way. The pragma comment are
47−-- removed from the 'CommentStream'.
43+-- removed from the 'CommentStream'. Shebangs are only extracted from the
48−
44+-- comments that come from the first argument.
49−mkCommentStream
45+mkCommentStream ::
46+ -- | Original input
47+ String ->
50− :: [Located String] -- ^ Extra comments to include
48+ -- | Extra comments to include
49+ [Located String] ->
51− -> GHC.PState -- ^ Parser state to use for comment extraction
50+ -- | Parser state to use for comment extraction
52− -> (CommentStream, Set String)
51+ GHC.PState ->
53− -- ^ Comment stream and a set of extensions enabled
52+ -- | Stack header, shebangs, pragmas, and comment stream
53+ ( Maybe (RealLocated Comment),
54+ [Shebang],
55+ [([RealLocated Comment], Pragma)],
56+ CommentStream
57+ )
54−mkCommentStream extraComments pstate =
58+mkCommentStream input extraComments pstate =
55− ( CommentStream $
59+ ( mstackHeader,
56− -- NOTE It's easier to normalize pragmas right when we construct comment
60+ shebangs,
57− -- streams. Because this way we need to do it only once and when we
61+ pragmas,
58− -- perform checking later they'll automatically match.
62+ CommentStream comments
59− mkComment <$> sortOn (realSrcSpanStart . getLoc) comments
60− , S.unions exts
61 )
63 )
62 where
64 where
63− (comments, exts) = partitionEithers (partitionComments <$> rawComments)
65+ (comments, pragmas) = extractPragmas input rawComments1
66+ (rawComments1, mstackHeader) = extractStackHeader rawComments0
67+ rawComments0 =
64− rawComments = mapMaybe toRealSpan $
68+ L.sortOn (realSrcSpanStart . getRealSrcSpan) . mapMaybe toRealSpan $
65− extraComments ++
69+ otherExtraComments
66− (fmap unAnnotationComment <$> GHC.comment_q pstate) ++
70+ ++ mapMaybe (liftMaybe . fmap unAnnotationComment) (GHC.comment_q pstate)
71+ ++ concatMap
67− concatMap (fmap (fmap unAnnotationComment) . snd)
72+ (mapMaybe (liftMaybe . fmap unAnnotationComment) . snd)
68− (GHC.annotations_comments pstate)
73+ (GHC.annotations_comments pstate)
69−
74+ (shebangs, otherExtraComments) = extractShebangs extraComments
70−-- | Test whether a 'Comment' looks like a Haddock following a definition,
71−-- i.e. something starting with @-- ^@.
72−
73−isPrevHaddock :: Comment -> Bool
74−isPrevHaddock (Comment (x :| _)) = "-- ^" `isPrefixOf` x
75
75
76-- | Pretty-print a 'CommentStream'.
76-- | Pretty-print a 'CommentStream'.
77−
78showCommentStream :: CommentStream -> String
77showCommentStream :: CommentStream -> String
79−showCommentStream (CommentStream xs) = unlines $
78+showCommentStream (CommentStream xs) =
79+ unlines $
80− showComment <$> xs
80+ showComment <$> xs
81 where
81 where
82 showComment (GHC.L l str) = showOutputable l ++ " " ++ show str
82 showComment (GHC.L l str) = showOutputable l ++ " " ++ show str
83
83
84----------------------------------------------------------------------------
84----------------------------------------------------------------------------
85−-- Helpers
85+-- Comment
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)
86
93
87-- | Normalize comment string. Sometimes one multi-line comment is turned
94-- | Normalize comment string. Sometimes one multi-line comment is turned
88-- into several lines for subsequent outputting with correct indentation for
95-- into several lines for subsequent outputting with correct indentation for
89-- each line.
96-- each line.
90−
97+mkComment ::
91−mkComment :: RealLocated String -> RealLocated Comment
98+ -- | Lines of original input with their indices
92−mkComment (L l s) = L l . Comment . fmap dropTrailing $
99+ [(Int, String)] ->
93− if "{-" `isPrefixOf` s
100+ -- | Raw comment string
94− then case NE.nonEmpty (lines s) of
101+ RealLocated String ->
95− Nothing -> s :| []
102+ -- | Remaining lines of original input and the constructed 'Comment'
96− Just (x:|xs) ->
103+ ([(Int, String)], RealLocated Comment)
97− let getIndent y =
104+mkComment ls (L l s) = (ls', comment)
98− if all isSpace y
99− then startIndent
100− else length (takeWhile isSpace y)
101− n = minimum (startIndent : fmap getIndent xs)
102− in x :| (drop n <$> xs)
103− else s :| []
104 where
105 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'')
105− dropTrailing = dropWhileEnd isSpace
131+ dropTrailing = L.dropWhileEnd isSpace
106 startIndent = srcSpanStartCol l - 1
132 startIndent = srcSpanStartCol l - 1
133+ commentLine = srcSpanStartLine l
107
134
108−-- | Get a 'String' from 'GHC.AnnotationComment'.
135+-- | Get a collection of lines from a 'Comment'.
136+unComment :: Comment -> NonEmpty String
137+unComment (Comment _ xs) = xs
109
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+
197+-- | Get a 'String' from 'GHC.AnnotationComment'.
110−unAnnotationComment :: GHC.AnnotationComment -> String
198+unAnnotationComment :: GHC.AnnotationComment -> Maybe String
111unAnnotationComment = \case
199unAnnotationComment = \case
112− GHC.AnnDocCommentNext s -> s
200+ GHC.AnnDocCommentNext _ -> Nothing -- @-- |@
113− GHC.AnnDocCommentPrev s -> s
201+ GHC.AnnDocCommentPrev _ -> Nothing -- @-- ^@
114− GHC.AnnDocCommentNamed s -> s
202+ GHC.AnnDocCommentNamed _ -> Nothing -- @-- $@
115− GHC.AnnDocSection _ s -> s
203+ GHC.AnnDocSection _ _ -> Nothing -- @-- *@
116− GHC.AnnDocOptions s -> s
204+ GHC.AnnDocOptions s -> Just s
117− GHC.AnnLineComment s -> s
205+ GHC.AnnLineComment s -> Just s
118− GHC.AnnBlockComment s -> s
206+ GHC.AnnBlockComment s -> Just s
207+
208+liftMaybe :: Located (Maybe a) -> Maybe (Located a)
209+liftMaybe = \case
210+ L _ Nothing -> Nothing
211+ L l (Just a) -> Just (L l a)
119
212
120toRealSpan :: Located a -> Maybe (RealLocated a)
213toRealSpan :: Located a -> Maybe (RealLocated a)
121toRealSpan (L (RealSrcSpan l) a) = Just (L l a)
214toRealSpan (L (RealSrcSpan l) a) = Just (L l a)
122toRealSpan _ = Nothing
215toRealSpan _ = Nothing
123
216
124−-- | If a given comment is a LANGUAGE pragma, return the set of extensions
217+-- | Remove consecutive blank lines.
125−-- it enables in 'Right'. Otherwise return the original comment unchanged.
218+removeConseqBlanks :: NonEmpty String -> NonEmpty String
126−
219+removeConseqBlanks (x :| xs) = x :| go (null x) id xs
127−partitionComments
220+ where
128− :: RealLocated String
221+ go seenBlank acc = \case
129− -> Either (RealLocated String) (Set String)
222+ [] -> acc []
130−partitionComments input =
223+ (y : ys) ->
131− case parseLanguagePragma (unLoc input) of
224+ if seenBlank && null y
132− Nothing -> Left input
225+ then go True acc ys
133− Just exts -> Right exts
226+ else go (null y) (acc . (y :)) ys
src/Ormolu/Parser/LanguagePragma.hsdeleted−85
@@ -1,85 +0,0 @@
1−-- | A module for parsing of language pragmas from comments.
2−
3−{-# LANGUAGE LambdaCase #-}
4−{-# LANGUAGE OverloadedStrings #-}
5−
6−module Ormolu.Parser.LanguagePragma
7− ( parseLanguagePragma
8− )
9−where
10−
11−import Data.Char (toLower)
12−import Data.List (isPrefixOf)
13−import Data.Set (Set)
14−import FastString (mkFastString, unpackFS)
15−import Module (newSimpleUnitId, ComponentId (..))
16−import SrcLoc
17−import StringBuffer
18−import qualified Data.Set as S
19−import qualified EnumSet as ES
20−import qualified Lexer as L
21−
22−-- | Extract a 'Set' of language extensions from a comment if it's a
23−-- language pragma or return 'Nothing' otherwise.
24−
25−parseLanguagePragma
26− :: String -- ^ Comment to try to parse
27− -> Maybe (Set String)
28−parseLanguagePragma input =
29− if "{-#" `isPrefixOf` input
30− then do
31− toks0 <- tokenize (drop 3 input)
32− toks1 <- dropLanguage toks0
33− S.fromList <$> parseExtensions toks1
34− else Nothing
35−
36−-- | Assuming the input consists of a series of tokens from a language
37−-- pragma, return the set of enabled extensions.
38−
39−parseExtensions :: [L.Token] -> Maybe [String]
40−parseExtensions = \case
41− (L.ITconid ext : L.ITclose_prag : []) -> return [unpackFS ext]
42− (L.ITconid ext : L.ITcomma : xs) -> (unpackFS ext :) <$> parseExtensions xs
43− _ -> Nothing
44−
45−-- | Drop LANGUAGE pragma text from the token stream.
46−
47−dropLanguage :: [L.Token] -> Maybe [L.Token]
48−dropLanguage = \case
49− (L.ITconid lang : xs) -> go lang xs
50− (L.ITvarid lang : xs) -> go lang xs
51− _ -> Nothing
52− where
53− go lang xs =
54− if (toLower <$> unpackFS lang) == "language"
55− then Just xs
56− else Nothing
57−
58−-- | Tokenize a given input using GHC's lexer.
59−
60−tokenize :: String -> Maybe [L.Token]
61−tokenize input =
62− case L.unP pLexer parseState of
63− L.PFailed {} -> Nothing
64− L.POk _ x -> Just x
65− where
66− location = mkRealSrcLoc (mkFastString "") 1 1
67− buffer = stringToStringBuffer input
68− parseState = L.mkPStatePure parserFlags buffer location
69− parserFlags = L.ParserFlags
70− { L.pWarningFlags = ES.empty
71− , L.pExtensionFlags = ES.empty
72− , L.pThisPackage = newSimpleUnitId (ComponentId (mkFastString ""))
73− , L.pExtsBitmap = 0xffffffffffffffff
74− }
75−
76−-- | Haskell lexer.
77−
78−pLexer :: L.P [L.Token]
79−pLexer = go
80− where
81− go = do
82− r <- L.lexer False return
83− case unLoc r of
84− L.ITeof -> return []
85− x -> (x:) <$> go
src/Ormolu/Parser/Pragma.hsnew file+89
@@ -0,0 +1,89 @@
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+
4+-- | A module for parsing of pragmas from comments.
5+module Ormolu.Parser.Pragma
6+ ( Pragma (..),
7+ parsePragma,
8+ )
9+where
10+
11+import Control.Monad
12+import Data.Char (isSpace, toLower)
13+import qualified Data.List as L
14+import qualified EnumSet as ES
15+import FastString (mkFastString, unpackFS)
16+import qualified Lexer as L
17+import Module (ComponentId (..), newSimpleUnitId)
18+import SrcLoc
19+import StringBuffer
20+
21+-- | Ormolu's representation of pragmas.
22+data Pragma
23+ = -- | Language pragma
24+ PragmaLanguage [String]
25+ | -- | GHC options pragma
26+ PragmaOptionsGHC String
27+ | -- | Haddock options pragma
28+ PragmaOptionsHaddock String
29+ deriving (Show, Eq)
30+
31+-- | Extract a pragma from a comment if possible, or return 'Nothing'
32+-- otherwise.
33+parsePragma ::
34+ -- | Comment to try to parse
35+ String ->
36+ Maybe Pragma
37+parsePragma input = do
38+ inputNoPrefix <- L.stripPrefix "{-#" input
39+ guard ("#-}" `L.isSuffixOf` input)
40+ let contents = take (length inputNoPrefix - 3) inputNoPrefix
41+ (pragmaName, cs) = (break isSpace . dropWhile isSpace) contents
42+ case toLower <$> pragmaName of
43+ "language" -> PragmaLanguage <$> parseExtensions cs
44+ "options_ghc" -> Just $ PragmaOptionsGHC (trimSpaces cs)
45+ "options_haddock" -> Just $ PragmaOptionsHaddock (trimSpaces cs)
46+ _ -> Nothing
47+ where
48+ trimSpaces :: String -> String
49+ trimSpaces = L.dropWhileEnd isSpace . dropWhile isSpace
50+
51+-- | Assuming the input consists of a series of tokens from a language
52+-- pragma, return the set of enabled extensions.
53+parseExtensions :: String -> Maybe [String]
54+parseExtensions str = tokenize str >>= go
55+ where
56+ go = \case
57+ [L.ITconid ext] -> return [unpackFS ext]
58+ (L.ITconid ext : L.ITcomma : xs) -> (unpackFS ext :) <$> go xs
59+ _ -> Nothing
60+
61+-- | Tokenize a given input using GHC's lexer.
62+tokenize :: String -> Maybe [L.Token]
63+tokenize input =
64+ case L.unP pLexer parseState of
65+ L.PFailed {} -> Nothing
66+ L.POk _ x -> Just x
67+ where
68+ location = mkRealSrcLoc (mkFastString "") 1 1
69+ buffer = stringToStringBuffer input
70+ parseState = L.mkPStatePure parserFlags buffer location
71+ parserFlags =
72+ L.mkParserFlags'
73+ ES.empty
74+ ES.empty
75+ (newSimpleUnitId (ComponentId (mkFastString "")))
76+ True
77+ True
78+ True
79+ True
80+
81+-- | Haskell lexer.
82+pLexer :: L.P [L.Token]
83+pLexer = go
84+ where
85+ go = do
86+ r <- L.lexer False return
87+ case unLoc r of
88+ L.ITeof -> return []
89+ x -> (x :) <$> go
src/Ormolu/Parser/Result.hs+35−21
@@ -1,37 +1,51 @@
1−-- | A type for result of parsing.
2−
3{-# LANGUAGE RecordWildCards #-}
1{-# LANGUAGE RecordWildCards #-}
4
2
3+-- | A type for result of parsing.
5module Ormolu.Parser.Result
4module Ormolu.Parser.Result
6− ( ParseResult (..)
5+ ( ParseResult (..),
7− , prettyPrintParseResult
6+ prettyPrintParseResult,
8 )
7 )
9where
8where
10
9
11−import Data.Set (Set)
10+import Data.Text (Text)
12import GHC
11import GHC
13import Ormolu.Parser.Anns
12import Ormolu.Parser.Anns
14import Ormolu.Parser.CommentStream
13import Ormolu.Parser.CommentStream
14+import Ormolu.Parser.Pragma (Pragma)
15+import Ormolu.Parser.Shebang (Shebang)
15
16
16-- | A collection of data that represents a parsed module in Ormolu.
17-- | A collection of data that represents a parsed module in Ormolu.
17−
18data ParseResult = ParseResult
18data ParseResult = ParseResult
19− { prParsedSource :: ParsedSource
20− -- ^ 'ParsedSource' from GHC
19+ { -- | 'ParsedSource' from GHC
21− , prAnns :: Anns
20+ prParsedSource :: HsModule GhcPs,
22− -- ^ Ormolu-specfic representation of annotations
21+ -- | Ormolu-specfic representation of annotations
22+ 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
23− , prCommentStream :: CommentStream
30+ prCommentStream :: CommentStream,
24− -- ^ Comment stream
31+ -- | Whether or not record dot syntax is enabled
25− , prExtensions :: Set String
32+ prUseRecordDot :: Bool,
26− -- ^ Extensions enabled in that module
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
27 }
41 }
28
42
29-- | Pretty-print a 'ParseResult'.
43-- | Pretty-print a 'ParseResult'.
30−
31prettyPrintParseResult :: ParseResult -> String
44prettyPrintParseResult :: ParseResult -> String
32−prettyPrintParseResult ParseResult {..} = unlines
45+prettyPrintParseResult ParseResult {..} =
46+ unlines
33− [ "parse result:"
47+ [ "parse result:",
34− , " comment stream:"
48+ " comment stream:",
35− , showCommentStream prCommentStream
49+ showCommentStream prCommentStream
36− -- XXX extend as needed
50+ -- XXX extend as needed
37− ]
51+ ]
src/Ormolu/Parser/Shebang.hsnew file+27
@@ -0,0 +1,27 @@
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+25−16
@@ -1,11 +1,8 @@
1−{-# LANGUAGE LambdaCase #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
1+{-# LANGUAGE RecordWildCards #-}
4
2
5-- | Pretty-printer for Haskell AST.
3-- | Pretty-printer for Haskell AST.
6−
7module Ormolu.Printer
4module Ormolu.Printer
8− ( printModule
5+ ( printModule,
9 )
6 )
10where
7where
11
8
@@ -14,16 +11,28 @@ import Ormolu.Parser.Result
14import Ormolu.Printer.Combinators
11import Ormolu.Printer.Combinators
15import Ormolu.Printer.Meat.Module
12import Ormolu.Printer.Meat.Module
16import Ormolu.Printer.SpanStream
13import Ormolu.Printer.SpanStream
14+import Ormolu.Processing.Postprocess (postprocess)
17
15
18-- | Render a module.
16-- | Render a module.
19−
20−printModule
17+printModule ::
21− :: Bool -- ^ Whether to trace debugging information
22− -> ParseResult -- ^ Result of parsing
18+ -- | Result of parsing
19+ ParseResult ->
23− -> Text -- ^ Resulting rendition
20+ -- | Resulting rendition
21+ Text
24−printModule debugOn ParseResult {..} =
22+printModule ParseResult {..} =
23+ prLiteralPrefix <> region <> prLiteralSuffix
24+ where
25+ region =
26+ postprocess prIndent $
25− runR debugOn
27+ runR
28+ ( p_hsModule
29+ prStackHeader
30+ prShebangs
31+ prPragmas
32+ prImportQualifiedPost
26− (p_hsModule prExtensions prParsedSource)
33+ prParsedSource
34+ )
27− (mkSpanStream prParsedSource)
35+ (mkSpanStream prParsedSource)
28− prCommentStream
36+ prCommentStream
29− prAnns
37+ prAnns
38+ prUseRecordDot
src/Ormolu/Printer/Combinators.hs+203−223
@@ -1,147 +1,142 @@
1+{-# LANGUAGE FlexibleContexts #-}
2+{-# LANGUAGE GADTs #-}
1−{-# LANGUAGE LambdaCase #-}
3+{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
4{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
4
5
5-- | Printing combinators. The definitions here are presented in such an
6-- | Printing combinators. The definitions here are presented in such an
6-- order so you can just go through the Haddocks and by the end of the file
7-- order so you can just go through the Haddocks and by the end of the file
7-- you should have a pretty good idea how to program rendering logic.
8-- you should have a pretty good idea how to program rendering logic.
8−
9module Ormolu.Printer.Combinators
9module Ormolu.Printer.Combinators
10 ( -- * The 'R' monad
10 ( -- * The 'R' monad
11− R
11+ R,
12− , runR
12+ runR,
13+ getAnns,
14+ getEnclosingSpan,
15+
13 -- * Combinators
16 -- * Combinators
17+
14 -- ** Basic
18 -- ** Basic
15− , txt
19+ txt,
16− , atom
20+ atom,
21+ space,
17− , newline
22+ newline,
18− , inci
23+ inci,
24+ inciIf,
19− , located
25+ located,
20− , locatedVia
21− , located'
26+ located',
22− , switchLayout
27+ switchLayout,
28+ Layout (..),
23− , vlayout
29+ vlayout,
30+ getLayout,
24− , breakpoint
31+ breakpoint,
25− , breakpoint'
32+ breakpoint',
33+
26 -- ** Formatting lists
34 -- ** Formatting lists
27− , velt
35+ sep,
28− , velt'
36+ sepSemi,
29− , withSep
37+ canUseBraces,
30− , spaceSep
38+ useBraces,
31− , newlineSep
39+ dontUseBraces,
40+
32 -- ** Wrapping
41 -- ** Wrapping
42+ BracketStyle (..),
33− , sitcc
43+ sitcc,
34− , line
35− , backticks
44+ backticks,
36− , banana
45+ banana,
37− , braces
46+ braces,
38− , brackets
47+ brackets,
39− , bracketsPar
40− , parens
48+ parens,
41− , parensHash
49+ parensHash,
42− , pragmaBraces
50+ pragmaBraces,
43− , pragma
51+ pragma,
52+
44 -- ** Literals
53 -- ** Literals
45− , comma
54+ comma,
46− , space
55+ commaDel,
56+ equals,
57+
58+ -- ** Stateful markers
59+ SpanMark (..),
60+ spanMarkSpan,
61+ HaddockStyle (..),
62+ setSpanMark,
63+ getSpanMark,
47 )
64 )
48where
65where
49
66
50−import Data.Data (Data)
67+import Control.Monad
51import Data.List (intersperse)
68import Data.List (intersperse)
52import Data.Text (Text)
69import Data.Text (Text)
53import Ormolu.Printer.Comments
70import Ormolu.Printer.Comments
54import Ormolu.Printer.Internal
71import Ormolu.Printer.Internal
55−import Ormolu.Utils (isModule)
56−import Outputable (Outputable (..), showSDocUnsafe)
57import SrcLoc
72import SrcLoc
58−import qualified Data.Text as T
59
73
60----------------------------------------------------------------------------
74----------------------------------------------------------------------------
61-- Basic
75-- Basic
62
76
63−-- | Output a fixed 'Text' fragment. The argument may not contain any line
77+-- | Indent the inner expression if the first argument is 'True'.
64−-- breaks or tab characters. 'txt' is used to output all sorts of “fixed”
78+inciIf ::
65−-- bits of syntax like keywords and pipes @|@ in functional dependencies.
79+ -- | Whether to indent
66−
80+ Bool ->
67−txt :: Text -> R ()
81+ -- | The expression to indent
68−txt t = ensureIndent >> spit t
82+ R () ->
69−
83+ R ()
70−-- | Output 'Outputable' fragment of AST. This can be used to output numeric
84+inciIf b m = if b then inci m else m
71−-- literals and similar. Everything that doesn't have inner structure but
72−-- does have an 'Outputable' instance.
73−
74−atom :: Outputable a => a -> R ()
75−atom = txt . T.pack . showSDocUnsafe . ppr
76
85
77-- | Enter a 'Located' entity. This combinator handles outputting comments
86-- | Enter a 'Located' entity. This combinator handles outputting comments
78-- and sets layout (single-line vs multi-line) for the inner computation.
87-- and sets layout (single-line vs multi-line) for the inner computation.
79-- Roughly, the rule for using 'located' is that every time there is a
88-- Roughly, the rule for using 'located' is that every time there is a
80-- 'Located' wrapper, it should be “discharged” with a corresponding
89-- 'Located' wrapper, it should be “discharged” with a corresponding
81-- 'located' invocation.
90-- 'located' invocation.
82−
83−located
91+located ::
84− :: Data a
85− => Located a -- ^ Thing to enter
92+ -- | Thing to enter
93+ Located a ->
86− -> (a -> R ()) -- ^ How to render inner value
94+ -- | How to render inner value
87− -> R ()
95+ (a -> R ()) ->
88−located loc@(L l _) = locatedVia (Just l) loc
96+ R ()
89−
97+located (L (UnhelpfulSpan _) a) f = f a
90−-- | A special version of 'located' that allows to control layout using an
98+located (L (RealSrcSpan l) a) f = do
91−-- externally provided span. 'Nothing' means that layout won't be changed.
92−
93−locatedVia
94− :: Data a
95− => Maybe SrcSpan -- ^ Span that controls layout selection
96− -> Located a -- ^ Thing to enter
97− -> (a -> R ()) -- ^ How to render inner value
98− -> R ()
99−locatedVia ml loc f = do
100− let withRealLocated (L l a) g =
101− case l of
102− UnhelpfulSpan _ -> return ()
103− RealSrcSpan l' -> g (L l' a)
104− withRealLocated loc spitPrecedingComments
99+ spitPrecedingComments l
105− let setEnclosingSpan =
106− case getLoc loc of
107− UnhelpfulSpan _ -> id
108− RealSrcSpan orf ->
109− if isModule (unLoc loc)
110− then id
111− else withEnclosingSpan orf
100+ withEnclosingSpan l $
112− setEnclosingSpan $ case ml of
113− Nothing -> f (unLoc loc)
114− Just l' -> switchLayout l' (f (unLoc loc))
101+ switchLayout [RealSrcSpan l] (f a)
115− withRealLocated loc spitFollowingComments
102+ spitFollowingComments l
116
103
117-- | A version of 'located' with arguments flipped.
104-- | A version of 'located' with arguments flipped.
118−
119−located'
105+located' ::
120− :: Data a
121− => (a -> R ()) -- ^ How to render inner value
106+ -- | How to render inner value
107+ (a -> R ()) ->
122− -> Located a -- ^ Thing to enter
108+ -- | Thing to enter
109+ Located a ->
123− -> R ()
110+ R ()
124located' = flip located
111located' = flip located
125
112
126−-- | Set layout according to given 'SrcSpan' for a given computation. Use
113+-- | Set layout according to combination of given 'SrcSpan's for a given.
127−-- this only when you need to set layout based on e.g. combined span of
114+-- Use this only when you need to set layout based on e.g. combined span of
128-- several elements when there is no corresponding 'Located' wrapper
115-- several elements when there is no corresponding 'Located' wrapper
129-- provided by GHC AST. It is relatively rare that this one is needed.
116-- provided by GHC AST. It is relatively rare that this one is needed.
130−
117+--
118+-- Given empty list this function will set layout to single line.
131−switchLayout
119+switchLayout ::
132− :: SrcSpan -- ^ Span that controls layout
120+ -- | Span that controls layout
121+ [SrcSpan] ->
133− -> R () -- ^ Computation to run with changed layout
122+ -- | Computation to run with changed layout
123+ R () ->
134− -> R ()
124+ R ()
135−switchLayout spn = enterLayout
125+switchLayout spans' = enterLayout (spansLayout spans')
126+
127+-- | Which layout combined spans result in?
128+spansLayout :: [SrcSpan] -> Layout
129+spansLayout = \case
130+ [] -> SingleLine
131+ (x : xs) ->
136− (if isOneLineSpan spn
132+ if isOneLineSpan (foldr combineSrcSpans x xs)
137− then SingleLine
133+ then SingleLine
138− else MultiLine)
134+ else MultiLine
139
135
140-- | Insert a space if enclosing layout is single-line, or newline if it's
136-- | Insert a space if enclosing layout is single-line, or newline if it's
141-- multiline.
137-- multiline.
142--
138--
143-- > breakpoint = vlayout space newline
139-- > breakpoint = vlayout space newline
144−
145breakpoint :: R ()
140breakpoint :: R ()
146breakpoint = vlayout space newline
141breakpoint = vlayout space newline
147
142
@@ -149,80 +144,68 @@ breakpoint = vlayout space newline
149-- layout.
144-- layout.
150--
145--
151-- > breakpoint' = vlayout (return ()) newline
146-- > breakpoint' = vlayout (return ()) newline
152−
153breakpoint' :: R ()
147breakpoint' :: R ()
154breakpoint' = vlayout (return ()) newline
148breakpoint' = vlayout (return ()) newline
155
149
156----------------------------------------------------------------------------
150----------------------------------------------------------------------------
157-- Formatting lists
151-- Formatting lists
158
152
159−-- | Element of variable layout. This means that the sub-components may be
153+-- | Render a collection of elements inserting a separator between them.
160−-- rendered either on single line or each on its own line depending on
154+sep ::
161−-- current layout.
155+ -- | Separator
156+ R () ->
157+ -- | How to render an element
158+ (a -> R ()) ->
159+ -- | Elements to render
160+ [a] ->
161+ R ()
162+sep s f xs = sequence_ (intersperse s (f <$> xs))
163+
164+-- | Render a collection of elements layout-sensitively using given printer,
165+-- inserting semicolons if necessary and respecting 'useBraces' and
166+-- 'dontUseBraces' combinators.
162--
167--
163−-- This version does not make subsequent element (second and later) align
168+-- > useBraces $ sepSemi txt ["foo", "bar"]
164−-- with the first automatically and does not insert spaces between elements
169+-- > == vlayout (txt "{ foo; bar }") (txt "foo\nbar")
165−-- when layout is single line.
166−
167−velt :: [R ()] -> R ()
168−velt xs = sequence_ (intersperse breakpoint' (sitcc <$> xs))
169−
170−-- | Like 'velt', but all sub-elements start at the same indentation level
171−-- as first element, additionally spaces are inserted when layout is single
172−-- line.
173−
174−velt' :: [R ()] -> R ()
175−velt' xs = sitcc $ sequence_ (intersperse breakpoint (sitcc <$> xs))
176−
177−-- | Put separator between renderings of items of a list.
178−
179−withSep
180− :: R () -- ^ Separator
181− -> (a -> R ()) -- ^ How to render list items
182− -> [a] -- ^ List to render
183− -> [R ()] -- ^ List of printing actions
184−withSep sep f = \case
185− [] -> []
186− (x:xs) ->
187− let g a = sep >> f a
188− in f x : fmap g xs
189−
190−-- | Render space-separated elements.
191--
170--
192−-- > spaceSep f = sequence_ . withSep space f
171+-- > dontUseBraces $ sepSemi txt ["foo", "bar"]
193−
172+-- > == vlayout (txt "foo; bar") (txt "foo\nbar")
194−spaceSep
173+sepSemi ::
195− :: (a -> R ()) -- ^ How to render list items
174+ -- | How to render an element
196− -> [a] -- ^ List to render
175+ (a -> R ()) ->
197− -> R ()
176+ -- | Elements to render
198−spaceSep f = sequence_ . withSep space f
177+ [a] ->
199−
178+ R ()
200−-- | Render newline-separated elements.
179+sepSemi f xs = vlayout singleLine multiLine
201−--
180+ where
202−-- > newlineSep f = sequence_ . withSep newline f
181+ singleLine = do
203−
182+ ub <- canUseBraces
204−newlineSep
183+ case xs of
205− :: (a -> R ()) -- ^ How to render list items
184+ [] -> when ub $ txt "{}"
206− -> [a] -- ^ List to render
185+ xs' ->
207− -> R ()
186+ if ub
208−newlineSep f = sequence_ . withSep newline f
187+ then do
188+ txt "{"
189+ space
190+ sep (txt ";" >> space) (dontUseBraces . f) xs'
191+ space
192+ txt "}"
193+ else sep (txt ";" >> space) f xs'
194+ multiLine =
195+ sep newline (dontUseBraces . f) xs
209
196
210----------------------------------------------------------------------------
197----------------------------------------------------------------------------
211-- Wrapping
198-- Wrapping
212
199
213−-- | Finish given entity by a 'newline'.
200+-- | 'BracketStyle' controlling how closing bracket is rendered.
214−--
201+data BracketStyle
215−-- > line m = do
202+ = -- | Normal
216−-- > m
203+ N
217−-- > newline
204+ | -- | Shifted one level
218−
205+ S
219−line :: R () -> R ()
206+ deriving (Eq, Show)
220−line m = do
221− m
222− newline
223
207
224-- | Surround given entity by backticks.
208-- | Surround given entity by backticks.
225−
226backticks :: R () -> R ()
209backticks :: R () -> R ()
227backticks m = do
210backticks m = do
228 txt "`"
211 txt "`"
@@ -230,89 +213,86 @@ backticks m = do
230 txt "`"
213 txt "`"
231
214
232-- | Surround given entity by banana brackets (i.e., from arrow notation.)
215-- | Surround given entity by banana brackets (i.e., from arrow notation.)
233−
234banana :: R () -> R ()
216banana :: R () -> R ()
235−banana m = sitcc $ do
217+banana = brackets_ True "(|" "|)" N
236− txt "(|"
237− ospaces m
238− txt "|)"
239
218
240-- | Surround given entity by curly braces @{@ and @}@.
219-- | Surround given entity by curly braces @{@ and @}@.
241−
220+braces :: BracketStyle -> R () -> R ()
242−braces :: R () -> R ()
221+braces = brackets_ False "{" "}"
243−braces m = sitcc $ do
244− txt "{"
245− ospaces m
246− txt "}"
247
222
248-- | Surround given entity by square brackets @[@ and @]@.
223-- | Surround given entity by square brackets @[@ and @]@.
249−
224+brackets :: BracketStyle -> R () -> R ()
250−brackets :: R () -> R ()
225+brackets = brackets_ False "[" "]"
251−brackets m = sitcc $ do
252− txt "["
253− ospaces m
254− txt "]"
255−
256−-- | Surround given entity by parallel array brackets @[:@ and @:]@.
257−
258−bracketsPar :: R () -> R ()
259−bracketsPar m = sitcc $ do
260− txt "[: "
261− m
262− txt " :]"
263
226
264-- | Surround given entity by parentheses @(@ and @)@.
227-- | Surround given entity by parentheses @(@ and @)@.
265−
228+parens :: BracketStyle -> R () -> R ()
266−parens :: R () -> R ()
229+parens = brackets_ False "(" ")"
267−parens m = sitcc $ do
268− txt "("
269− ospaces m
270− txt ")"
271
230
272-- | Surround given entity by @(# @ and @ #)@.
231-- | Surround given entity by @(# @ and @ #)@.
273−
232+parensHash :: BracketStyle -> R () -> R ()
274−parensHash :: R () -> R ()
233+parensHash = brackets_ True "(#" "#)"
275−parensHash m = sitcc $ do
276− txt "(# "
277− m
278− breakpoint
279− txt "#)"
280
234
281-- | Braces as used for pragmas: @{-#@ and @#-}@.
235-- | Braces as used for pragmas: @{-#@ and @#-}@.
282−
283pragmaBraces :: R () -> R ()
236pragmaBraces :: R () -> R ()
284pragmaBraces m = sitcc $ do
237pragmaBraces m = sitcc $ do
285− txt "{-# "
238+ txt "{-#"
239+ space
286 m
240 m
287− vlayout space (newline >> txt " ")
241+ breakpoint
288− txt "#-}"
242+ inci (txt "#-}")
289
243
290-- | Surround the body with a pragma name and 'pragmaBraces'.
244-- | Surround the body with a pragma name and 'pragmaBraces'.
291−
245+pragma ::
292−pragma
246+ -- | Pragma text
293− :: Text -- ^ Pragma text
247+ Text ->
294− -> R () -- ^ Pragma body
248+ -- | Pragma body
295− -> R ()
249+ R () ->
250+ R ()
296pragma pragmaText body = pragmaBraces $ do
251pragma pragmaText body = pragmaBraces $ do
297 txt pragmaText
252 txt pragmaText
298 breakpoint
253 breakpoint
299− inci body
254+ body
300−
255+
301−-- | Surround given entity by optional space before and a newline after, iff
256+-- | A helper for defining wrappers like 'parens' and 'braces'.
302−-- current layout is multiline.
257+brackets_ ::
303−
258+ -- | Insert breakpoints around brackets
304−ospaces :: R () -> R ()
259+ Bool ->
305−ospaces m = vlayout m (txt " " >> m >> newline)
260+ -- | Opening bracket
261+ Text ->
262+ -- | Closing bracket
263+ Text ->
264+ -- | Bracket style
265+ BracketStyle ->
266+ -- | Inner expression
267+ R () ->
268+ R ()
269+brackets_ needBreaks open close style m = sitcc (vlayout singleLine multiLine)
270+ where
271+ singleLine = do
272+ txt open
273+ when needBreaks space
274+ m
275+ when needBreaks space
276+ txt close
277+ multiLine = do
278+ txt open
279+ if needBreaks
280+ then newline >> inci m
281+ else space >> sitcc m
282+ newline
283+ inciIf (style == S) (txt close)
306
284
307----------------------------------------------------------------------------
285----------------------------------------------------------------------------
308-- Literals
286-- Literals
309
287
310−-- | Print @,@ followed by a space.
288+-- | Print @,@.
311−
312comma :: R ()
289comma :: R ()
313−comma = txt ", "
290+comma = txt ","
314
291
315−-- | Print single space.
292+-- | Delimiting combination with 'comma'. To be used with 'sep'.
293+commaDel :: R ()
294+commaDel = comma >> breakpoint
316
295
317−space :: R ()
296+-- | Print @=@. Do not use @'txt' "="@.
318−space = txt " "
297+equals :: R ()
298+equals = interferingTxt "="
src/Ormolu/Printer/Comments.hs+195−124
@@ -1,184 +1,215 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3
3
4-- | Helpers for formatting of comments. This is low-level code, use
4-- | Helpers for formatting of comments. This is low-level code, use
5-- "Ormolu.Printer.Combinators" unless you know what you are doing.
5-- "Ormolu.Printer.Combinators" unless you know what you are doing.
6−
7module Ormolu.Printer.Comments
6module Ormolu.Printer.Comments
8− ( spitPrecedingComments
7+ ( spitPrecedingComments,
9− , spitFollowingComments
8+ spitFollowingComments,
10− , spitRemainingComments
9+ spitRemainingComments,
11− , hasMoreComments
10+ spitCommentNow,
11+ spitCommentPending,
12 )
12 )
13where
13where
14
14
15import Control.Monad
15import Control.Monad
16−import Data.Coerce (coerce)
16+import qualified Data.List.NonEmpty as NE
17−import Data.Data (Data)
17+import Data.Maybe (listToMaybe)
18+import qualified Data.Text as T
18import Ormolu.Parser.CommentStream
19import Ormolu.Parser.CommentStream
19import Ormolu.Printer.Internal
20import Ormolu.Printer.Internal
20−import Ormolu.Utils (isModule)
21import SrcLoc
21import SrcLoc
22−import qualified Data.List.NonEmpty as NE
23−import qualified Data.Text as T
24
22
25----------------------------------------------------------------------------
23----------------------------------------------------------------------------
26-- Top-level
24-- Top-level
27
25
28-- | Output all preceding comments for an element at given location.
26-- | Output all preceding comments for an element at given location.
29−
27+spitPrecedingComments ::
30−spitPrecedingComments
28+ -- | Span of the element to attach comments to
31− :: Data a
29+ RealSrcSpan ->
32− => RealLocated a -- ^ AST element to attach comments to
30+ R ()
33− -> R ()
31+spitPrecedingComments ref = do
34−spitPrecedingComments = handleCommentSeries . spitPrecedingComment
32+ gotSome <- handleCommentSeries (spitPrecedingComment ref)
33+ when gotSome $ do
34+ lastMark <- getSpanMark
35+ -- Insert a blank line between the preceding comments and the thing
36+ -- after them if there was a blank line in the input.
37+ when (needsNewlineBefore ref lastMark) newline
35
38
36-- | Output all comments following an element at given location.
39-- | Output all comments following an element at given location.
37−
40+spitFollowingComments ::
38−spitFollowingComments
41+ -- | Span of the element to attach comments to
39− :: Data a
42+ RealSrcSpan ->
40− => RealLocated a -- ^ AST element of attach comments to
43+ R ()
41− -> R ()
42spitFollowingComments ref = do
44spitFollowingComments ref = do
43− trimSpanStream (getLoc ref)
45+ trimSpanStream ref
44− handleCommentSeries (spitFollowingComment ref)
46+ void $ handleCommentSeries (spitFollowingComment ref)
45
47
46-- | Output all remaining comments in the comment stream.
48-- | Output all remaining comments in the comment stream.
47−
48spitRemainingComments :: R ()
49spitRemainingComments :: R ()
49−spitRemainingComments = handleCommentSeries spitRemainingComment
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
50
55
51----------------------------------------------------------------------------
56----------------------------------------------------------------------------
52-- Single-comment functions
57-- Single-comment functions
53
58
54-- | Output a single preceding comment for an element at given location.
59-- | Output a single preceding comment for an element at given location.
55−
60+spitPrecedingComment ::
56−spitPrecedingComment
61+ -- | Span of the element to attach comments to
57− :: Data a
62+ RealSrcSpan ->
58− => RealLocated a -- ^ AST element to attach comments to
63+ -- | Are we done?
59− -> Maybe RealSrcSpan -- ^ Location of last comment in the series
64+ R Bool
60− -> R (Maybe RealSrcSpan) -- ^ Location of this comment
65+spitPrecedingComment ref = do
61−spitPrecedingComment (L ref a) mlastSpn = do
66+ mlastMark <- getSpanMark
62 let p (L l _) = realSrcSpanEnd l <= realSrcSpanStart ref
67 let p (L l _) = realSrcSpanEnd l <= realSrcSpanStart ref
63 withPoppedComment p $ \l comment -> do
68 withPoppedComment p $ \l comment -> do
64− when (needsNewlineBefore l mlastSpn) newline
69+ lineSpans <- thisLineSpans
65− spitComment comment
70+ let thisCommentLine = srcLocLine (realSrcSpanStart l)
66− if theSameLine l ref && not (isModule a)
71+ needsNewline =
67− then spit " "
72+ case listToMaybe lineSpans of
73+ Nothing -> False
74+ Just spn -> srcLocLine (realSrcSpanEnd spn) /= thisCommentLine
75+ when (needsNewline || needsNewlineBefore l mlastMark) newline
76+ spitCommentNow l comment
77+ if theSameLinePre l ref
78+ then space
68 else newline
79 else newline
69
80
70-- | Output a comment that follows element at given location immediately on
81-- | Output a comment that follows element at given location immediately on
71-- the same line, if there is any.
82-- the same line, if there is any.
72−
83+spitFollowingComment ::
73−spitFollowingComment
84+ -- | AST element to attach comments to
74− :: Data a
85+ RealSrcSpan ->
75− => RealLocated a -- ^ AST element to attach comments to
86+ -- | Are we done?
76− -> Maybe RealSrcSpan -- ^ Location of last comment in the series
87+ R Bool
77− -> R (Maybe RealSrcSpan) -- ^ Location of this comment
88+spitFollowingComment ref = do
78−spitFollowingComment (L ref a) mlastSpn = do
89+ mlastMark <- getSpanMark
79 mnSpn <- nextEltSpan
90 mnSpn <- nextEltSpan
80− meSpn <- getEnclosingSpan ref
91+ -- Get first enclosing span that is not equal to reference span, i.e. it's
81− i <- getIndent
92+ -- truly something enclosing the AST element.
82− withPoppedComment (commentFollowsElt ref mnSpn meSpn mlastSpn) $ \l comment ->
93+ meSpn <- getEnclosingSpan (/= ref)
83− if theSameLine l ref && not (isModule a)
94+ withPoppedComment (commentFollowsElt ref mnSpn meSpn mlastMark) $ \l comment ->
84− then modNewline $ \m -> setIndent i $ do
95+ if theSameLinePost l ref
85− spit " "
96+ then
86− spitComment comment
97+ if isMultilineComment comment
87− m
98+ then space >> spitCommentNow l comment
88− else modNewline $ \m -> setIndent i $ do
99+ else spitCommentPending OnTheSameLine l comment
89− m
100+ else do
90− when (needsNewlineBefore l mlastSpn) newline
101+ when (needsNewlineBefore l mlastMark) $
91− spitComment comment
102+ registerPendingCommentLine OnNextLine ""
92− newline
103+ spitCommentPending OnNextLine l comment
93
104
94-- | Output a single remaining comment from the comment stream.
105-- | Output a single remaining comment from the comment stream.
95−
106+spitRemainingComment ::
96−spitRemainingComment
107+ -- | Are we done?
97− :: Maybe RealSrcSpan -- ^ Location of last comment in the series
108+ R Bool
98− -> R (Maybe RealSrcSpan) -- ^ Location of this comment
109+spitRemainingComment = do
99−spitRemainingComment mlastSpn =
110+ mlastMark <- getSpanMark
100 withPoppedComment (const True) $ \l comment -> do
111 withPoppedComment (const True) $ \l comment -> do
101− when (needsNewlineBefore l mlastSpn) newline
112+ when (needsNewlineBefore l mlastMark) newline
102− spitComment comment
113+ spitCommentNow l comment
103 newline
114 newline
104
115
105----------------------------------------------------------------------------
116----------------------------------------------------------------------------
106-- Helpers
117-- Helpers
107
118
108-- | Output series of comments.
119-- | Output series of comments.
109−
120+handleCommentSeries ::
110−handleCommentSeries
121+ -- | Given location of previous comment, output the next comment
111− :: (Maybe RealSrcSpan -> R (Maybe RealSrcSpan))
122+ -- returning 'True' if we're done
112− -- ^ Given location of previous comment, output the next comment
123+ R Bool ->
113− -- returning its location, or 'Nothing' if we are done
124+ -- | Whether we printed any comments
114− -> R ()
125+ R Bool
115−handleCommentSeries f = go Nothing
126+handleCommentSeries f = go False
116 where
127 where
117− go mlastSpn = do
128+ go gotSome = do
118− r <- f mlastSpn
129+ done <- f
119− case r of
130+ if done
120− Nothing -> return ()
131+ then return gotSome
121− Just spn -> go (Just spn)
132+ else go True
122
133
123-- | Try to pop a comment using given predicate and if there is a comment
134-- | Try to pop a comment using given predicate and if there is a comment
124-- matching the predicate, print it out.
135-- matching the predicate, print it out.
125−
136+withPoppedComment ::
126−withPoppedComment
137+ -- | Comment predicate
127− :: (RealLocated Comment -> Bool) -- ^ Comment predicate
138+ (RealLocated Comment -> Bool) ->
128− -> (RealSrcSpan -> Comment -> R ()) -- ^ Priting function
139+ -- | Printing function
129− -> R (Maybe RealSrcSpan)
140+ (RealSrcSpan -> Comment -> R ()) ->
141+ -- | Are we done?
142+ R Bool
130withPoppedComment p f = do
143withPoppedComment p f = do
131 r <- popComment p
144 r <- popComment p
132 case r of
145 case r of
133− Nothing -> return Nothing
146+ Nothing -> return True
134− Just (L l comment) -> Just l <$ f l comment
147+ Just (L l comment) -> False <$ f l comment
135
148
136-- | Determine if we need to insert a newline between current comment and
149-- | Determine if we need to insert a newline between current comment and
137-- last printed comment.
150-- last printed comment.
138−
151+needsNewlineBefore ::
139−needsNewlineBefore
152+ -- | Current comment span
140− :: RealSrcSpan -- ^ Current comment span
153+ RealSrcSpan ->
141− -> Maybe RealSrcSpan -- ^ Last printed comment span
154+ -- | Last printed comment span
142− -> Bool
155+ Maybe SpanMark ->
143−needsNewlineBefore l mlastSpn =
156+ Bool
144− case mlastSpn of
157+needsNewlineBefore _ (Just (HaddockSpan _ _)) = True
158+needsNewlineBefore l mlastMark =
159+ case spanMarkSpan <$> mlastMark of
145 Nothing -> False
160 Nothing -> False
146− Just lastSpn ->
161+ Just lastMark ->
147− srcSpanStartLine l > srcSpanEndLine lastSpn + 1
162+ srcSpanStartLine l > srcSpanEndLine lastMark + 1
148
163
149−-- | Is the comment and AST element are on the same line?
164+-- | Is the preceding comment and AST element are on the same line?
150−
165+theSameLinePre ::
151−theSameLine
166+ -- | Current comment span
152− :: RealSrcSpan -- ^ Current comment span
167+ RealSrcSpan ->
153− -> RealSrcSpan -- ^ AST element location
168+ -- | AST element location
154− -> Bool
169+ RealSrcSpan ->
155−theSameLine l ref =
170+ Bool
171+theSameLinePre l ref =
156 srcSpanEndLine l == srcSpanStartLine ref
172 srcSpanEndLine l == srcSpanStartLine ref
157
173
158−-- | Determine if given comment follows AST element.
174+-- | Is the following comment and AST element are on the same line?
175+theSameLinePost ::
176+ -- | Current comment span
177+ RealSrcSpan ->
178+ -- | AST element location
179+ RealSrcSpan ->
180+ Bool
181+theSameLinePost l ref =
182+ srcSpanStartLine l == srcSpanEndLine ref
159
183
160−commentFollowsElt
184+-- | Determine if given comment follows AST element.
161− :: RealSrcSpan -- ^ Location of AST element
185+commentFollowsElt ::
162− -> Maybe RealSrcSpan -- ^ Location of next AST element
186+ -- | Location of AST element
163− -> Maybe RealSrcSpan -- ^ Location of enclosing AST element
187+ RealSrcSpan ->
164− -> Maybe RealSrcSpan -- ^ Location of last comment in the series
188+ -- | Location of next AST element
165− -> RealLocated Comment -- ^ Comment to test
189+ Maybe RealSrcSpan ->
166− -> Bool
190+ -- | Location of enclosing AST element
167−commentFollowsElt ref mnSpn meSpn mlastSpn (L l comment) =
191+ Maybe RealSrcSpan ->
192+ -- | Location of last comment in the series
193+ Maybe SpanMark ->
194+ -- | Comment to test
195+ RealLocated Comment ->
196+ Bool
197+commentFollowsElt ref mnSpn meSpn mlastMark (L l comment) =
168 -- A comment follows a AST element if all 4 conditions are satisfied:
198 -- A comment follows a AST element if all 4 conditions are satisfied:
169 goesAfter
199 goesAfter
170 && logicallyFollows
200 && logicallyFollows
171 && noEltBetween
201 && noEltBetween
172− && (continuation || supersedesParentElt)
202+ && (continuation || lastInEnclosing || supersedesParentElt)
173 where
203 where
174 -- 1) The comment starts after end of the AST element:
204 -- 1) The comment starts after end of the AST element:
175 goesAfter =
205 goesAfter =
176 realSrcSpanStart l >= realSrcSpanEnd ref
206 realSrcSpanStart l >= realSrcSpanEnd ref
177− -- 2) The comment logically belongs to the element, three cases:
207+ -- 2) The comment logically belongs to the element, four cases:
178− logicallyFollows
208+ logicallyFollows =
179− = theSameLine l ref -- a) it's on the same line
209+ theSameLinePost l ref -- a) it's on the same line
180− || isPrevHaddock comment -- b) it's a Haddock string starting with -- ^
210+ || continuation -- b) it's a continuation of a comment block
181− || continuation -- c) it's a continuation of a comment block
211+ || lastInEnclosing -- c) it's the last element in the enclosing construct
212+
182 -- 3) There is no other AST element between this element and the comment:
213 -- 3) There is no other AST element between this element and the comment:
183 noEltBetween =
214 noEltBetween =
184 case mnSpn of
215 case mnSpn of
@@ -199,17 +230,57 @@ commentFollowsElt ref mnSpn meSpn mlastSpn (L l comment) =
199 Nothing -> True
230 Nothing -> True
200 Just espn ->
231 Just espn ->
201 let startColumn = srcLocCol . realSrcSpanStart
232 let startColumn = srcLocCol . realSrcSpanStart
202− in abs (startColumn espn - startColumn l)
233+ in startColumn espn > startColumn ref
203− >= abs (startColumn ref - startColumn l)
234+ || ( abs (startColumn espn - startColumn l)
235+ >= abs (startColumn ref - startColumn l)
236+ )
204 continuation =
237 continuation =
205− case mlastSpn of
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
242+ Just (HaddockSpan _ _) -> False
243+ Just (CommentSpan spn) ->
244+ srcSpanEndLine spn + 1 == srcSpanStartLine l
245+ _ -> False
246+ )
247+ lastInEnclosing =
248+ case meSpn of
249+ -- When there is no enclosing element, return false
206 Nothing -> False
250 Nothing -> False
207− Just spn -> srcSpanEndLine spn + 1 == srcSpanStartLine l
251+ -- When there is an enclosing element,
252+ Just espn ->
253+ let -- Make sure that the comment is inside the enclosing element
254+ insideParent = realSrcSpanEnd l <= realSrcSpanEnd espn
255+ -- And check if the next element is outside of the parent
256+ nextOutsideParent = case mnSpn of
257+ Nothing -> True
258+ Just nspn -> realSrcSpanEnd espn < realSrcSpanStart nspn
259+ in insideParent && nextOutsideParent
208
260
209−-- | Output a 'Comment'. This is a low-level printing function.
261+-- | Output a 'Comment' immediately. This is a low-level printing function.
262+spitCommentNow :: RealSrcSpan -> Comment -> R ()
263+spitCommentNow spn comment = do
264+ sitcc
265+ . sequence_
266+ . NE.intersperse newline
267+ . fmap (txt . T.pack)
268+ . unComment
269+ $ comment
270+ setSpanMark (CommentSpan spn)
210
271
211−spitComment :: Comment -> R ()
272+-- | Output a 'Comment' at the end of correct line or after it depending on
212−spitComment =
273+-- 'CommentPosition'. Used for comments that may potentially follow on the
213− sequence_ . NE.intersperse newline . fmap f . coerce
274+-- same line as something we just rendered, but not immediately after it.
214− where
275+spitCommentPending :: CommentPosition -> RealSrcSpan -> Comment -> R ()
215− f x = ensureIndent >> spit (T.pack x)
276+spitCommentPending position spn comment = do
277+ let wrapper = case position of
278+ OnTheSameLine -> sitcc
279+ OnNextLine -> id
280+ wrapper
281+ . sequence_
282+ . NE.toList
283+ . fmap (registerPendingCommentLine position . T.pack)
284+ . unComment
285+ $ comment
286+ setSpanMark (CommentSpan spn)
src/Ormolu/Printer/Internal.hs+447−243
@@ -1,373 +1,577 @@
1{-# LANGUAGE GeneralizedNewtypeDeriving #-}
1{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2−{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE LambdaCase #-}
3−{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE RankNTypes #-}
4+{-# LANGUAGE RankNTypes #-}
5
5
6-- | In most cases import "Ormolu.Printer.Combinators" instead, these
6-- | In most cases import "Ormolu.Printer.Combinators" instead, these
7-- functions are the low-level building blocks and should not be used on
7-- functions are the low-level building blocks and should not be used on
8-- their own. The 'R' monad is re-exported from "Ormolu.Printer.Combinators"
8-- their own. The 'R' monad is re-exported from "Ormolu.Printer.Combinators"
9-- as well.
9-- as well.
10−
11module Ormolu.Printer.Internal
10module Ormolu.Printer.Internal
12 ( -- * The 'R' monad
11 ( -- * The 'R' monad
13− R
12+ R,
14− , runR
13+ runR,
14+
15 -- * Internal functions
15 -- * Internal functions
16− , spit
16+ txt,
17− , newline
17+ interferingTxt,
18− , modNewline
18+ atom,
19− , ensureIndent
19+ space,
20− , inci
20+ newline,
21− , sitcc
21+ useRecordDot,
22− , Layout (..)
22+ inci,
23− , enterLayout
23+ sitcc,
24− , vlayout
24+ Layout (..),
25+ enterLayout,
26+ vlayout,
27+ getLayout,
28+
29+ -- * Helpers for braces
30+ useBraces,
31+ dontUseBraces,
32+ canUseBraces,
33+
25 -- * Special helpers for comment placement
34 -- * Special helpers for comment placement
26− , trimSpanStream
35+ CommentPosition (..),
27− , nextEltSpan
36+ registerPendingCommentLine,
28− , popComment
37+ trimSpanStream,
29− , hasMoreComments
38+ nextEltSpan,
30− , getIndent
39+ popComment,
31− , setIndent
40+ getEnclosingSpan,
32− , getEnclosingSpan
41+ withEnclosingSpan,
33− , withEnclosingSpan
42+ thisLineSpans,
43+
44+ -- * Stateful markers
45+ SpanMark (..),
46+ spanMarkSpan,
47+ HaddockStyle (..),
48+ setSpanMark,
49+ getSpanMark,
50+
34 -- * Annotations
51 -- * Annotations
35− , getAnns
52+ getAnns,
36 )
53 )
37where
54where
38
55
39import Control.Monad.Reader
56import Control.Monad.Reader
40import Control.Monad.State.Strict
57import Control.Monad.State.Strict
58+import Data.Bool (bool)
41import Data.Coerce
59import Data.Coerce
42import Data.Maybe (listToMaybe)
60import Data.Maybe (listToMaybe)
43import Data.Text (Text)
61import Data.Text (Text)
62+import qualified Data.Text as T
63+import qualified Data.Text.Lazy as TL
44import Data.Text.Lazy.Builder
64import Data.Text.Lazy.Builder
45−import Debug.Trace
46import GHC
65import GHC
47import Ormolu.Parser.Anns
66import Ormolu.Parser.Anns
48import Ormolu.Parser.CommentStream
67import Ormolu.Parser.CommentStream
49import Ormolu.Printer.SpanStream
68import Ormolu.Printer.SpanStream
50−import SrcLoc
69+import Ormolu.Utils (showOutputable)
51−import qualified Data.Text as T
70+import Outputable (Outputable)
52−import qualified Data.Text.Lazy as TL
53
71
54----------------------------------------------------------------------------
72----------------------------------------------------------------------------
55-- The 'R' monad
73-- The 'R' monad
56
74
57-- | The 'R' monad hosts combinators that allow us to describe how to render
75-- | The 'R' monad hosts combinators that allow us to describe how to render
58-- AST.
76-- AST.
59−
60newtype R a = R (ReaderT RC (State SC) a)
77newtype R a = R (ReaderT RC (State SC) a)
61 deriving (Functor, Applicative, Monad)
78 deriving (Functor, Applicative, Monad)
62
79
63−-- | Reader context of 'R'.
80+-- | Reader context of 'R'. This should be used when we control rendering by
64−
81+-- enclosing certain expressions with wrappers.
65data RC = RC
82data RC = RC
66− { rcIndent :: !Int
83+ { -- | Indentation level, as the column index we need to start from after
67− -- ^ Indentation level, as the column index we need to start from after a
84+ -- a newline if we break lines
68− -- newline if we break lines
85+ rcIndent :: !Int,
69− , rcLayout :: Layout
86+ -- | Current layout
70− -- ^ Current layout
87+ rcLayout :: Layout,
71− , rcRelaxedComments :: Bool
88+ -- | Spans of enclosing elements of AST
72− -- ^ Whether to relax aligning rules for comments
89+ rcEnclosingSpans :: [RealSrcSpan],
73− , rcDebug :: Bool
90+ -- | Collection of annotations
74− -- ^ Whether to print debugging info as we go
91+ rcAnns :: Anns,
75− , rcEnclosingSpans :: [RealSrcSpan]
92+ -- | Whether the last expression in the layout can use braces
76− -- ^ Span of enclosing element of AST
93+ rcCanUseBraces :: Bool,
77− , rcAnns :: Anns
94+ -- | Whether the source could have used the record dot preprocessor
78− -- ^ Collection of annotations
95+ rcUseRecDot :: Bool
79 }
96 }
80
97
81-- | State context of 'R'.
98-- | State context of 'R'.
82−
83data SC = SC
99data SC = SC
84− { scColumn :: !Int
100+ { -- | Index of the next column to render
85− -- ^ Index of the next column to render
101+ scColumn :: !Int,
86− , scBuilder :: Builder
102+ -- | Indentation level that was used for the current line
87− -- ^ Rendered source code so far
103+ scIndent :: !Int,
88− , scSpanStream :: SpanStream
104+ -- | Rendered source code so far
89− -- ^ Span stream
105+ scBuilder :: Builder,
90− , scCommentStream :: CommentStream
106+ -- | Span stream
91− -- ^ Comment stream
107+ scSpanStream :: SpanStream,
92− , scNewline :: R ()
108+ -- | Spans of atoms that have been printed on the current line so far
93− -- ^ What to render as newline
109+ scThisLineSpans :: [RealSrcSpan],
110+ -- | Comment stream
111+ scCommentStream :: CommentStream,
112+ -- | Pending comment lines (in reverse order) to be inserted before next
113+ -- newline, 'Int' is the indentation level
114+ scPendingComments :: ![(CommentPosition, Text)],
115+ -- | Whether to output a space before the next output
116+ scRequestedDelimiter :: !RequestedDelimiter,
117+ -- | An auxiliary marker for keeping track of last output element
118+ scSpanMark :: !(Maybe SpanMark)
94 }
119 }
95
120
96−-- | 'Layout' options.
121+-- | Make sure next output is delimited by one of the following.
122+data RequestedDelimiter
123+ = -- | A space
124+ RequestedSpace
125+ | -- | A newline
126+ RequestedNewline
127+ | -- | Nothing
128+ RequestedNothing
129+ | -- | We just output a newline
130+ AfterNewline
131+ | -- | We haven't printed anything yet
132+ VeryBeginning
133+ deriving (Eq, Show)
97
134
135+-- | 'Layout' options.
98data Layout
136data Layout
99− = SingleLine -- ^ Put everything on single line
137+ = -- | Put everything on single line
100− | MultiLine -- ^ Use multiple lines
138+ SingleLine
139+ | -- | Use multiple lines
140+ MultiLine
101 deriving (Eq, Show)
141 deriving (Eq, Show)
102
142
103−-- | Run an 'R' monad.
143+-- | Modes for rendering of pending comments.
144+data CommentPosition
145+ = -- | Put the comment on the same line
146+ OnTheSameLine
147+ | -- | Put the comment on next line
148+ OnNextLine
149+ deriving (Eq, Show)
104
150
105−runR
151+-- | Run an 'R' monad.
106− :: Bool -- ^ Whether to print debugging info
152+runR ::
107− -> R () -- ^ Monad to run
153+ -- | Monad to run
108− -> SpanStream -- ^ Span stream
154+ R () ->
109− -> CommentStream -- ^ Comment stream
155+ -- | Span stream
110− -> Anns -- ^ Annotations
156+ SpanStream ->
111− -> Text -- ^ Resulting rendition
157+ -- | Comment stream
112−runR debug (R m) sstream cstream anns =
158+ CommentStream ->
159+ -- | Annotations
160+ Anns ->
161+ -- | Use Record Dot Syntax
162+ Bool ->
163+ -- | Resulting rendition
164+ Text
165+runR (R m) sstream cstream anns recDot =
113 TL.toStrict . toLazyText . scBuilder $ execState (runReaderT m rc) sc
166 TL.toStrict . toLazyText . scBuilder $ execState (runReaderT m rc) sc
114 where
167 where
115− rc = RC
168+ rc =
116− { rcIndent = 0
169+ RC
117− , rcLayout = MultiLine
170+ { rcIndent = 0,
118− , rcRelaxedComments = False
171+ rcLayout = MultiLine,
119− , rcDebug = debug
172+ rcEnclosingSpans = [],
120− , rcEnclosingSpans = []
173+ rcAnns = anns,
121− , rcAnns = anns
174+ rcCanUseBraces = False,
122− }
175+ rcUseRecDot = recDot
123− sc = SC
176+ }
124− { scColumn = 0
177+ sc =
125− , scBuilder = mempty
178+ SC
126− , scSpanStream = sstream
179+ { scColumn = 0,
127− , scCommentStream = cstream
180+ scIndent = 0,
128− , scNewline = newlineRaw
181+ scBuilder = mempty,
129− }
182+ scSpanStream = sstream,
183+ scThisLineSpans = [],
184+ scCommentStream = cstream,
185+ scPendingComments = [],
186+ scRequestedDelimiter = VeryBeginning,
187+ scSpanMark = Nothing
188+ }
130
189
131----------------------------------------------------------------------------
190----------------------------------------------------------------------------
132-- Internal functions
191-- Internal functions
133
192
134−-- | Grow current output by appending given 'Text' to it, which may not
193+-- | Type of the thing to output. Influences the primary low-level rendering
135−-- contain newlines.
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
211+-- breaks. 'txt' is used to output all sorts of “fixed” bits of syntax like
212+-- keywords and pipes @|@ in functional dependencies.
213+--
214+-- To separate various bits of syntax with white space use 'space' instead
215+-- of @'txt' " "@. To output 'Outputable' Haskell entities like numbers use
216+-- 'atom'.
217+txt ::
218+ -- | 'Text' to output
219+ Text ->
220+ R ()
221+txt = spit SimpleText
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+
231+-- | Output 'Outputable' fragment of AST. This can be used to output numeric
232+-- literals and similar. Everything that doesn't have inner structure but
233+-- does have an 'Outputable' instance.
234+atom ::
235+ Outputable a =>
236+ a ->
237+ R ()
238+atom = spit Atom . T.pack . showOutputable
239+
240+-- | Low-level non-public helper to define 'txt' and 'atom'.
241+spit ::
242+ -- | Type of the thing to spit
243+ SpitType ->
244+ -- | 'Text' to output
245+ Text ->
246+ R ()
247+spit _ "" = return ()
248+spit stype text = do
249+ requestedDel <- R (gets scRequestedDelimiter)
250+ pendingComments <- R (gets scPendingComments)
251+ when (stype == InterferingText && not (null pendingComments)) newline
252+ case requestedDel of
253+ RequestedNewline -> do
254+ R . modify $ \sc ->
255+ sc
256+ { scRequestedDelimiter = RequestedNothing
257+ }
258+ case stype of
259+ CommentPart -> newlineRaw
260+ _ -> newline
261+ _ -> return ()
262+ R $ do
263+ i <- asks rcIndent
264+ c <- gets scColumn
265+ closestEnclosing <- listToMaybe <$> asks rcEnclosingSpans
266+ let indentedTxt = spaces <> text
267+ spaces = T.replicate spacesN " "
268+ spacesN =
269+ if c == 0
270+ then i
271+ else bool 0 1 (requestedDel == RequestedSpace)
272+ modify $ \sc ->
273+ sc
274+ { scBuilder = scBuilder sc <> fromText indentedTxt,
275+ scColumn = scColumn sc + T.length indentedTxt,
276+ scIndent =
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,
288+ scSpanMark =
289+ -- If there are pending comments, do not reset last comment
290+ -- location.
291+ if (stype == CommentPart) || (not . null . scPendingComments) sc
292+ then scSpanMark sc
293+ else Nothing
294+ }
136
295
137−spit :: Text -> R ()
296+-- | This primitive /does not/ necessarily output a space. It just ensures
138−spit x = do
297+-- that the next thing that will be printed on the same line will be
139− traceR "spit_before" (Just x)
298+-- separated by a single space from the previous output. Using this
140− R . modify $ \sc -> sc
299+-- combinator twice results in at most one space.
141− { scBuilder = scBuilder sc <> fromText x
300+--
142− , scColumn = scColumn sc + T.length x
301+-- In practice this design prevents trailing white space and makes it hard
302+-- to output more than one delimiting space in a row, which is what we
303+-- usually want.
304+space :: R ()
305+space = R . modify $ \sc ->
306+ sc
307+ { scRequestedDelimiter = case scRequestedDelimiter sc of
308+ RequestedNothing -> RequestedSpace
309+ other -> other
143 }
310 }
144− traceR "spit_after" Nothing
145−
146−-- | Output a newline.
147
311
312+-- | Output a newline. First time 'newline' is used after some non-'newline'
313+-- output it gets inserted immediately. Second use of 'newline' does not
314+-- output anything but makes sure that the next non-white space output will
315+-- be prefixed by a newline. Using 'newline' more than twice in a row has no
316+-- effect. Also, using 'newline' at the very beginning has no effect, this
317+-- is to avoid leading whitespace.
318+--
319+-- Similarly to 'space', this design prevents trailing newlines and makes it
320+-- hard to output more than one blank newline in a row.
148newline :: R ()
321newline :: R ()
149newline = do
322newline = do
150− n <- R (gets scNewline)
323+ indent <- R (gets scIndent)
151− R . modify $ \sc -> sc
324+ cs <- reverse <$> R (gets scPendingComments)
152− { scNewline = newlineRaw
325+ case cs of
153− }
326+ [] -> newlineRaw
154− n
327+ ((position, _) : _) -> do
328+ case position of
329+ OnTheSameLine -> space
330+ OnNextLine -> newlineRaw
331+ R . forM_ cs $ \(_, text) ->
332+ let modRC rc =
333+ rc
334+ { rcIndent = indent
335+ }
336+ R m = do
337+ unless (T.null text) $
338+ spit CommentPart text
339+ newlineRaw
340+ in local modRC m
341+ R . modify $ \sc ->
342+ sc
343+ { scPendingComments = []
344+ }
155
345
156-- | Low-level newline primitive. This one always just inserts a newline, no
346-- | Low-level newline primitive. This one always just inserts a newline, no
157-- hooks can be attached.
347-- hooks can be attached.
158−
159newlineRaw :: R ()
348newlineRaw :: R ()
160−newlineRaw = do
349+newlineRaw = R . modify $ \sc ->
161− traceR "newline_before" (Just "\n")
350+ let requestedDel = scRequestedDelimiter sc
162− R . modify $ \sc -> sc
351+ builderSoFar = scBuilder sc
163− { scBuilder = scBuilder sc <> "\n"
352+ in sc
164− , scColumn = 0
353+ { scBuilder = case requestedDel of
165− }
354+ AfterNewline -> builderSoFar
166− traceR "newline_after" Nothing
355+ RequestedNewline -> builderSoFar
167−
356+ VeryBeginning -> builderSoFar
168−-- | The 'modNewline' function can be used to alter what will be inserted as
357+ _ -> builderSoFar <> "\n",
169−-- a newline. This is used to output comments following an element of AST
358+ scColumn = 0,
170−-- because we cannot output comments immediately, e.g. because we need to
359+ scIndent = 0,
171−-- close parentheses first, etc.
360+ scThisLineSpans = [],
172−--
361+ scRequestedDelimiter = case scRequestedDelimiter sc of
173−-- 'newline' auto-resets its modifications so the changes introduced with
362+ AfterNewline -> RequestedNewline
174−-- 'modNewline' only have effect once.
363+ RequestedNewline -> RequestedNewline
175−--
364+ VeryBeginning -> VeryBeginning
176−-- The argument of the call-back is the version of 'newline' built so far.
365+ _ -> AfterNewline
177−
366+ }
178−modNewline :: (R () -> R ()) -> R ()
179−modNewline f = R $ do
180− old <- gets scNewline
181− modify $ \sc -> sc
182− { scNewline = f old
183− }
184−
185−-- | Ensure that indentation level is satisfied. Insert correct number of
186−-- spaces if it isn't.
187
367
188−ensureIndent :: R ()
368+-- | Return 'True' if we should print record dot syntax.
189−ensureIndent = do
369+useRecordDot :: R Bool
190− traceR "ensure_indent" Nothing
370+useRecordDot = R (asks rcUseRecDot)
191− i <- R (asks rcIndent)
192− c <- R (gets scColumn)
193− when (c < i) $
194− spit (T.replicate (i - c) " ")
195
371
196-- | Increase indentation level by one indentation step for the inner
372-- | Increase indentation level by one indentation step for the inner
197-- computation. 'inci' should be used when a part of code must be more
373-- computation. 'inci' should be used when a part of code must be more
198-- indented relative to the parts outside of 'inci' in order for the output
374-- indented relative to the parts outside of 'inci' in order for the output
199-- to be valid Haskell. When layout is single-line there is no obvious
375-- to be valid Haskell. When layout is single-line there is no obvious
200-- effect, but with multi-line layout correct indentation levels matter.
376-- effect, but with multi-line layout correct indentation levels matter.
201−
202inci :: R () -> R ()
377inci :: R () -> R ()
203−inci m' = do
378+inci (R m) = R (local modRC m)
204− traceR "inci_before" Nothing
379+ where
205− let R m = traceR "inci_inside" Nothing >> m'
380+ modRC rc =
206− modRC rc = rc
381+ rc
207 { rcIndent = rcIndent rc + indentStep
382 { rcIndent = rcIndent rc + indentStep
208 }
383 }
209− R (local modRC m)
210− traceR "inci_ended" Nothing
211
384
212-- | Set indentation level for the inner computation equal to current
385-- | Set indentation level for the inner computation equal to current
213-- column. This makes sure that the entire inner block is uniformly
386-- column. This makes sure that the entire inner block is uniformly
214−-- \"shifted\" to the right. Only works (and makes sense) when enclosing
387+-- \"shifted\" to the right.
215−-- layout is multi-line.
216−
217sitcc :: R () -> R ()
388sitcc :: R () -> R ()
218−sitcc m' = do
389+sitcc (R m) = do
219− traceR "sitcc_before" Nothing
390+ requestedDel <- R (gets scRequestedDelimiter)
220 i <- R (asks rcIndent)
391 i <- R (asks rcIndent)
221 c <- R (gets scColumn)
392 c <- R (gets scColumn)
222− let R m = traceR "sitcc_inside" Nothing >> m'
393+ let modRC rc =
223− modRC rc = rc
394+ rc
224− { rcIndent = max i c
395+ { rcIndent = max i (c + bool 0 1 (requestedDel == RequestedSpace))
225− }
396+ }
226− vlayout m' (R (local modRC m))
397+ R (local modRC m)
227− traceR "sitcc_ended" Nothing
228
398
229-- | Set 'Layout' for internal computation.
399-- | Set 'Layout' for internal computation.
230−
231enterLayout :: Layout -> R () -> R ()
400enterLayout :: Layout -> R () -> R ()
232−enterLayout l (R m) = do
401+enterLayout l (R m) = R (local modRC m)
233− let label =
402+ where
234− case l of
403+ modRC rc =
235− SingleLine -> "single_line"
404+ rc
236− MultiLine -> "multi_line"
237− traceR ("lstart_" ++ label) Nothing
238− let modRC rc = rc
239 { rcLayout = l
405 { rcLayout = l
240 }
406 }
241− x <- R (local modRC m)
242− traceR ("lend_" ++ label) Nothing
243− return x
244
407
245-- | Do one or another thing depending on current 'Layout'.
408-- | Do one or another thing depending on current 'Layout'.
246−
409+vlayout ::
247−vlayout
410+ -- | Single line
248− :: R a -- ^ Single line
411+ R a ->
249− -> R a -- ^ Multi line
412+ -- | Multi line
250− -> R a
413+ R a ->
414+ R a
251vlayout sline mline = do
415vlayout sline mline = do
252− l <- R (asks rcLayout)
416+ l <- getLayout
253 case l of
417 case l of
254 SingleLine -> sline
418 SingleLine -> sline
255 MultiLine -> mline
419 MultiLine -> mline
256
420
421+-- | Get current 'Layout'.
422+getLayout :: R Layout
423+getLayout = R (asks rcLayout)
424+
257----------------------------------------------------------------------------
425----------------------------------------------------------------------------
258-- Special helpers for comment placement
426-- Special helpers for comment placement
259
427
428+-- | Register a comment line for outputting. It will be inserted right
429+-- before next newline. When the comment goes after something else on the
430+-- same line, a space will be inserted between preceding text and the
431+-- comment when necessary.
432+registerPendingCommentLine ::
433+ -- | Comment position
434+ CommentPosition ->
435+ -- | 'Text' to output
436+ Text ->
437+ R ()
438+registerPendingCommentLine position text = R $ do
439+ modify $ \sc ->
440+ sc
441+ { scPendingComments = (position, text) : scPendingComments sc
442+ }
443+
260-- | Drop elements that begin before or at the same place as given
444-- | Drop elements that begin before or at the same place as given
261-- 'SrcSpan'.
445-- 'SrcSpan'.
262−
446+trimSpanStream ::
263−trimSpanStream
447+ -- | Reference span
264− :: RealSrcSpan -- ^ Reference span
448+ RealSrcSpan ->
265− -> R ()
449+ R ()
266trimSpanStream ref = do
450trimSpanStream ref = do
267 let leRef :: RealSrcSpan -> Bool
451 let leRef :: RealSrcSpan -> Bool
268 leRef x = realSrcSpanStart x <= realSrcSpanStart ref
452 leRef x = realSrcSpanStart x <= realSrcSpanStart ref
269− R . modify $ \sc -> sc
453+ R . modify $ \sc ->
270− { scSpanStream = coerce (dropWhile leRef) (scSpanStream sc)
454+ sc
271− }
455+ { scSpanStream = coerce (dropWhile leRef) (scSpanStream sc)
456+ }
272
457
273-- | Get location of next element in AST.
458-- | Get location of next element in AST.
274−
275nextEltSpan :: R (Maybe RealSrcSpan)
459nextEltSpan :: R (Maybe RealSrcSpan)
276nextEltSpan = listToMaybe . coerce <$> R (gets scSpanStream)
460nextEltSpan = listToMaybe . coerce <$> R (gets scSpanStream)
277
461
278-- | Pop a 'Comment' from the 'CommentStream' if given predicate is
462-- | Pop a 'Comment' from the 'CommentStream' if given predicate is
279-- satisfied and there are comments in the stream.
463-- satisfied and there are comments in the stream.
280−
464+popComment ::
281−popComment
465+ (RealLocated Comment -> Bool) ->
282− :: (RealLocated Comment -> Bool)
466+ R (Maybe (RealLocated Comment))
283− -> R (Maybe (RealLocated Comment))
284popComment f = R $ do
467popComment f = R $ do
285 CommentStream cstream <- gets scCommentStream
468 CommentStream cstream <- gets scCommentStream
286 case cstream of
469 case cstream of
287 [] -> return Nothing
470 [] -> return Nothing
288− (x:xs) ->
471+ (x : xs) ->
289 if f x
472 if f x
290− then Just x <$ modify (\sc -> sc
473+ then
291− { scCommentStream = CommentStream xs
474+ Just x
292− })
475+ <$ modify
476+ ( \sc ->
477+ sc
478+ { scCommentStream = CommentStream xs
479+ }
480+ )
293 else return Nothing
481 else return Nothing
294
482
295−-- | Return 'True' if there are more comments in the 'CommentStream'.
483+-- | Get the first enclosing 'RealSrcSpan' that satisfies given predicate.
296−
484+getEnclosingSpan ::
297−hasMoreComments :: R Bool
485+ -- | Predicate to use
298−hasMoreComments = R $ do
486+ (RealSrcSpan -> Bool) ->
299− CommentStream cstream <- gets scCommentStream
487+ R (Maybe RealSrcSpan)
300− (return . not . null) cstream
488+getEnclosingSpan f =
301−
489+ listToMaybe . filter f <$> R (asks rcEnclosingSpans)
302−-- | Current indentation level.
303−
304−getIndent :: R Int
305−getIndent = R (asks rcIndent)
306−
307−-- | Set indentation level for the given computation.
308−
309−setIndent :: Int -> R () -> R ()
310−setIndent i m' = do
311− traceR "set_indent_before" Nothing
312− let R m = traceR "set_indent_inside" Nothing >> m'
313− modRC rc = rc
314− { rcIndent = i
315− }
316− R (local modRC m)
317− traceR "set_indent_after" Nothing
318−
319−-- | Get 'RealSrcSpan' of enclosing span for given referencne span.
320−
321−getEnclosingSpan :: RealSrcSpan -> R (Maybe RealSrcSpan)
322−getEnclosingSpan r =
323− listToMaybe . dropWhile (== r) <$> R (asks rcEnclosingSpans)
324
490
325-- | Set 'RealSrcSpan' of enclosing span for the given computation.
491-- | Set 'RealSrcSpan' of enclosing span for the given computation.
326−
327withEnclosingSpan :: RealSrcSpan -> R () -> R ()
492withEnclosingSpan :: RealSrcSpan -> R () -> R ()
328−withEnclosingSpan spn (R m) = do
493+withEnclosingSpan spn (R m) = R (local modRC m)
329− let modRC rc = rc
494+ where
495+ modRC rc =
496+ rc
330 { rcEnclosingSpans = spn : rcEnclosingSpans rc
497 { rcEnclosingSpans = spn : rcEnclosingSpans rc
331 }
498 }
332− R (local modRC m)
499+
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.
524+data HaddockStyle
525+ = -- | @-- |@
526+ Pipe
527+ | -- | @-- ^@
528+ Caret
529+ | -- | @-- *@
530+ Asterisk Int
531+ | -- | @-- $@
532+ Named String
533+
534+-- | Set span of last output comment.
535+setSpanMark ::
536+ -- | Span mark to set
537+ SpanMark ->
538+ R ()
539+setSpanMark spnMark = R . modify $ \sc ->
540+ sc
541+ { scSpanMark = Just spnMark
542+ }
543+
544+-- | Get span of last output comment.
545+getSpanMark :: R (Maybe SpanMark)
546+getSpanMark = R (gets scSpanMark)
333
547
334----------------------------------------------------------------------------
548----------------------------------------------------------------------------
335-- Annotations
549-- Annotations
336
550
337-- | For a given span return 'AnnKeywordId's associated with it.
551-- | For a given span return 'AnnKeywordId's associated with it.
338−
552+getAnns ::
339−getAnns
553+ SrcSpan ->
340− :: SrcSpan
554+ R [AnnKeywordId]
341− -> R [AnnKeywordId]
342getAnns spn = lookupAnns spn <$> R (asks rcAnns)
555getAnns spn = lookupAnns spn <$> R (asks rcAnns)
343
556
344----------------------------------------------------------------------------
557----------------------------------------------------------------------------
345−-- Debug helpers
558+-- Helpers for braces
346−
559+
347−-- | Tracing helper.
560+-- | Make the inner computation use braces around single-line layouts.
348−
561+useBraces :: R () -> R ()
349−traceR
562+useBraces (R r) = R (local (\i -> i {rcCanUseBraces = True}) r)
350− :: String -- ^ Label
563+
351− -> Maybe Text -- ^ Output, if any
564+-- | Make the inner computation omit braces around single-line layouts.
352− -> R ()
565+dontUseBraces :: R () -> R ()
353−traceR label moutput = R $ do
566+dontUseBraces (R r) = R (local (\i -> i {rcCanUseBraces = False}) r)
354− debug <- asks rcDebug
567+
355− i <- asks rcIndent
568+-- | Return 'True' if we can use braces in this context.
356− c <- gets scColumn
569+canUseBraces :: R Bool
357− when debug . traceM . concat $
570+canUseBraces = R (asks rcCanUseBraces)
358− [ replicate i ' '
359− , unwords [ label ++ ":"
360− , "i=" ++ show i
361− , "c=" ++ show c
362− ]
363− ] ++ case moutput of
364− Nothing -> []
365− Just output -> [" out=" ++ show output]
366
571
367----------------------------------------------------------------------------
572----------------------------------------------------------------------------
368-- Constants
573-- Constants
369
574
370-- | Indentation step.
575-- | Indentation step.
371−
372indentStep :: Int
576indentStep :: Int
373indentStep = 2
577indentStep = 2
src/Ormolu/Printer/Meat/Common.hs+117−58
@@ -1,88 +1,108 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3
3
4-- | Rendering of commonly useful bits.
4-- | Rendering of commonly useful bits.
5−
6module Ormolu.Printer.Meat.Common
5module Ormolu.Printer.Meat.Common
7− ( FamilyStyle (..)
6+ ( FamilyStyle (..),
8− , p_hsmodName
7+ p_hsmodName,
9− , p_ieWrappedName
8+ p_ieWrappedName,
10− , p_rdrName
9+ p_rdrName,
11− , p_qualName
10+ doesNotNeedExtraParens,
12− , p_ieWildcard
11+ p_qualName,
13− , p_infixDefHelper
12+ p_infixDefHelper,
13+ p_hsDocString,
14+ p_hsDocName,
14 )
15 )
15where
16where
16
17
17import Control.Monad
18import Control.Monad
18import Data.List (isPrefixOf)
19import Data.List (isPrefixOf)
20+import qualified Data.Text as T
19import GHC hiding (GhcPs, IE)
21import GHC hiding (GhcPs, IE)
20import Name (nameStableString)
22import Name (nameStableString)
21import OccName (OccName (..))
23import OccName (OccName (..))
22import Ormolu.Printer.Combinators
24import Ormolu.Printer.Combinators
23−import Ormolu.Printer.Internal (getAnns)
25+import Ormolu.Utils
24−import RdrName (RdrName (..))
25
26
26-- | Data and type family style.
27-- | Data and type family style.
27−
28data FamilyStyle
28data FamilyStyle
29− = Associated -- ^ Declarations in type classes
29+ = -- | Declarations in type classes
30− | Free -- ^ Top-level declarations
30+ Associated
31+ | -- | Top-level declarations
32+ Free
31
33
32p_hsmodName :: ModuleName -> R ()
34p_hsmodName :: ModuleName -> R ()
33p_hsmodName mname = do
35p_hsmodName mname = do
34− txt "module "
36+ txt "module"
37+ space
35 atom mname
38 atom mname
36
39
37p_ieWrappedName :: IEWrappedName RdrName -> R ()
40p_ieWrappedName :: IEWrappedName RdrName -> R ()
38p_ieWrappedName = \case
41p_ieWrappedName = \case
39 IEName x -> p_rdrName x
42 IEName x -> p_rdrName x
40 IEPattern x -> do
43 IEPattern x -> do
41− txt "pattern "
44+ txt "pattern"
45+ space
42 p_rdrName x
46 p_rdrName x
43 IEType x -> do
47 IEType x -> do
44− txt "type "
48+ txt "type"
49+ space
45 p_rdrName x
50 p_rdrName x
46
51
47-- | Render a @'Located' 'RdrName'@.
52-- | Render a @'Located' 'RdrName'@.
48−
49p_rdrName :: Located RdrName -> R ()
53p_rdrName :: Located RdrName -> R ()
50p_rdrName l@(L spn _) = located l $ \x -> do
54p_rdrName l@(L spn _) = located l $ \x -> do
51 ids <- getAnns spn
55 ids <- getAnns spn
52− -- NOTE Right now we're mainly interested in backticks and parentheses.
53 let backticksWrapper =
56 let backticksWrapper =
54 if AnnBackquote `elem` ids
57 if AnnBackquote `elem` ids
55 then backticks
58 then backticks
56 else id
59 else id
57 parensWrapper =
60 parensWrapper =
58 if AnnOpenP `elem` ids
61 if AnnOpenP `elem` ids
59− then parens
62+ then parens N
60 else id
63 else id
61− (m, avoidParens) =
64+ singleQuoteWrapper =
65+ if AnnSimpleQuote `elem` ids
66+ then \y -> do
67+ txt "'"
68+ y
69+ else id
70+ m =
62 case x of
71 case x of
63 Unqual occName ->
72 Unqual occName ->
64− (atom occName, False)
73+ atom occName
65 Qual mname occName ->
74 Qual mname occName ->
66− (p_qualName mname occName, False)
75+ p_qualName mname occName
67 Orig _ occName ->
76 Orig _ occName ->
68− -- NOTE This is used when GHC generates code that will be fed
77+ -- This is used when GHC generates code that will be fed into
69− -- into the renamer (e.g. from deriving clauses), but where we
78+ -- the renamer (e.g. from deriving clauses), but where we want
70− -- want to say that something comes from given module which is
79+ -- to say that something comes from given module which is not
71− -- not specified in the source code, e.g. @Prelude.map@.
80+ -- specified in the source code, e.g. @Prelude.map@.
72 --
81 --
73 -- My current understanding is that the provided module name
82 -- My current understanding is that the provided module name
74 -- serves no purpose for us and can be safely ignored.
83 -- serves no purpose for us and can be safely ignored.
75− (atom occName, False)
84+ atom occName
76 Exact name ->
85 Exact name ->
77− -- NOTE I'm not sure this "stable string" is stable enough, but
86+ atom name
78− -- it looks like this is the most robust way to tell if we're
87+ m' = backticksWrapper (singleQuoteWrapper m)
79− -- looking at exactly this piece of built-in syntax.
88+ if doesNotNeedExtraParens x
80− ( atom name
89+ then m'
81− , "$ghc-prim$GHC.Tuple$" `isPrefixOf` nameStableString name
90+ else parensWrapper m'
82− )
91+
83− if avoidParens
92+-- | Whether given name should not have parentheses around it. This is used
84− then m
93+-- to detect e.g. tuples for which annotations will indicate parentheses,
85− else parensWrapper (backticksWrapper m)
94+-- but the parentheses are already part of the symbol, so no extra layer of
95+-- parentheses should be added. It also detects the [] literal.
96+doesNotNeedExtraParens :: RdrName -> Bool
97+doesNotNeedExtraParens = \case
98+ Exact name ->
99+ let s = nameStableString name
100+ in -- 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
102+ -- exactly this piece of built-in syntax.
103+ ("$ghc-prim$GHC.Tuple$" `isPrefixOf` s)
104+ || ("$ghc-prim$GHC.Types$[]" `isPrefixOf` s)
105+ _ -> False
86
106
87p_qualName :: ModuleName -> OccName -> R ()
107p_qualName :: ModuleName -> OccName -> R ()
88p_qualName mname occName = do
108p_qualName mname occName = do
@@ -90,37 +110,76 @@ p_qualName mname occName = do
90 txt "."
110 txt "."
91 atom occName
111 atom occName
92
112
93−p_ieWildcard :: IEWildcard -> R ()
94−p_ieWildcard = \case
95− NoIEWildcard -> return ()
96− IEWildcard n -> parens (atom n)
97−
98-- | A helper for formatting infix constructions in lhs of definitions.
113-- | A helper for formatting infix constructions in lhs of definitions.
99−
114+p_infixDefHelper ::
100−p_infixDefHelper
115+ -- | Whether to format in infix style
101− :: Bool -- ^ Whether to format in infix style
116+ Bool ->
102− -> (R () -> R ()) -- ^ Indentation-bumping wrapper
117+ -- | Whether to bump indentation for arguments
103− -> R () -- ^ How to print the operator\/name
118+ Bool ->
104− -> [R ()] -- ^ How to print the arguments
119+ -- | How to print the operator\/name
105− -> R ()
120+ R () ->
106−p_infixDefHelper isInfix inci' name args =
121+ -- | How to print the arguments
122+ [R ()] ->
123+ R ()
124+p_infixDefHelper isInfix indentArgs name args =
107 case (isInfix, args) of
125 case (isInfix, args) of
108− (True, p0:p1:ps) -> do
126+ (True, p0 : p1 : ps) -> do
109 let parens' =
127 let parens' =
110 if null ps
128 if null ps
111 then id
129 then id
112− else parens
130+ else parens N
113 parens' $ do
131 parens' $ do
114 p0
132 p0
115− space
116− name
117 breakpoint
133 breakpoint
118− inci' p1
134+ inci . sitcc $ do
119− unless (null ps) . inci' $ do
135+ name
136+ space
137+ p1
138+ unless (null ps) . inciIf indentArgs $ do
120 breakpoint
139 breakpoint
121− velt' ps
140+ sitcc (sep breakpoint sitcc ps)
122 (_, ps) -> do
141 (_, ps) -> do
123 name
142 name
124 unless (null ps) $ do
143 unless (null ps) $ do
125 breakpoint
144 breakpoint
126− inci' (velt' args)
145+ inciIf indentArgs $ sitcc (sep breakpoint sitcc args)
146+
147+-- | Print a Haddock.
148+p_hsDocString ::
149+ -- | Haddock style
150+ HaddockStyle ->
151+ -- | Finish the doc string with a newline
152+ Bool ->
153+ -- | The doc string to render
154+ LHsDocString ->
155+ R ()
156+p_hsDocString hstyle needsNewline (L l str) = do
157+ let isCommentSpan = \case
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.
163+ when goesAfterComment newline
164+ forM_ (zip (splitDocString str) (True : repeat False)) $ \(x, isFirst) -> do
165+ if isFirst
166+ then case hstyle of
167+ Pipe -> txt "-- |"
168+ Caret -> txt "-- ^"
169+ Asterisk n -> txt ("-- " <> T.replicate n "*")
170+ Named name -> p_hsDocName name
171+ else newline >> txt "--"
172+ space
173+ unless (T.null x) (txt x)
174+ when needsNewline newline
175+ case l of
176+ UnhelpfulSpan _ ->
177+ -- 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
179+ -- nearest enclosing span.
180+ getEnclosingSpan (const True) >>= mapM_ (setSpanMark . HaddockSpan hstyle)
181+ RealSrcSpan spn -> setSpanMark (HaddockSpan hstyle spn)
182+
183+-- | Print anchor of named doc section.
184+p_hsDocName :: String -> R ()
185+p_hsDocName name = txt ("-- $" <> T.pack name)
src/Ormolu/Printer/Meat/Declaration.hs+272−80
@@ -1,18 +1,21 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE PatternSynonyms #-}
3{-# LANGUAGE PatternSynonyms #-}
3{-# LANGUAGE RecordWildCards #-}
4{-# LANGUAGE RecordWildCards #-}
4−{-# LANGUAGE ViewPatterns #-}
5+{-# LANGUAGE ViewPatterns #-}
5
6
6-- | Rendering of declarations.
7-- | Rendering of declarations.
7−
8module Ormolu.Printer.Meat.Declaration
8module Ormolu.Printer.Meat.Declaration
9− ( p_hsDecls
9+ ( p_hsDecls,
10− , p_hsDecl
10+ p_hsDeclsRespectGrouping,
11 )
11 )
12where
12where
13
13
14−import Control.Monad (forM_)
14+import Data.List (sort)
15−import GHC
15+import Data.List.NonEmpty (NonEmpty (..), (<|))
16+import qualified Data.List.NonEmpty as NE
17+import GHC hiding (InlinePragma)
18+import OccName (occNameFS)
16import Ormolu.Printer.Combinators
19import Ormolu.Printer.Combinators
17import Ormolu.Printer.Meat.Common
20import Ormolu.Printer.Meat.Common
18import Ormolu.Printer.Meat.Declaration.Annotation
21import Ormolu.Printer.Meat.Declaration.Annotation
@@ -22,6 +25,7 @@ import Ormolu.Printer.Meat.Declaration.Default
22import Ormolu.Printer.Meat.Declaration.Foreign
25import Ormolu.Printer.Meat.Declaration.Foreign
23import Ormolu.Printer.Meat.Declaration.Instance
26import Ormolu.Printer.Meat.Declaration.Instance
24import Ormolu.Printer.Meat.Declaration.RoleAnnotation
27import Ormolu.Printer.Meat.Declaration.RoleAnnotation
28+import Ormolu.Printer.Meat.Declaration.Rule
25import Ormolu.Printer.Meat.Declaration.Signature
29import Ormolu.Printer.Meat.Declaration.Signature
26import Ormolu.Printer.Meat.Declaration.Splice
30import Ormolu.Printer.Meat.Declaration.Splice
27import Ormolu.Printer.Meat.Declaration.Type
31import Ormolu.Printer.Meat.Declaration.Type
@@ -31,41 +35,106 @@ import Ormolu.Printer.Meat.Declaration.Warning
31import Ormolu.Printer.Meat.Type
35import Ormolu.Printer.Meat.Type
32import Ormolu.Utils
36import Ormolu.Utils
33
37
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+
34p_hsDecls :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
45p_hsDecls :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
35−p_hsDecls style decls =
46+p_hsDecls = p_hsDecls' Disregard
36− forM_ (zip decls ((Just <$> drop 1 decls) ++ [Nothing])) $ \(d, md) ->
47+
37− case md of
48+-- | Like 'p_hsDecls' but respects user choices regarding grouping. If the
38− Nothing -> located d pDecl
49+-- user omits newlines between declarations, we also omit them in most
39− Just d' ->
50+-- cases, except when said declarations have associated Haddocks.
40− if separatedDecls (unLoc d) (unLoc d')
51+--
41− then line (located d pDecl)
52+-- Does some normalization (compress subsequent newlines into a single one)
42− else located d pDecl
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 $
59+ -- Return a list of rendered declarations, adding a newline to separate
60+ -- groups.
61+ case groupDecls decls of
62+ [] -> []
63+ (x : xs) -> renderGroup x ++ concat (zipWith renderGroupWithPrev (x : xs) xs)
43 where
64 where
44− pDecl = p_hsDecl style
65+ renderGroup = NE.toList . fmap (located' $ dontUseBraces . p_hsDecl style)
66+ renderGroupWithPrev prev curr =
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+
87+-- | Group relevant declarations together.
88+groupDecls :: [LHsDecl GhcPs] -> [NonEmpty (LHsDecl GhcPs)]
89+groupDecls [] = []
90+groupDecls (l@(L _ DocNext) : xs) =
91+ -- If the first element is a doc string for next element, just include it
92+ -- in the next block:
93+ case groupDecls xs of
94+ [] -> [l :| []]
95+ (x : xs') -> (l <| x) : xs'
96+groupDecls (header : xs) =
97+ let (grp, rest) = flip span (zip (header : xs) xs) $ \(previous, current) ->
98+ let relevantToHdr = groupedDecls header current
99+ relevantToPrev = groupedDecls previous current
100+ isDeclSeries = declSeries previous current
101+ in isDeclSeries || relevantToHdr || relevantToPrev
102+ in (header :| map snd grp) : groupDecls (map snd rest)
45
103
46p_hsDecl :: FamilyStyle -> HsDecl GhcPs -> R ()
104p_hsDecl :: FamilyStyle -> HsDecl GhcPs -> R ()
47p_hsDecl style = \case
105p_hsDecl style = \case
48− TyClD NoExt x -> p_tyClDecl style x
106+ TyClD NoExtField x -> p_tyClDecl style x
49− ValD NoExt x -> p_valDecl x
107+ ValD NoExtField x -> p_valDecl x
50− SigD NoExt x -> p_sigDecl x
108+ SigD NoExtField x -> p_sigDecl x
51− InstD NoExt x -> p_instDecl style x
109+ InstD NoExtField x -> p_instDecl style x
52− DerivD NoExt x -> p_derivDecl x
110+ DerivD NoExtField x -> p_derivDecl x
53− DefD NoExt x -> p_defaultDecl x
111+ DefD NoExtField x -> p_defaultDecl x
54− ForD NoExt x -> p_foreignDecl x
112+ ForD NoExtField x -> p_foreignDecl x
55− WarningD NoExt x -> p_warnDecls x
113+ WarningD NoExtField x -> p_warnDecls x
56− AnnD NoExt x -> p_annDecl x
114+ AnnD NoExtField x -> p_annDecl x
57− RuleD _ _ -> notImplemented "RuleD"
115+ RuleD NoExtField x -> p_ruleDecls x
58− SpliceD NoExt x -> p_spliceDecl x
116+ SpliceD NoExtField x -> p_spliceDecl x
59− DocD _ _ -> notImplemented "DocD"
117+ DocD NoExtField docDecl ->
60− RoleAnnotD NoExt x -> p_roleAnnot x
118+ case docDecl of
61− XHsDecl _ -> notImplemented "XHsDecl"
119+ DocCommentNext str -> p_hsDocString Pipe False (noLoc str)
120+ DocCommentPrev str -> p_hsDocString Caret False (noLoc str)
121+ DocCommentNamed name str -> p_hsDocString (Named name) False (noLoc str)
122+ DocGroup n str -> p_hsDocString (Asterisk n) False (noLoc str)
123+ RoleAnnotD NoExtField x -> p_roleAnnot x
124+ KindSigD NoExtField s -> p_standaloneKindSig s
125+ XHsDecl x -> noExtCon x
62
126
63p_tyClDecl :: FamilyStyle -> TyClDecl GhcPs -> R ()
127p_tyClDecl :: FamilyStyle -> TyClDecl GhcPs -> R ()
64p_tyClDecl style = \case
128p_tyClDecl style = \case
65− FamDecl NoExt x -> p_famDecl style x
129+ FamDecl NoExtField x -> p_famDecl style x
66− SynDecl {..} -> p_synDecl tcdLName tcdTyVars tcdRhs
130+ SynDecl {..} -> p_synDecl tcdLName tcdFixity tcdTyVars tcdRhs
67 DataDecl {..} ->
131 DataDecl {..} ->
68− p_dataDecl Associated tcdLName (tyVarsToTypes tcdTyVars) tcdDataDefn
132+ p_dataDecl
133+ Associated
134+ tcdLName
135+ (tyVarsToTypes tcdTyVars)
136+ tcdFixity
137+ tcdDataDefn
69 ClassDecl {..} ->
138 ClassDecl {..} ->
70 p_classDecl
139 p_classDecl
71 tcdCtxt
140 tcdCtxt
@@ -77,59 +146,182 @@ p_tyClDecl style = \case
77 tcdMeths
146 tcdMeths
78 tcdATs
147 tcdATs
79 tcdATDefs
148 tcdATDefs
80− XTyClDecl {} -> notImplemented "XTyClDecl"
149+ tcdDocs
150+ XTyClDecl x -> noExtCon x
81
151
82p_instDecl :: FamilyStyle -> InstDecl GhcPs -> R ()
152p_instDecl :: FamilyStyle -> InstDecl GhcPs -> R ()
83p_instDecl style = \case
153p_instDecl style = \case
84− ClsInstD NoExt x -> p_clsInstDecl x
154+ ClsInstD NoExtField x -> p_clsInstDecl x
85− TyFamInstD NoExt x -> p_tyFamInstDecl style x
155+ TyFamInstD NoExtField x -> p_tyFamInstDecl style x
86− DataFamInstD NoExt x -> p_dataFamInstDecl style x
156+ DataFamInstD NoExtField x -> p_dataFamInstDecl style x
87− XInstDecl _ -> notImplemented "XInstDecl"
157+ XInstDecl x -> noExtCon x
88
158
89p_derivDecl :: DerivDecl GhcPs -> R ()
159p_derivDecl :: DerivDecl GhcPs -> R ()
90p_derivDecl = \case
160p_derivDecl = \case
91− d@DerivDecl {..} -> p_standaloneDerivDecl d
161+ d@DerivDecl {} -> p_standaloneDerivDecl d
92− XDerivDecl _ -> notImplemented "XDerivDecl standalone deriving"
162+ XDerivDecl x -> noExtCon x
93−
163+
94−-- | Determine if these declarations should be separated by a blank line.
164+-- | Determine if these declarations should be grouped together.
95−
165+groupedDecls ::
96−separatedDecls
166+ LHsDecl GhcPs ->
97− :: HsDecl GhcPs
167+ LHsDecl GhcPs ->
98− -> HsDecl GhcPs
168+ Bool
99− -> Bool
169+groupedDecls (L l_x x') (L l_y y') =
100−separatedDecls (TypeSignature n) (FunctionBody n') = n /= n'
170+ case (x', y') of
101−separatedDecls (FunctionBody n) x | Just n' <- isPragma x = n /= n'
171+ (TypeSignature ns, FunctionBody ns') -> ns `intersects` ns'
102−separatedDecls x y | Just n <- isPragma x, Just n' <- isPragma y = n /= n'
172+ (TypeSignature ns, DefaultSignature ns') -> ns `intersects` ns'
103−separatedDecls x (TypeSignature n') | Just n <- isPragma x = n /= n'
173+ (DefaultSignature ns, TypeSignature ns') -> ns `intersects` ns'
104−separatedDecls _ _ = True
174+ (DefaultSignature ns, FunctionBody ns') -> ns `intersects` ns'
105−
175+ (x, FunctionBody ns) | Just ns' <- isPragma x -> ns `intersects` ns'
106−isPragma
176+ (FunctionBody ns, x) | Just ns' <- isPragma x -> ns `intersects` ns'
107− :: HsDecl GhcPs
177+ (x, DataDeclaration n) | Just ns <- isPragma x -> n `elem` ns
108− -> (Maybe RdrName)
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 ->
202+ Bool
203+declSeries (L _ x) (L _ y) =
204+ case (x, y) of
205+ ( SigD NoExtField (TypeSig NoExtField _ _),
206+ SigD NoExtField (TypeSig NoExtField _ _)
207+ ) -> True
208+ _ -> False
209+
210+intersects :: Ord a => [a] -> [a] -> Bool
211+intersects a b = go (sort a) (sort b)
212+ where
213+ go :: Ord a => [a] -> [a] -> Bool
214+ go _ [] = False
215+ go [] _ = False
216+ go (x : xs) (y : ys)
217+ | x < y = go xs (y : ys)
218+ | x > y = go (x : xs) ys
219+ | otherwise = True
220+
221+isPragma ::
222+ HsDecl GhcPs ->
223+ Maybe [RdrName]
109isPragma = \case
224isPragma = \case
110− InlinePragma n -> Just n
225+ InlinePragma n -> Just [n]
111− SpecializePragma n -> Just n
226+ SpecializePragma n -> Just [n]
112− SCCPragma n -> Just n
227+ SCCPragma n -> Just [n]
113− AnnTypePragma n -> Just n
228+ AnnTypePragma n -> Just [n]
114− AnnValuePragma n -> Just n
229+ AnnValuePragma n -> Just [n]
230+ WarningPragma n -> Just n
115 _ -> Nothing
231 _ -> Nothing
116
232
117−pattern TypeSignature
233+-- Declarations that do not refer to names
118− , FunctionBody
234+
119− , InlinePragma
235+pattern Splice :: HsDecl GhcPs
120− , SpecializePragma
236+pattern Splice <- SpliceD NoExtField (SpliceDecl NoExtField _ _)
121− , SCCPragma
237+
122− , AnnTypePragma
238+-- Declarations referring to a single name
123− , AnnValuePragma :: RdrName -> HsDecl GhcPs
239+
124−pattern TypeSignature n <- (sigRdrName -> Just n)
240+pattern
125−pattern FunctionBody n <- ValD NoExt (FunBind NoExt (L _ n) _ _ _)
241+ InlinePragma,
126−pattern InlinePragma n <- SigD NoExt (InlineSig NoExt (L _ n) _)
242+ SpecializePragma,
127−pattern SpecializePragma n <- SigD NoExt (SpecSig NoExt (L _ n) _ _)
243+ SCCPragma,
128−pattern SCCPragma n <- SigD NoExt (SCCFunSig NoExt _ (L _ n) _)
244+ AnnTypePragma,
129−pattern AnnTypePragma n <- AnnD NoExt (HsAnnotation NoExt _ (TypeAnnProvenance (L _ n)) _)
245+ AnnValuePragma,
130−pattern AnnValuePragma n <- AnnD NoExt (HsAnnotation NoExt _ (ValueAnnProvenance (L _ n)) _)
246+ Pattern,
131−
247+ DataDeclaration,
132−sigRdrName :: HsDecl GhcPs -> Maybe RdrName
248+ ClassDeclaration,
133−sigRdrName (SigD NoExt (TypeSig NoExt ((L _ n):_) _)) = Just n
249+ KindSignature,
134−sigRdrName (SigD NoExt (ClassOpSig NoExt _ ((L _ n):_) _)) = Just n
250+ FamilyDeclaration ::
135−sigRdrName _ = Nothing
251+ RdrName -> HsDecl GhcPs
252+pattern InlinePragma n <- SigD NoExtField (InlineSig NoExtField (L _ n) _)
253+pattern SpecializePragma n <- SigD NoExtField (SpecSig NoExtField (L _ n) _ _)
254+pattern SCCPragma n <- SigD NoExtField (SCCFunSig NoExtField _ (L _ n) _)
255+pattern AnnTypePragma n <- AnnD NoExtField (HsAnnotation NoExtField _ (TypeAnnProvenance (L _ n)) _)
256+pattern AnnValuePragma n <- AnnD NoExtField (HsAnnotation NoExtField _ (ValueAnnProvenance (L _ n)) _)
257+pattern Pattern n <- ValD NoExtField (PatSynBind NoExtField (PSB _ (L _ n) _ _ _))
258+pattern DataDeclaration n <- TyClD NoExtField (DataDecl NoExtField (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+
263+-- Declarations which can refer to multiple names
264+
265+pattern
266+ TypeSignature,
267+ DefaultSignature,
268+ FunctionBody,
269+ PatternSignature,
270+ WarningPragma ::
271+ [RdrName] -> HsDecl GhcPs
272+pattern TypeSignature n <- (sigRdrNames -> Just n)
273+pattern DefaultSignature n <- (defSigRdrNames -> Just n)
274+pattern FunctionBody n <- (funRdrNames -> Just n)
275+pattern PatternSignature n <- (patSigRdrNames -> Just n)
276+pattern WarningPragma n <- (warnSigRdrNames -> Just n)
277+
278+pattern DocNext, DocPrev :: HsDecl GhcPs
279+pattern DocNext <- (DocD NoExtField (DocCommentNext _))
280+pattern DocPrev <- (DocD NoExtField (DocCommentPrev _))
281+
282+sigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
283+sigRdrNames (SigD NoExtField (TypeSig NoExtField ns _)) = Just $ map unLoc ns
284+sigRdrNames (SigD NoExtField (ClassOpSig NoExtField _ ns _)) = Just $ map unLoc ns
285+sigRdrNames (SigD NoExtField (PatSynSig NoExtField ns _)) = Just $ map unLoc ns
286+sigRdrNames _ = Nothing
287+
288+defSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
289+defSigRdrNames (SigD NoExtField (ClassOpSig NoExtField True ns _)) = Just $ map unLoc ns
290+defSigRdrNames _ = Nothing
291+
292+funRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
293+funRdrNames (ValD NoExtField (FunBind NoExtField (L _ n) _ _ _)) = Just [n]
294+funRdrNames (ValD NoExtField (PatBind NoExtField (L _ n) _ _)) = Just $ patBindNames n
295+funRdrNames _ = Nothing
296+
297+patSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
298+patSigRdrNames (SigD NoExtField (PatSynSig NoExtField ns _)) = Just $ map unLoc ns
299+patSigRdrNames _ = Nothing
300+
301+warnSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
302+warnSigRdrNames (WarningD NoExtField (Warnings NoExtField _ ws)) = Just $
303+ flip concatMap ws $ \case
304+ L _ (Warning NoExtField ns _) -> map unLoc ns
305+ L _ (XWarnDecl x) -> noExtCon x
306+warnSigRdrNames _ = Nothing
307+
308+patBindNames :: Pat GhcPs -> [RdrName]
309+patBindNames (TuplePat NoExtField ps _) = concatMap (patBindNames . unLoc) ps
310+patBindNames (VarPat NoExtField (L _ n)) = [n]
311+patBindNames (WildPat NoExtField) = []
312+patBindNames (LazyPat NoExtField (L _ p)) = patBindNames p
313+patBindNames (BangPat NoExtField (L _ p)) = patBindNames p
314+patBindNames (ParPat NoExtField (L _ p)) = patBindNames p
315+patBindNames (ListPat NoExtField ps) = concatMap (patBindNames . unLoc) ps
316+patBindNames (AsPat NoExtField (L _ n) (L _ p)) = n : patBindNames p
317+patBindNames (SumPat NoExtField (L _ p) _ _) = patBindNames p
318+patBindNames (ViewPat NoExtField _ (L _ p)) = patBindNames p
319+patBindNames (SplicePat NoExtField _) = []
320+patBindNames (LitPat NoExtField _) = []
321+patBindNames (SigPat _ (L _ p) _) = patBindNames p
322+patBindNames (NPat NoExtField _ _ _) = []
323+patBindNames (NPlusKPat NoExtField (L _ n) _ _ _ _) = [n]
324+patBindNames (ConPatIn _ d) = concatMap (patBindNames . unLoc) (hsConPatArgs d)
325+patBindNames ConPatOut {} = notImplemented "ConPatOut" -- created by renamer
326+patBindNames (CoPat NoExtField _ p _) = patBindNames p
327+patBindNames (XPat x) = noExtCon x
src/Ormolu/Printer/Meat/Declaration.hs-boot+3−4
@@ -1,6 +1,6 @@
1module Ormolu.Printer.Meat.Declaration
1module Ormolu.Printer.Meat.Declaration
2− ( p_hsDecls
2+ ( p_hsDecls,
3− , p_hsDecl
3+ p_hsDeclsRespectGrouping,
4 )
4 )
5where
5where
6
6
@@ -9,5 +9,4 @@ 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−
12+p_hsDeclsRespectGrouping :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
13−p_hsDecl :: FamilyStyle -> HsDecl GhcPs -> R ()
src/Ormolu/Printer/Meat/Declaration/Annotation.hs+5−6
@@ -1,8 +1,8 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3
3
4module Ormolu.Printer.Meat.Declaration.Annotation
4module Ormolu.Printer.Meat.Declaration.Annotation
5− ( p_annDecl
5+ ( p_annDecl,
6 )
6 )
7where
7where
8
8
@@ -10,18 +10,17 @@ 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
14
13
15p_annDecl :: AnnDecl GhcPs -> R ()
14p_annDecl :: AnnDecl GhcPs -> R ()
16p_annDecl = \case
15p_annDecl = \case
17− HsAnnotation NoExt _ annProv expr -> line . pragma "ANN" $ do
16+ HsAnnotation NoExtField _ annProv expr -> pragma "ANN" . inci $ do
18 p_annProv annProv
17 p_annProv annProv
19 breakpoint
18 breakpoint
20 located expr p_hsExpr
19 located expr p_hsExpr
21− XAnnDecl {} -> notImplemented "XAnnDecl"
20+ XAnnDecl x -> noExtCon x
22
21
23p_annProv :: AnnProvenance (IdP GhcPs) -> R ()
22p_annProv :: AnnProvenance (IdP GhcPs) -> R ()
24p_annProv = \case
23p_annProv = \case
25 ValueAnnProvenance name -> p_rdrName name
24 ValueAnnProvenance name -> p_rdrName name
26− TypeAnnProvenance name -> p_rdrName name
25+ TypeAnnProvenance name -> txt "type" >> space >> p_rdrName name
27 ModuleAnnProvenance -> txt "module"
26 ModuleAnnProvenance -> txt "module"
src/Ormolu/Printer/Meat/Declaration/Class.hs+58−67
@@ -1,11 +1,10 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
4
4
5-- | Rendering of type class declarations.
5-- | Rendering of type class declarations.
6−
7module Ormolu.Printer.Meat.Declaration.Class
6module Ormolu.Printer.Meat.Declaration.Class
8− ( p_classDecl
7+ ( p_classDecl,
9 )
8 )
10where
9where
11
10
@@ -13,97 +12,89 @@ import Class
13import Control.Arrow
12import Control.Arrow
14import Control.Monad
13import Control.Monad
15import Data.Foldable
14import Data.Foldable
16−import Data.List (sortBy)
15+import Data.List (sortOn)
17−import Data.Ord (comparing)
18import GHC
16import GHC
19import Ormolu.Printer.Combinators
17import Ormolu.Printer.Combinators
20import Ormolu.Printer.Meat.Common
18import Ormolu.Printer.Meat.Common
21−import Ormolu.Printer.Meat.Type
22−import Ormolu.Utils
23−import RdrName (RdrName (..))
24−import SrcLoc (Located, combineSrcSpans)
25import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration
19import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration
20+import Ormolu.Printer.Meat.Type
26
21
27−p_classDecl
22+p_classDecl ::
28− :: LHsContext GhcPs
23+ LHsContext GhcPs ->
29− -> Located RdrName
24+ Located RdrName ->
30− -> LHsQTyVars GhcPs
25+ LHsQTyVars GhcPs ->
31− -> LexicalFixity
26+ LexicalFixity ->
32− -> [Located (FunDep (Located RdrName))]
27+ [Located (FunDep (Located RdrName))] ->
33− -> [LSig GhcPs]
28+ [LSig GhcPs] ->
34− -> LHsBinds GhcPs
29+ LHsBinds GhcPs ->
35− -> [LFamilyDecl GhcPs]
30+ [LFamilyDecl GhcPs] ->
36− -> [LTyFamDefltEqn GhcPs]
31+ [LTyFamDefltDecl GhcPs] ->
37− -> R ()
32+ [LDocDecl] ->
38−p_classDecl ctx name tvars fixity fdeps csigs cdefs cats catdefs = do
33+ R ()
39− let HsQTvs {..} = tvars
34+p_classDecl ctx name HsQTvs {..} fixity fdeps csigs cdefs cats catdefs cdocs = do
40− variableSpans = foldr (combineSrcSpans . getLoc) noSrcSpan hsq_explicit
35+ let variableSpans = getLoc <$> hsq_explicit
41− signatureSpans = getLoc name `combineSrcSpans` variableSpans
36+ signatureSpans = getLoc name : variableSpans
42− dependencySpans = foldr (combineSrcSpans . getLoc) noSrcSpan fdeps
37+ dependencySpans = getLoc <$> fdeps
43− combinedSpans =
38+ combinedSpans = getLoc ctx : (signatureSpans ++ dependencySpans)
44− getLoc ctx `combineSrcSpans`
39+ -- GHC's AST does not necessarily store each kind of element in source
45− signatureSpans `combineSrcSpans`
40+ -- location order. This happens because different declarations are stored
46− dependencySpans
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)
47 txt "class"
53 txt "class"
48− switchLayout combinedSpans $ do
54+ switchLayout combinedSpans $ do
49 breakpoint
55 breakpoint
50− inci $ do
56+ inci $ do
51 p_classContext ctx
57 p_classContext ctx
52− switchLayout signatureSpans $ do
58+ switchLayout signatureSpans $
53 p_infixDefHelper
59 p_infixDefHelper
54 (isInfix fixity)
60 (isInfix fixity)
55− inci
61+ True
56 (p_rdrName name)
62 (p_rdrName name)
57 (located' p_hsTyVarBndr <$> hsq_explicit)
63 (located' p_hsTyVarBndr <$> hsq_explicit)
58 inci (p_classFundeps fdeps)
64 inci (p_classFundeps fdeps)
59− -- GHC's AST does not necessarily store each kind of element in source
65+ unless (null allDecls) $ do
60− -- location order. This happens because different declarations are stored in
66+ breakpoint
61− -- different lists. Consequently, to get all the declarations in proper order,
67+ txt "where"
62− -- they need to be manually sorted.
68+ unless (null allDecls) $ do
63− let sigs = (getLoc &&& fmap (SigD NoExt)) <$> csigs
69+ breakpoint -- Ensure whitespace is added after where clause.
64− vals = (getLoc &&& fmap (ValD NoExt)) <$> toList cdefs
70+ inci (p_hsDeclsRespectGrouping Associated allDecls)
65− tyFams = (getLoc &&& fmap (TyClD NoExt . FamDecl NoExt)) <$> cats
71+p_classDecl _ _ (XLHsQTyVars c) _ _ _ _ _ _ _ = noExtCon c
66− tyFamDefs =
67− ( getLoc &&& fmap (InstD NoExt . TyFamInstD NoExt . defltEqnToInstDecl)
68− ) <$> catdefs
69− allDecls =
70− snd <$> sortBy (comparing fst) (sigs <> vals <> tyFams <> tyFamDefs)
71− if not (null allDecls)
72− then do
73− txt " where"
74− newline -- Ensure line is added after where clause.
75− newline -- Add newline before first declaration.
76− inci (p_hsDecls Associated allDecls)
77− else newline
78
72
79p_classContext :: LHsContext GhcPs -> R ()
73p_classContext :: LHsContext GhcPs -> R ()
80−p_classContext ctx = unless (null (unLoc ctx)) $ do
74+p_classContext ctx = unless (null (unLoc ctx)) $ do
81 located ctx p_hsContext
75 located ctx p_hsContext
76+ space
77+ txt "=>"
82 breakpoint
78 breakpoint
83− txt "=> "
84
79
85p_classFundeps :: [Located (FunDep (Located RdrName))] -> R ()
80p_classFundeps :: [Located (FunDep (Located RdrName))] -> R ()
86p_classFundeps fdeps = unless (null fdeps) $ do
81p_classFundeps fdeps = unless (null fdeps) $ do
87 breakpoint
82 breakpoint
88− txt "| "
83+ txt "|"
89− velt $ withSep comma (located' p_funDep) fdeps
84+ space
85+ inci $ sep commaDel (sitcc . located' p_funDep) fdeps
90
86
91p_funDep :: FunDep (Located RdrName) -> R ()
87p_funDep :: FunDep (Located RdrName) -> R ()
92p_funDep (before, after) = do
88p_funDep (before, after) = do
93− spaceSep p_rdrName before
89+ sep space p_rdrName before
94− txt " -> "
90+ space
95− spaceSep p_rdrName after
91+ txt "->"
92+ space
93+ sep space p_rdrName after
96
94
97----------------------------------------------------------------------------
95----------------------------------------------------------------------------
98-- Helpers
96-- Helpers
99
97
100−defltEqnToInstDecl :: TyFamDefltEqn GhcPs -> TyFamInstDecl GhcPs
101−defltEqnToInstDecl FamEqn {..} = TyFamInstDecl {..}
102− where
103− eqn = FamEqn {feqn_pats = tyVarsToTypes feqn_pats, ..}
104− tfid_eqn = HsIB {hsib_ext = NoExt, hsib_body = eqn}
105−defltEqnToInstDecl XFamEqn {} = notImplemented "XFamEqn"
106−
107isInfix :: LexicalFixity -> Bool
98isInfix :: LexicalFixity -> Bool
108isInfix = \case
99isInfix = \case
109 Infix -> True
100 Infix -> True
src/Ormolu/Printer/Meat/Declaration/Data.hs+192−98
@@ -1,127 +1,194 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
4
4
5-- | Renedring of data type declarations.
5-- | Renedring of data type declarations.
6−
7module Ormolu.Printer.Meat.Declaration.Data
6module Ormolu.Printer.Meat.Declaration.Data
8− ( p_dataDecl
7+ ( p_dataDecl,
9 )
8 )
10where
9where
11
10
12import Control.Monad
11import Control.Monad
13−import Data.List.NonEmpty (NonEmpty (..))
12+import Data.Maybe (isJust, maybeToList)
14−import Data.Maybe (isJust)
15import GHC
13import GHC
16import Ormolu.Printer.Combinators
14import Ormolu.Printer.Combinators
17import Ormolu.Printer.Meat.Common
15import Ormolu.Printer.Meat.Common
18import Ormolu.Printer.Meat.Type
16import Ormolu.Printer.Meat.Type
19import Ormolu.Utils
17import Ormolu.Utils
20−import RdrName (RdrName (..))
21−import SrcLoc (Located)
22
18
23−p_dataDecl
19+p_dataDecl ::
24− :: FamilyStyle -- ^ Whether to format as data family
20+ -- | Whether to format as data family
25− -> Located RdrName -- ^ Type constructor
21+ FamilyStyle ->
26− -> [LHsType GhcPs] -- ^ Type patterns
22+ -- | Type constructor
27− -> HsDataDefn GhcPs -- ^ Data definition
23+ Located RdrName ->
28− -> R ()
24+ -- | Type patterns
29−p_dataDecl style name tpats HsDataDefn {..} = do
25+ [LHsType GhcPs] ->
26+ -- | Lexical fixity
27+ LexicalFixity ->
28+ -- | Data definition
29+ HsDataDefn GhcPs ->
30+ R ()
31+p_dataDecl style name tpats fixity HsDataDefn {..} = do
30 txt $ case dd_ND of
32 txt $ case dd_ND of
31− NewType -> "newtype "
33+ NewType -> "newtype"
32− DataType -> "data "
34+ DataType -> "data"
33− txt $ case style of
35+ txt $ case style of
34 Associated -> mempty
36 Associated -> mempty
35− Free -> "instance "
37+ Free -> " instance"
36− p_rdrName name
38+ let constructorSpans = getLoc name : fmap getLoc tpats
37− unless (null tpats) space
39+ switchLayout constructorSpans $ do
38− spaceSep (located' p_hsType) tpats
40+ breakpoint
41+ inci $
42+ p_infixDefHelper
43+ (isInfix fixity)
44+ True
45+ (p_rdrName name)
46+ (located' p_hsType <$> tpats)
39 case dd_kindSig of
47 case dd_kindSig of
40 Nothing -> return ()
48 Nothing -> return ()
41 Just k -> do
49 Just k -> do
42 space
50 space
43− txt ":: "
51+ txt "::"
52+ space
44 located k p_hsType
53 located k p_hsType
45 let gadt = isJust dd_kindSig || any (isGadt . unLoc) dd_cons
54 let gadt = isJust dd_kindSig || any (isGadt . unLoc) dd_cons
46 unless (null dd_cons) $
55 unless (null dd_cons) $
47 if gadt
56 if gadt
48− then do
57+ then inci $ do
49− txt " where"
58+ switchLayout constructorSpans $ do
50− newline
51− inci $ newlineSep (sitcc . located' p_conDecl) dd_cons
52− else switchLayout (combineSrcSpans' (getLoc name :| (getLoc <$> dd_cons))) $
53− inci $ do
54 breakpoint
59 breakpoint
55− txt "= "
60+ txt "where"
56− let sep = vlayout (txt " | ") (txt "| ")
61+ breakpoint
57− velt $ withSep sep (sitcc . located' p_conDecl) dd_cons
62+ sepSemi (located' (p_conDecl False)) dd_cons
58− newline
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
73+ layout <- getLayout
74+ let s =
75+ if layout == MultiLine || hasHaddocks dd_cons
76+ then 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
83+ unless (null $ unLoc dd_derivs) breakpoint
59 inci . located dd_derivs $ \xs ->
84 inci . located dd_derivs $ \xs ->
60− forM_ xs (line . located' p_hsDerivingClause)
85+ sep newline (located' p_hsDerivingClause) xs
61−p_dataDecl _ _ _ (XHsDataDefn NoExt) = notImplemented "XHsDataDefn"
86+p_dataDecl _ _ _ _ (XHsDataDefn x) = noExtCon x
62
87
63−p_conDecl :: ConDecl GhcPs -> R ()
88+p_conDecl ::
64−p_conDecl = \case
89+ Bool ->
90+ ConDecl GhcPs ->
91+ R ()
92+p_conDecl singleConstRec = \case
65 ConDeclGADT {..} -> do
93 ConDeclGADT {..} -> do
66− spaceSep p_rdrName con_names
94+ mapM_ (p_hsDocString Pipe True) con_doc
67− breakpoint
95+ let conDeclSpn =
68− inci $ do
96+ fmap getLoc con_names
69− txt ":: "
97+ <> [getLoc con_forall]
70− p_forallBndrs (hsq_explicit con_qvars)
98+ <> conTyVarsSpans con_qvars
99+ <> maybeToList (fmap getLoc con_mb_cxt)
100+ <> conArgsSpans con_args
101+ switchLayout conDeclSpn $ do
102+ case con_names of
103+ [] -> return ()
104+ (c : cs) -> do
105+ p_rdrName c
106+ unless (null cs) . inci $ do
107+ commaDel
108+ sep commaDel p_rdrName cs
109+ inci $ do
110+ space
111+ txt "::"
112+ let interArgBreak =
113+ if hasDocStrings (unLoc con_res_ty)
114+ then newline
115+ else breakpoint
116+ interArgBreak
117+ when (unLoc con_forall) $ do
118+ p_forallBndrs ForallInvis p_hsTyVarBndr (hsq_explicit con_qvars)
119+ interArgBreak
120+ forM_ con_mb_cxt p_lhsContext
121+ case con_args of
122+ PrefixCon xs -> do
123+ sep breakpoint (located' p_hsType) xs
124+ unless (null xs) $ do
125+ space
126+ txt "->"
127+ breakpoint
128+ RecCon l -> do
129+ located l p_conDeclFields
130+ unless (null $ unLoc l) $ do
131+ space
132+ txt "->"
133+ breakpoint
134+ InfixCon _ _ -> notImplemented "InfixCon"
135+ p_hsType (unLoc con_res_ty)
136+ ConDeclH98 {..} -> do
137+ mapM_ (p_hsDocString Pipe True) con_doc
138+ let conDeclWithContextSpn =
139+ [getLoc con_forall]
140+ <> fmap getLoc con_ex_tvs
141+ <> maybeToList (fmap getLoc con_mb_cxt)
142+ <> conDeclSpn
143+ conDeclSpn =
144+ getLoc con_name : conArgsSpans con_args
145+ switchLayout conDeclWithContextSpn $ do
146+ when (unLoc con_forall) $ do
147+ p_forallBndrs ForallInvis p_hsTyVarBndr con_ex_tvs
148+ breakpoint
71 forM_ con_mb_cxt p_lhsContext
149 forM_ con_mb_cxt p_lhsContext
72− case con_args of
150+ switchLayout conDeclSpn $ case con_args of
73 PrefixCon xs -> do
151 PrefixCon xs -> do
74− velt' (located' p_hsType <$> xs)
152+ p_rdrName con_name
75− unless (null xs) $ do
153+ unless (null xs) breakpoint
76− breakpoint
154+ inci . sitcc $ sep breakpoint (sitcc . located' p_hsTypePostDoc) xs
77− txt "-> "
78 RecCon l -> do
155 RecCon l -> do
79− located l p_conDeclFields
80− unless (null $ unLoc l) $ do
81− breakpoint
82− txt "-> "
83− InfixCon _ _ -> notImplemented "InfixCon"
84− locatedVia Nothing con_res_ty p_hsType
85− ConDeclH98 {..} -> do
86− p_forallBndrs con_ex_tvs
87− forM_ con_mb_cxt p_lhsContext
88− case con_args of
89− PrefixCon xs -> do
90− p_rdrName con_name
91− unless (null xs) breakpoint
92− inci $ velt' (located' p_hsType <$> xs)
93− RecCon l -> do
94− p_rdrName con_name
95− breakpoint
96− inci $ located l p_conDeclFields
97− InfixCon x y -> do
98− located x p_hsType
99− breakpoint
100− inci $ do
101 p_rdrName con_name
156 p_rdrName con_name
102− space
157+ breakpoint
103− located y p_hsType
158+ inciIf (not singleConstRec) (located l p_conDeclFields)
104− XConDecl NoExt -> notImplemented "XConDecl"
159+ InfixCon x y -> do
160+ located x p_hsType
161+ breakpoint
162+ inci $ do
163+ p_rdrName con_name
164+ space
165+ located y p_hsType
166+ XConDecl x -> noExtCon x
167+
168+conArgsSpans :: HsConDeclDetails GhcPs -> [SrcSpan]
169+conArgsSpans = \case
170+ PrefixCon xs ->
171+ getLoc <$> xs
172+ RecCon l ->
173+ [getLoc l]
174+ InfixCon x y ->
175+ [getLoc x, getLoc y]
105
176
106−p_forallBndrs
177+conTyVarsSpans :: LHsQTyVars GhcPs -> [SrcSpan]
107− :: [LHsTyVarBndr GhcPs]
178+conTyVarsSpans = \case
108− -> R ()
179+ HsQTvs {..} -> getLoc <$> hsq_explicit
109−p_forallBndrs = \case
180+ XLHsQTyVars x -> noExtCon x
110− [] -> return ()
111− bndrs -> do
112− txt "forall "
113− spaceSep (located' p_hsTyVarBndr) bndrs
114− txt ". "
115
181
116−p_lhsContext
182+p_lhsContext ::
117− :: LHsContext GhcPs
183+ LHsContext GhcPs ->
118− -> R ()
184+ R ()
119p_lhsContext = \case
185p_lhsContext = \case
120 L _ [] -> pure ()
186 L _ [] -> pure ()
121 ctx -> do
187 ctx -> do
122 located ctx p_hsContext
188 located ctx p_hsContext
189+ space
190+ txt "=>"
123 breakpoint
191 breakpoint
124− txt "=> "
125
192
126isGadt :: ConDecl GhcPs -> Bool
193isGadt :: ConDecl GhcPs -> Bool
127isGadt = \case
194isGadt = \case
@@ -129,30 +196,35 @@ isGadt = \case
129 ConDeclH98 {} -> False
196 ConDeclH98 {} -> False
130 XConDecl {} -> False
197 XConDecl {} -> False
131
198
132−p_hsDerivingClause
199+p_hsDerivingClause ::
133− :: HsDerivingClause GhcPs
200+ HsDerivingClause GhcPs ->
134− -> R ()
201+ R ()
135p_hsDerivingClause HsDerivingClause {..} = do
202p_hsDerivingClause HsDerivingClause {..} = do
136 txt "deriving"
203 txt "deriving"
137 let derivingWhat = located deriv_clause_tys $ \case
204 let derivingWhat = located deriv_clause_tys $ \case
138 [] -> txt "()"
205 [] -> txt "()"
139− [x] -> located (hsib_body x) p_hsType
206+ xs ->
140− xs -> parens . velt $ withSep comma (located' p_hsType . hsib_body) xs
207+ parens N $
208+ sep
209+ commaDel
210+ (sitcc . located' p_hsType . hsib_body)
211+ xs
212+ space
141 case deriv_clause_strategy of
213 case deriv_clause_strategy of
142 Nothing -> do
214 Nothing -> do
143 breakpoint
215 breakpoint
144 inci derivingWhat
216 inci derivingWhat
145− Just l -> locatedVia Nothing l $ \case
217+ Just (L _ a) -> case a of
146 StockStrategy -> do
218 StockStrategy -> do
147− txt " stock"
219+ txt "stock"
148 breakpoint
220 breakpoint
149 inci derivingWhat
221 inci derivingWhat
150 AnyclassStrategy -> do
222 AnyclassStrategy -> do
151− txt " anyclass"
223+ txt "anyclass"
152 breakpoint
224 breakpoint
153 inci derivingWhat
225 inci derivingWhat
154 NewtypeStrategy -> do
226 NewtypeStrategy -> do
155− txt " newtype"
227+ txt "newtype"
156 breakpoint
228 breakpoint
157 inci derivingWhat
229 inci derivingWhat
158 ViaStrategy HsIB {..} -> do
230 ViaStrategy HsIB {..} -> do
@@ -160,8 +232,30 @@ p_hsDerivingClause HsDerivingClause {..} = do
160 inci $ do
232 inci $ do
161 derivingWhat
233 derivingWhat
162 breakpoint
234 breakpoint
163− txt "via "
235+ txt "via"
236+ space
164 located hsib_body p_hsType
237 located hsib_body p_hsType
165− ViaStrategy (XHsImplicitBndrs NoExt) ->
238+ ViaStrategy (XHsImplicitBndrs x) ->
166− notImplemented "XHsImplicitBndrs"
239+ noExtCon x
167−p_hsDerivingClause (XHsDerivingClause NoExt) = notImplemented "XHsDerivingClause"
240+p_hsDerivingClause (XHsDerivingClause x) = noExtCon x
241+
242+----------------------------------------------------------------------------
243+-- Helpers
244+
245+isInfix :: LexicalFixity -> Bool
246+isInfix = \case
247+ Infix -> True
248+ 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+6−7
@@ -1,21 +1,20 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3
3
4module Ormolu.Printer.Meat.Declaration.Default
4module Ormolu.Printer.Meat.Declaration.Default
5− ( p_defaultDecl
5+ ( p_defaultDecl,
6 )
6 )
7where
7where
8
8
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
13
12
14p_defaultDecl :: DefaultDecl GhcPs -> R ()
13p_defaultDecl :: DefaultDecl GhcPs -> R ()
15p_defaultDecl = \case
14p_defaultDecl = \case
16− DefaultDecl NoExt ts -> line $ do
15+ DefaultDecl NoExtField ts -> do
17 txt "default"
16 txt "default"
18 breakpoint
17 breakpoint
19− inci . parens . velt $
18+ inci . parens N $
20− withSep comma (located' p_hsType) ts
19+ sep commaDel (sitcc . located' p_hsType) ts
21− XDefaultDecl {} -> notImplemented "XDefaultDecl"
20+ XDefaultDecl x -> noExtCon x
src/Ormolu/Printer/Meat/Declaration/Foreign.hs+18−16
@@ -1,9 +1,9 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2−{-# LANGUAGE NamedFieldPuns #-}
2+{-# LANGUAGE NamedFieldPuns #-}
3{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE OverloadedStrings #-}
4
4
5module Ormolu.Printer.Meat.Declaration.Foreign
5module Ormolu.Printer.Meat.Declaration.Foreign
6− ( p_foreignDecl
6+ ( p_foreignDecl,
7 )
7 )
8where
8where
9
9
@@ -15,29 +15,30 @@ 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
19
18
20p_foreignDecl :: ForeignDecl GhcPs -> R ()
19p_foreignDecl :: ForeignDecl GhcPs -> R ()
21p_foreignDecl = \case
20p_foreignDecl = \case
22− fd@ForeignImport {fd_fi} -> line $ do
21+ fd@ForeignImport {fd_fi} -> do
23 p_foreignImport fd_fi
22 p_foreignImport fd_fi
24 p_foreignTypeSig fd
23 p_foreignTypeSig fd
25− fd@ForeignExport {fd_fe} -> line $ do
24+ fd@ForeignExport {fd_fe} -> do
26 p_foreignExport fd_fe
25 p_foreignExport fd_fe
27 p_foreignTypeSig fd
26 p_foreignTypeSig fd
28− XForeignDecl {} -> notImplemented "XForeignDecl"
27+ XForeignDecl x -> noExtCon x
29
28
30-- | Printer for the last part of an import\/export, which is function name
29-- | Printer for the last part of an import\/export, which is function name
31-- and type signature.
30-- and type signature.
32−
33p_foreignTypeSig :: ForeignDecl GhcPs -> R ()
31p_foreignTypeSig :: ForeignDecl GhcPs -> R ()
34p_foreignTypeSig fd = do
32p_foreignTypeSig fd = do
35 breakpoint
33 breakpoint
36− -- Switch into the layout of the signature, to allow us to pull name and
34+ inci
37− -- signature onto a single line.
35+ . switchLayout
38− inci . switchLayout (getLoc . hsib_body $ fd_sig_ty fd) $ do
36+ [ getLoc (fd_name fd),
39− p_rdrName (fd_name fd)
37+ (getLoc . hsib_body . fd_sig_ty) fd
40− p_typeAscription (HsWC NoExt (fd_sig_ty fd))
38+ ]
39+ $ do
40+ p_rdrName (fd_name fd)
41+ p_typeAscription (HsWC NoExtField (fd_sig_ty fd))
41
42
42-- | Printer for 'ForeignImport'.
43-- | Printer for 'ForeignImport'.
43--
44--
@@ -51,10 +52,10 @@ p_foreignTypeSig fd = do
51-- We also layout the identifier using the 'SourceText', because printing
52-- We also layout the identifier using the 'SourceText', because printing
52-- with the other two fields of 'CImport' is very complicated. See the
53-- with the other two fields of 'CImport' is very complicated. See the
53-- 'Outputable' instance of 'ForeignImport' for details.
54-- 'Outputable' instance of 'ForeignImport' for details.
54−
55p_foreignImport :: ForeignImport -> R ()
55p_foreignImport :: ForeignImport -> R ()
56p_foreignImport (CImport cCallConv safety _ _ sourceText) = do
56p_foreignImport (CImport cCallConv safety _ _ sourceText) = do
57− txt "foreign import "
57+ txt "foreign import"
58+ space
58 located cCallConv atom
59 located cCallConv atom
59 -- Need to check for 'noLoc' for the 'safe' annotation
60 -- Need to check for 'noLoc' for the 'safe' annotation
60 when (isGoodSrcSpan $ getLoc safety) (space >> atom safety)
61 when (isGoodSrcSpan $ getLoc safety) (space >> atom safety)
@@ -62,7 +63,8 @@ p_foreignImport (CImport cCallConv safety _ _ sourceText) = do
62
63
63p_foreignExport :: ForeignExport -> R ()
64p_foreignExport :: ForeignExport -> R ()
64p_foreignExport (CExport (L loc (CExportStatic _ _ cCallConv)) sourceText) = do
65p_foreignExport (CExport (L loc (CExportStatic _ _ cCallConv)) sourceText) = do
65− txt "foreign export "
66+ txt "foreign export"
67+ space
66 located (L loc cCallConv) atom
68 located (L loc cCallConv) atom
67 located sourceText p_sourceText
69 located sourceText p_sourceText
68
70
src/Ormolu/Printer/Meat/Declaration/Instance.hs+56−57
@@ -1,30 +1,29 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
4
4
5-- | Type class, type family, and data family instance declarations.
5-- | Type class, type family, and data family instance declarations.
6−
7module Ormolu.Printer.Meat.Declaration.Instance
6module Ormolu.Printer.Meat.Declaration.Instance
8− ( p_clsInstDecl
7+ ( p_clsInstDecl,
9− , p_tyFamInstDecl
8+ p_tyFamInstDecl,
10− , p_dataFamInstDecl
9+ p_dataFamInstDecl,
11− , p_standaloneDerivDecl
10+ p_standaloneDerivDecl,
12 )
11 )
13where
12where
14
13
15import BasicTypes
14import BasicTypes
16import Control.Arrow
15import Control.Arrow
16+import Control.Monad
17import Data.Foldable
17import Data.Foldable
18−import Data.List (sortBy)
18+import Data.List (sortOn)
19−import Data.Ord (comparing)
20import GHC
19import GHC
21import Ormolu.Printer.Combinators
20import Ormolu.Printer.Combinators
22import Ormolu.Printer.Meat.Common
21import Ormolu.Printer.Meat.Common
22+import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration
23import Ormolu.Printer.Meat.Declaration.Data
23import Ormolu.Printer.Meat.Declaration.Data
24import Ormolu.Printer.Meat.Declaration.TypeFamily
24import Ormolu.Printer.Meat.Declaration.TypeFamily
25import Ormolu.Printer.Meat.Type
25import Ormolu.Printer.Meat.Type
26import Ormolu.Utils
26import Ormolu.Utils
27−import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration
28
27
29p_standaloneDerivDecl :: DerivDecl GhcPs -> R ()
28p_standaloneDerivDecl :: DerivDecl GhcPs -> R ()
30p_standaloneDerivDecl DerivDecl {..} = do
29p_standaloneDerivDecl DerivDecl {..} = do
@@ -33,33 +32,30 @@ p_standaloneDerivDecl DerivDecl {..} = do
33 txt "instance"
32 txt "instance"
34 breakpoint
33 breakpoint
35 match_overlap_mode deriv_overlap_mode breakpoint
34 match_overlap_mode deriv_overlap_mode breakpoint
36− if toIndent
35+ inciIf toIndent typesAfterInstance
37− then inci typesAfterInstance
38− else typesAfterInstance
39 txt "deriving"
36 txt "deriving"
37+ space
40 case deriv_strategy of
38 case deriv_strategy of
41− Nothing -> do
39+ Nothing ->
42− space
43 instTypes False
40 instTypes False
44− Just l -> locatedVia Nothing l $ \case
41+ Just (L _ a) -> case a of
45 StockStrategy -> do
42 StockStrategy -> do
46− txt " stock "
43+ txt "stock "
47 instTypes False
44 instTypes False
48 AnyclassStrategy -> do
45 AnyclassStrategy -> do
49− txt " anyclass "
46+ txt "anyclass "
50 instTypes False
47 instTypes False
51 NewtypeStrategy -> do
48 NewtypeStrategy -> do
52− txt " newtype "
49+ txt "newtype "
53 instTypes False
50 instTypes False
54 ViaStrategy HsIB {..} -> do
51 ViaStrategy HsIB {..} -> do
55− txt " via"
52+ txt "via"
56 breakpoint
53 breakpoint
57 inci (located hsib_body p_hsType)
54 inci (located hsib_body p_hsType)
58 breakpoint
55 breakpoint
59 instTypes True
56 instTypes True
60− ViaStrategy (XHsImplicitBndrs NoExt) ->
57+ ViaStrategy (XHsImplicitBndrs x) ->
61− notImplemented "XHsImplicitBndrs"
58+ noExtCon x
62− newline
63p_standaloneDerivDecl (XDerivDecl _) = notImplemented "XDerivDecl"
59p_standaloneDerivDecl (XDerivDecl _) = notImplemented "XDerivDecl"
64
60
65p_clsInstDecl :: ClsInstDecl GhcPs -> R ()
61p_clsInstDecl :: ClsInstDecl GhcPs -> R ()
@@ -67,35 +63,37 @@ p_clsInstDecl = \case
67 ClsInstDecl {..} -> do
63 ClsInstDecl {..} -> do
68 txt "instance"
64 txt "instance"
69 case cid_poly_ty of
65 case cid_poly_ty of
70− HsIB {..} -> located hsib_body $ \x -> do
66+ HsIB {..} -> do
71− breakpoint
67+ -- GHC's AST does not necessarily store each kind of element in source
72− inci $ do
68+ -- location order. This happens because different declarations are stored in
73− match_overlap_mode cid_overlap_mode breakpoint
69+ -- different lists. Consequently, to get all the declarations in proper
74− p_hsType x
70+ -- order, they need to be manually sorted.
75− XHsImplicitBndrs NoExt -> notImplemented "XHsImplicitBndrs"
71+ let sigs = (getLoc &&& fmap (SigD NoExtField)) <$> cid_sigs
76− -- GHC's AST does not necessarily store each kind of element in source
72+ vals = (getLoc &&& fmap (ValD NoExtField)) <$> toList cid_binds
77− -- location order. This happens because different declarations are stored in
73+ tyFamInsts =
78− -- different lists. Consequently, to get all the declarations in proper
74+ ( getLoc &&& fmap (InstD NoExtField . TyFamInstD NoExtField)
79− -- order, they need to be manually sorted.
75+ )
80− let sigs = (getLoc &&& fmap (SigD NoExt)) <$> cid_sigs
76+ <$> cid_tyfam_insts
81− vals = (getLoc &&& fmap (ValD NoExt)) <$> toList cid_binds
77+ dataFamInsts =
82− tyFamInsts =
78+ ( getLoc &&& fmap (InstD NoExtField . DataFamInstD NoExtField)
83− ( getLoc &&& fmap (InstD NoExt . TyFamInstD NoExt)
79+ )
84− ) <$> cid_tyfam_insts
80+ <$> cid_datafam_insts
85− dataFamInsts =
81+ allDecls =
86− ( getLoc &&& fmap (InstD NoExt . DataFamInstD NoExt)
82+ snd <$> sortOn fst (sigs <> vals <> tyFamInsts <> dataFamInsts)
87− ) <$> cid_datafam_insts
83+ located hsib_body $ \x -> do
88− allDecls =
84+ breakpoint
89− snd <$>
85+ inci $ do
90− sortBy (comparing fst) (sigs <> vals <> tyFamInsts <> dataFamInsts)
86+ match_overlap_mode cid_overlap_mode breakpoint
91− if not (null allDecls)
87+ p_hsType x
92− then do
88+ unless (null allDecls) $ do
93− txt " where"
89+ breakpoint
94− newline -- Ensure line is added after where clause.
90+ txt "where"
95− newline -- Add newline before first declaration.
91+ unless (null allDecls) . inci $ do
96− inci (p_hsDecls Associated allDecls)
92+ -- Ensure whitespace is added after where clause.
97− else newline
93+ breakpoint
98− XClsInstDecl NoExt -> notImplemented "XClsInstDecl"
94+ dontUseBraces $ p_hsDeclsRespectGrouping Associated allDecls
95+ XHsImplicitBndrs x -> noExtCon x
96+ XClsInstDecl x -> noExtCon x
99
97
100p_tyFamInstDecl :: FamilyStyle -> TyFamInstDecl GhcPs -> R ()
98p_tyFamInstDecl :: FamilyStyle -> TyFamInstDecl GhcPs -> R ()
101p_tyFamInstDecl style = \case
99p_tyFamInstDecl style = \case
@@ -105,14 +103,15 @@ p_tyFamInstDecl style = \case
105 Free -> "type instance"
103 Free -> "type instance"
106 breakpoint
104 breakpoint
107 inci (p_tyFamInstEqn tfid_eqn)
105 inci (p_tyFamInstEqn tfid_eqn)
108− newline
109
106
110p_dataFamInstDecl :: FamilyStyle -> DataFamInstDecl GhcPs -> R ()
107p_dataFamInstDecl :: FamilyStyle -> DataFamInstDecl GhcPs -> R ()
111p_dataFamInstDecl style = \case
108p_dataFamInstDecl style = \case
112− DataFamInstDecl {..} -> do
109+ DataFamInstDecl {dfid_eqn = HsIB {hsib_body = FamEqn {..}}} ->
113− let HsIB {..} = dfid_eqn
110+ p_dataDecl style feqn_tycon (map typeArgToType feqn_pats) feqn_fixity feqn_rhs
114− FamEqn {..} = hsib_body
111+ DataFamInstDecl {dfid_eqn = HsIB {hsib_body = XFamEqn {}}} ->
115− p_dataDecl style feqn_tycon feqn_pats feqn_rhs
112+ notImplemented "XFamEqn"
113+ DataFamInstDecl {dfid_eqn = XHsImplicitBndrs {}} ->
114+ notImplemented "XHsImplicitBndrs"
116
115
117match_overlap_mode :: Maybe (Located OverlapMode) -> R () -> R ()
116match_overlap_mode :: Maybe (Located OverlapMode) -> R () -> R ()
118match_overlap_mode overlap_mode layoutStrategy =
117match_overlap_mode overlap_mode layoutStrategy =
src/Ormolu/Printer/Meat/Declaration/RoleAnnotation.hs+7−13
@@ -1,12 +1,10 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
4{-# LANGUAGE TypeFamilies #-}
3{-# LANGUAGE TypeFamilies #-}
5
4
6-- | Rendering of Role annotation declarations.
5-- | Rendering of Role annotation declarations.
7−
8module Ormolu.Printer.Meat.Declaration.RoleAnnotation
6module Ormolu.Printer.Meat.Declaration.RoleAnnotation
9− ( p_roleAnnot
7+ ( p_roleAnnot,
10 )
8 )
11where
9where
12
10
@@ -14,25 +12,21 @@ import CoAxiom
14import GHC
12import GHC
15import Ormolu.Printer.Combinators
13import Ormolu.Printer.Combinators
16import Ormolu.Printer.Meat.Common
14import Ormolu.Printer.Meat.Common
17−import Ormolu.Utils
18−import RdrName (RdrName (..))
19−import SrcLoc (Located)
20
15
21p_roleAnnot :: RoleAnnotDecl GhcPs -> R ()
16p_roleAnnot :: RoleAnnotDecl GhcPs -> R ()
22p_roleAnnot = \case
17p_roleAnnot = \case
23− RoleAnnotDecl NoExt l_name anns -> p_roleAnnot' l_name anns
18+ RoleAnnotDecl NoExtField l_name anns -> p_roleAnnot' l_name anns
24− XRoleAnnotDecl _ -> notImplemented "XRoleAnnotDecl"
19+ XRoleAnnotDecl x -> noExtCon x
25
20
26p_roleAnnot' :: Located RdrName -> [Located (Maybe Role)] -> R ()
21p_roleAnnot' :: Located RdrName -> [Located (Maybe Role)] -> R ()
27−p_roleAnnot' l_name anns = line $ do
22+p_roleAnnot' l_name anns = do
28 txt "type role"
23 txt "type role"
29 breakpoint
24 breakpoint
30 inci $ do
25 inci $ do
31 p_rdrName l_name
26 p_rdrName l_name
32 breakpoint
27 breakpoint
33− let
28+ let p_role' = maybe (txt "_") p_role
34− p_role' = maybe (txt "_") p_role
29+ inci . sitcc $ sep breakpoint (sitcc . located' p_role') anns
35− inci $ velt' $ (located' p_role') <$> anns
36
30
37p_role :: Role -> R ()
31p_role :: Role -> R ()
38p_role = \case
32p_role = \case
src/Ormolu/Printer/Meat/Declaration/Rule.hsnew file+61
@@ -0,0 +1,61 @@
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+
4+module Ormolu.Printer.Meat.Declaration.Rule
5+ ( p_ruleDecls,
6+ )
7+where
8+
9+import BasicTypes
10+import Control.Monad (unless)
11+import GHC
12+import Ormolu.Printer.Combinators
13+import Ormolu.Printer.Meat.Common
14+import Ormolu.Printer.Meat.Declaration.Signature
15+import Ormolu.Printer.Meat.Declaration.Value
16+import Ormolu.Printer.Meat.Type
17+
18+p_ruleDecls :: RuleDecls GhcPs -> R ()
19+p_ruleDecls = \case
20+ HsRules NoExtField _ xs ->
21+ pragma "RULES" $
22+ sep breakpoint (sitcc . located' p_ruleDecl) xs
23+ XRuleDecls x -> noExtCon x
24+
25+p_ruleDecl :: RuleDecl GhcPs -> R ()
26+p_ruleDecl = \case
27+ HsRule NoExtField ruleName activation tyvars ruleBndrs lhs rhs -> do
28+ located ruleName p_ruleName
29+ space
30+ p_activation activation
31+ space
32+ case tyvars of
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
43+ inci $ do
44+ located lhs p_hsExpr
45+ space
46+ equals
47+ inci $ do
48+ breakpoint
49+ located rhs p_hsExpr
50+ XRuleDecl x -> noExtCon x
51+
52+p_ruleName :: (SourceText, RuleName) -> R ()
53+p_ruleName (_, name) = atom $ (HsString NoSourceText name :: HsLit GhcPs)
54+
55+p_ruleBndr :: RuleBndr GhcPs -> R ()
56+p_ruleBndr = \case
57+ RuleBndr NoExtField x -> p_rdrName x
58+ RuleBndrSig NoExtField x hswc -> parens N $ do
59+ p_rdrName x
60+ p_typeAscription hswc
61+ XRuleBndr x -> noExtCon x
src/Ormolu/Printer/Meat/Declaration/Signature.hs+162−113
@@ -1,13 +1,13 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
4
4
5-- | Type signature declarations.
5-- | Type signature declarations.
6−
7module Ormolu.Printer.Meat.Declaration.Signature
6module Ormolu.Printer.Meat.Declaration.Signature
8− ( p_sigDecl
7+ ( p_sigDecl,
9− , p_sigDecl'
8+ p_typeAscription,
10− , p_typeAscription
9+ p_activation,
10+ p_standaloneKindSig,
11 )
11 )
12where
12where
13
13
@@ -21,69 +21,82 @@ import Ormolu.Printer.Meat.Type
21import Ormolu.Utils
21import Ormolu.Utils
22
22
23p_sigDecl :: Sig GhcPs -> R ()
23p_sigDecl :: Sig GhcPs -> R ()
24−p_sigDecl = line . p_sigDecl'
24+p_sigDecl = \case
25−
25+ TypeSig NoExtField names hswc -> p_typeSig True names hswc
26−p_sigDecl' :: Sig GhcPs -> R ()
26+ PatSynSig NoExtField names hsib -> p_patSynSig names hsib
27−p_sigDecl' = \case
27+ ClassOpSig NoExtField def names hsib -> p_classOpSig def names hsib
28− TypeSig NoExt names hswc -> p_typeSig names hswc
28+ FixSig NoExtField sig -> p_fixSig sig
29− PatSynSig NoExt names hsib -> p_patSynSig names hsib
29+ InlineSig NoExtField name inlinePragma -> p_inlineSig name inlinePragma
30− ClassOpSig NoExt def names hsib -> p_classOpSig def names hsib
30+ SpecSig NoExtField name ts inlinePragma -> p_specSig name ts inlinePragma
31− FixSig NoExt sig -> p_fixSig sig
31+ SpecInstSig NoExtField _ hsib -> p_specInstSig hsib
32− InlineSig NoExt name inlinePragma -> p_inlineSig name inlinePragma
32+ MinimalSig NoExtField _ booleanFormula -> p_minimalSig booleanFormula
33− SpecSig NoExt name ts inlinePragma -> p_specSig name ts inlinePragma
33+ CompleteMatchSig NoExtField _sourceText cs ty -> p_completeSig cs ty
34− SpecInstSig NoExt _ hsib -> p_specInstSig hsib
34+ SCCFunSig NoExtField _ name literal -> p_sccSig name literal
35− MinimalSig NoExt _ booleanFormula -> p_minimalSig booleanFormula
36− CompleteMatchSig NoExt _sourceText cs ty -> p_completeSig cs ty
37− SCCFunSig NoExt _ name literal -> p_sccSig name literal
38 _ -> notImplemented "certain types of signature declarations"
35 _ -> notImplemented "certain types of signature declarations"
39
36
40−p_typeSig
37+p_typeSig ::
41− :: [Located RdrName] -- ^ Names (before @::@)
38+ -- | Should the tail of the names be indented
42− -> LHsSigWcType GhcPs -- ^ Type
39+ Bool ->
43− -> R ()
40+ -- | Names (before @::@)
44−p_typeSig [] _ = return () -- should not happen though
41+ [Located RdrName] ->
45−p_typeSig (n:ns) hswc = do
42+ -- | Type
43+ LHsSigWcType GhcPs ->
44+ R ()
45+p_typeSig _ [] _ = return () -- should not happen though
46+p_typeSig indentTail (n : ns) hswc = do
46 p_rdrName n
47 p_rdrName n
47 if null ns
48 if null ns
48 then p_typeAscription hswc
49 then p_typeAscription hswc
49− else inci $ do
50+ else inciIf indentTail $ do
50− vlayout (return ()) newline
51+ commaDel
51− comma
52+ sep commaDel p_rdrName ns
52− velt (withSep comma p_rdrName ns)
53 p_typeAscription hswc
53 p_typeAscription hswc
54
54
55−p_typeAscription
55+p_typeAscription ::
56− :: LHsSigWcType GhcPs
56+ LHsSigWcType GhcPs ->
57− -> R ()
57+ R ()
58−p_typeAscription HsWC {..} = do
58+p_typeAscription HsWC {..} = inci $ do
59− breakpoint
59+ space
60− inci $ do
60+ txt "::"
61− txt ":: "
61+ let t = hsib_body hswc_body
62− located (hsib_body hswc_body) p_hsType
62+ if hasDocStrings (unLoc t)
63−p_typeAscription (XHsWildCardBndrs NoExt) = notImplemented "XHsWildCardBndrs"
63+ then newline
64−
64+ else breakpoint
65−p_patSynSig
65+ located t p_hsType
66− :: [Located RdrName]
66+p_typeAscription (XHsWildCardBndrs x) = noExtCon x
67− -> HsImplicitBndrs GhcPs (LHsType GhcPs)
67+
68− -> R ()
68+p_patSynSig ::
69+ [Located RdrName] ->
70+ HsImplicitBndrs GhcPs (LHsType GhcPs) ->
71+ R ()
69p_patSynSig names hsib = do
72p_patSynSig names hsib = do
70− txt "pattern "
73+ txt "pattern"
71− p_typeSig names HsWC {hswc_ext = NoExt, hswc_body = hsib}
74+ let body =
72−
75+ p_typeSig
73−p_classOpSig
76+ False
74− :: Bool -- ^ Whether this is a \"default\" signature
77+ names
75− -> [Located RdrName] -- ^ Names (before @::@)
78+ HsWC {hswc_ext = NoExtField, hswc_body = hsib}
76− -> HsImplicitBndrs GhcPs (LHsType GhcPs) -- ^ Type
79+ if length names > 1
77− -> R ()
80+ then breakpoint >> inci body
78−p_classOpSig def names hsib = do
81+ else space >> body
79− when def (txt "default ")
82+
80− p_typeSig names HsWC {hswc_ext = NoExt, hswc_body = hsib}
83+p_classOpSig ::
81−
84+ -- | Whether this is a \"default\" signature
82−p_fixSig
85+ Bool ->
83− :: FixitySig GhcPs
86+ -- | Names (before @::@)
84− -> R ()
87+ [Located RdrName] ->
88+ -- | Type
89+ HsImplicitBndrs GhcPs (LHsType GhcPs) ->
90+ R ()
91+p_classOpSig def names hsib = do
92+ when def (txt "default" >> space)
93+ p_typeSig True names HsWC {hswc_ext = NoExtField, hswc_body = hsib}
94+
95+p_fixSig ::
96+ FixitySig GhcPs ->
97+ R ()
85p_fixSig = \case
98p_fixSig = \case
86− FixitySig NoExt names (Fixity _ n dir) -> do
99+ FixitySig NoExtField names (Fixity _ n dir) -> do
87 txt $ case dir of
100 txt $ case dir of
88 InfixL -> "infixl"
101 InfixL -> "infixl"
89 InfixR -> "infixr"
102 InfixR -> "infixr"
@@ -91,40 +104,53 @@ p_fixSig = \case
91 space
104 space
92 atom n
105 atom n
93 space
106 space
94− sequence_ (withSep comma p_rdrName names)
107+ sitcc $ sep commaDel p_rdrName names
95− XFixitySig NoExt -> notImplemented "XFixitySig"
108+ XFixitySig x -> noExtCon x
96−
109+
97−p_inlineSig
110+p_inlineSig ::
98− :: Located RdrName -- ^ Name
111+ -- | Name
99− -> InlinePragma -- ^ Inline pragma specification
112+ Located RdrName ->
100− -> R ()
113+ -- | Inline pragma specification
114+ InlinePragma ->
115+ R ()
101p_inlineSig name InlinePragma {..} = pragmaBraces $ do
116p_inlineSig name InlinePragma {..} = pragmaBraces $ do
102− txt $ case inl_inline of
117+ p_inlineSpec inl_inline
103− Inline -> "INLINE"
118+ space
104− Inlinable -> "INLINEABLE"
119+ case inl_rule of
105− NoInline -> "NOINLINE"
120+ ConLike -> txt "CONLIKE"
106− NoUserInline -> notImplemented "NoUserInline"
121+ FunLike -> return ()
107 space
122 space
108 p_activation inl_act
123 p_activation inl_act
124+ space
109 p_rdrName name
125 p_rdrName name
110
126
111−p_specSig
127+p_specSig ::
112− :: Located RdrName -- ^ Name
128+ -- | Name
113− -> [LHsSigType GhcPs] -- ^ The types to specialize to
129+ Located RdrName ->
114− -> InlinePragma -- ^ For specialize inline
130+ -- | The types to specialize to
115− -> R ()
131+ [LHsSigType GhcPs] ->
132+ -- | For specialize inline
133+ InlinePragma ->
134+ R ()
116p_specSig name ts InlinePragma {..} = pragmaBraces $ do
135p_specSig name ts InlinePragma {..} = pragmaBraces $ do
117 txt "SPECIALIZE"
136 txt "SPECIALIZE"
118 space
137 space
138+ p_inlineSpec inl_inline
139+ space
119 p_activation inl_act
140 p_activation inl_act
141+ space
120 p_rdrName name
142 p_rdrName name
143+ space
144+ txt "::"
121 breakpoint
145 breakpoint
122− inci $ do
146+ inci $ sep commaDel (located' p_hsType . hsib_body) ts
123− txt ":: "
147+
124− -- XXX Not at all sure why ts is a list of @LHsSigType GhcPs@ things, it
148+p_inlineSpec :: InlineSpec -> R ()
125− -- appears that we only can give one type to specialize to per pragma.
149+p_inlineSpec = \case
126− -- Maybe I'm mistaken.
150+ Inline -> txt "INLINE"
127− located (hsib_body (head ts)) p_hsType
151+ Inlinable -> txt "INLINEABLE"
152+ NoInline -> txt "NOINLINE"
153+ NoUserInline -> return ()
128
154
129p_activation :: Activation -> R ()
155p_activation :: Activation -> R ()
130p_activation = \case
156p_activation = \case
@@ -134,54 +160,77 @@ p_activation = \case
134 txt "[~"
160 txt "[~"
135 atom n
161 atom n
136 txt "]"
162 txt "]"
137− space
138 ActiveAfter _ n -> do
163 ActiveAfter _ n -> do
139 txt "["
164 txt "["
140 atom n
165 atom n
141 txt "]"
166 txt "]"
142− space
143
167
144p_specInstSig :: LHsSigType GhcPs -> R ()
168p_specInstSig :: LHsSigType GhcPs -> R ()
145−p_specInstSig hsib = pragma "SPECIALIZE instance" $
169+p_specInstSig hsib =
146− located (hsib_body hsib) p_hsType
170+ pragma "SPECIALIZE instance" . inci $
147−
171+ located (hsib_body hsib) p_hsType
148−p_minimalSig
172+
149− :: LBooleanFormula (Located RdrName) -- ^ Boolean formula
173+p_minimalSig ::
150− -> R ()
174+ -- | Boolean formula
175+ LBooleanFormula (Located RdrName) ->
176+ R ()
151p_minimalSig =
177p_minimalSig =
152 located' $ \booleanFormula ->
178 located' $ \booleanFormula ->
153− pragma "MINIMAL" (p_booleanFormula booleanFormula)
179+ pragma "MINIMAL" (inci $ p_booleanFormula booleanFormula)
154
180
155−p_booleanFormula
181+p_booleanFormula ::
156− :: BooleanFormula (Located RdrName) -- ^ Boolean formula
182+ -- | Boolean formula
157− -> R ()
183+ BooleanFormula (Located RdrName) ->
184+ R ()
158p_booleanFormula = \case
185p_booleanFormula = \case
159 Var name -> p_rdrName name
186 Var name -> p_rdrName name
160− And xs -> velt $
187+ And xs ->
161− withSep comma (located' p_booleanFormula) xs
188+ sitcc $
162− Or xs -> velt $
189+ sep
163− withSep (vlayout space (return ()) >> txt "| ")
190+ commaDel
164− (located' p_booleanFormula)
191+ (located' p_booleanFormula)
165− xs
192+ xs
166− Parens l -> located l (parens . p_booleanFormula)
193+ Or xs ->
167−
194+ sitcc $
168−p_completeSig
195+ sep
169− :: Located [Located RdrName] -- ^ Constructors\/patterns
196+ (breakpoint >> txt "|" >> space)
170− -> Maybe (Located RdrName) -- ^ Type
197+ (located' p_booleanFormula)
171− -> R ()
198+ xs
199+ Parens l -> located l (parens N . p_booleanFormula)
200+
201+p_completeSig ::
202+ -- | Constructors\/patterns
203+ Located [Located RdrName] ->
204+ -- | Type
205+ Maybe (Located RdrName) ->
206+ R ()
172p_completeSig cs' mty =
207p_completeSig cs' mty =
173 located cs' $ \cs ->
208 located cs' $ \cs ->
174− pragma "COMPLETE" $ do
209+ pragma "COMPLETE" . inci $ do
175− velt (withSep comma p_rdrName cs)
210+ sep commaDel p_rdrName cs
176 forM_ mty $ \ty -> do
211 forM_ mty $ \ty -> do
212+ space
213+ txt "::"
177 breakpoint
214 breakpoint
178− inci $ do
215+ inci (p_rdrName ty)
179− txt ":: "
180− p_rdrName ty
181
216
182p_sccSig :: Located (IdP GhcPs) -> Maybe (Located StringLiteral) -> R ()
217p_sccSig :: Located (IdP GhcPs) -> Maybe (Located StringLiteral) -> R ()
183−p_sccSig loc literal = pragma "SCC" $ do
218+p_sccSig loc literal = pragma "SCC" . inci $ do
184 p_rdrName loc
219 p_rdrName loc
185 forM_ literal $ \x -> do
220 forM_ literal $ \x -> do
186 breakpoint
221 breakpoint
187 atom x
222 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−4
@@ -1,16 +1,15 @@
1{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE LambdaCase #-}
2
2
3module Ormolu.Printer.Meat.Declaration.Splice
3module Ormolu.Printer.Meat.Declaration.Splice
4− ( p_spliceDecl
4+ ( p_spliceDecl,
5 )
5 )
6where
6where
7
7
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
12
11
13p_spliceDecl :: SpliceDecl GhcPs -> R ()
12p_spliceDecl :: SpliceDecl GhcPs -> R ()
14p_spliceDecl = \case
13p_spliceDecl = \case
15− SpliceDecl NoExt splice _explicit -> line $ located splice p_hsSplice
14+ SpliceDecl NoExtField splice _explicit -> located splice p_hsSplice
16− XSpliceDecl {} -> notImplemented "XSpliceDecl"
15+ XSpliceDecl x -> noExtCon x
src/Ormolu/Printer/Meat/Declaration/Type.hs+28−19
@@ -1,31 +1,40 @@
1{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE RecordWildCards #-}
2+{-# LANGUAGE RecordWildCards #-}
3
3
4-- | Rendering of type synonym declarations.
4-- | Rendering of type synonym declarations.
5−
6module Ormolu.Printer.Meat.Declaration.Type
5module Ormolu.Printer.Meat.Declaration.Type
7− ( p_synDecl
6+ ( p_synDecl,
8 )
7 )
9where
8where
10
9
11−import Control.Monad
12import GHC
10import GHC
13import Ormolu.Printer.Combinators
11import Ormolu.Printer.Combinators
14import Ormolu.Printer.Meat.Common
12import Ormolu.Printer.Meat.Common
15import Ormolu.Printer.Meat.Type
13import Ormolu.Printer.Meat.Type
16−import RdrName (RdrName (..))
17−import SrcLoc (Located)
18
14
19−p_synDecl
15+p_synDecl ::
20− :: Located RdrName -- ^ Type constructor
16+ -- | Type constructor
21− -> LHsQTyVars GhcPs -- ^ Type variables
17+ Located RdrName ->
22− -> LHsType GhcPs -- ^ RHS of type declaration
18+ -- | Fixity
23− -> R ()
19+ LexicalFixity ->
24−p_synDecl name tvars t = line $ do
20+ -- | Type variables
25− txt "type "
21+ LHsQTyVars GhcPs ->
26− p_rdrName name
22+ -- | RHS of type declaration
27− let HsQTvs {..} = tvars
23+ LHsType GhcPs ->
28− unless (null hsq_explicit) space
24+ R ()
29− spaceSep (located' p_hsTyVarBndr) hsq_explicit
25+p_synDecl name fixity HsQTvs {..} t = do
30− breakpoint
26+ txt "type"
31− inci (txt "= " >> located t p_hsType)
27+ space
28+ switchLayout (getLoc name : map getLoc hsq_explicit) $
29+ p_infixDefHelper
30+ (case fixity of Infix -> True; _ -> False)
31+ True
32+ (p_rdrName name)
33+ (map (located' p_hsTyVarBndr) hsq_explicit)
34+ space
35+ equals
36+ if hasDocStrings (unLoc t)
37+ then newline
38+ else breakpoint
39+ inci (located t p_hsType)
40+p_synDecl _ _ (XLHsQTyVars x) _ = noExtCon x
src/Ormolu/Printer/Meat/Declaration/TypeFamily.hs+62−54
@@ -1,103 +1,111 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
4
4
5-- | Rendering of data\/type families.
5-- | Rendering of data\/type families.
6−
7module Ormolu.Printer.Meat.Declaration.TypeFamily
6module Ormolu.Printer.Meat.Declaration.TypeFamily
8− ( p_famDecl
7+ ( p_famDecl,
9− , p_tyFamInstEqn
8+ p_tyFamInstEqn,
10 )
9 )
11where
10where
12
11
13−import BasicTypes (LexicalFixity (..))
14import Control.Monad
12import Control.Monad
15−import Data.List.NonEmpty (NonEmpty (..))
13+import Data.Maybe (isNothing)
16−import Data.Maybe (isNothing, isJust)
17import GHC
14import GHC
18import Ormolu.Printer.Combinators
15import Ormolu.Printer.Combinators
19import Ormolu.Printer.Meat.Common
16import Ormolu.Printer.Meat.Common
20import Ormolu.Printer.Meat.Type
17import Ormolu.Printer.Meat.Type
21import Ormolu.Utils
18import Ormolu.Utils
22−import SrcLoc (Located, GenLocated (..))
23
19
24p_famDecl :: FamilyStyle -> FamilyDecl GhcPs -> R ()
20p_famDecl :: FamilyStyle -> FamilyDecl GhcPs -> R ()
25−p_famDecl style FamilyDecl {..} = do
21+p_famDecl style FamilyDecl {fdTyVars = HsQTvs {..}, ..} = do
26 mmeqs <- case fdInfo of
22 mmeqs <- case fdInfo of
27 DataFamily -> Nothing <$ txt "data"
23 DataFamily -> Nothing <$ txt "data"
28 OpenTypeFamily -> Nothing <$ txt "type"
24 OpenTypeFamily -> Nothing <$ txt "type"
29 ClosedTypeFamily eqs -> Just eqs <$ txt "type"
25 ClosedTypeFamily eqs -> Just eqs <$ txt "type"
30− txt $ case style of
26+ txt $ case style of
31 Associated -> mempty
27 Associated -> mempty
32 Free -> " family"
28 Free -> " family"
33− let HsQTvs {..} = fdTyVars
34− combinedSpans = combineSrcSpans' $
35− getLoc fdLName :| fmap getLoc hsq_explicit
36 breakpoint
29 breakpoint
37 inci $ do
30 inci $ do
38− switchLayout combinedSpans $ do
31+ switchLayout (getLoc fdLName : (getLoc <$> hsq_explicit)) $
39 p_infixDefHelper
32 p_infixDefHelper
40 (isInfix fdFixity)
33 (isInfix fdFixity)
41− inci
34+ True
42 (p_rdrName fdLName)
35 (p_rdrName fdLName)
43 (located' p_hsTyVarBndr <$> hsq_explicit)
36 (located' p_hsTyVarBndr <$> hsq_explicit)
44− let rsig = p_familyResultSigL (isJust fdInjectivityAnn) fdResultSig
37+ let resultSig = p_familyResultSigL fdResultSig
45− unless (isNothing rsig && isNothing fdInjectivityAnn) $
38+ unless (isNothing resultSig && isNothing fdInjectivityAnn) space
46− breakpoint
47 inci $ do
39 inci $ do
48− sequence_ rsig
40+ sequence_ resultSig
49− when (isJust rsig && isJust fdInjectivityAnn) breakpoint
41+ space
50 forM_ fdInjectivityAnn (located' p_injectivityAnn)
42 forM_ fdInjectivityAnn (located' p_injectivityAnn)
51 case mmeqs of
43 case mmeqs of
52− Nothing -> newline
44+ Nothing -> return ()
53 Just meqs -> do
45 Just meqs -> do
54− txt " where"
46+ inci $ do
47+ breakpoint
48+ txt "where"
55 case meqs of
49 case meqs of
56− Nothing -> txt " .." >> newline
50+ Nothing -> do
51+ space
52+ txt ".."
57 Just eqs -> do
53 Just eqs -> do
58 newline
54 newline
59− forM_ eqs (located' (line . inci . p_tyFamInstEqn))
55+ sep newline (located' (inci . p_tyFamInstEqn)) eqs
60−p_famDecl _ (XFamilyDecl NoExt) = notImplemented "XFamilyDecl"
56+p_famDecl _ FamilyDecl {fdTyVars = XLHsQTyVars {}} =
57+ notImplemented "XLHsQTyVars"
58+p_famDecl _ (XFamilyDecl x) = noExtCon x
61
59
62−p_familyResultSigL
60+p_familyResultSigL ::
63− :: Bool
61+ Located (FamilyResultSig GhcPs) ->
64− -> Located (FamilyResultSig GhcPs)
62+ Maybe (R ())
65− -> Maybe (R ())
63+p_familyResultSigL l =
66−p_familyResultSigL injAnn l =
67 case l of
64 case l of
68 L _ a -> case a of
65 L _ a -> case a of
69− NoSig NoExt -> Nothing
66+ NoSig NoExtField -> Nothing
70− KindSig NoExt k -> Just $ do
67+ KindSig NoExtField k -> Just $ do
71− if injAnn then txt "= " else txt ":: "
68+ txt "::"
69+ breakpoint
72 located k p_hsType
70 located k p_hsType
73− TyVarSig NoExt bndr -> Just $ do
71+ TyVarSig NoExtField bndr -> Just $ do
74− if injAnn then txt "= " else txt ":: "
72+ equals
73+ breakpoint
75 located bndr p_hsTyVarBndr
74 located bndr p_hsTyVarBndr
76− XFamilyResultSig NoExt ->
75+ XFamilyResultSig x ->
77− notImplemented "XFamilyResultSig"
76+ noExtCon x
78
77
79p_injectivityAnn :: InjectivityAnn GhcPs -> R ()
78p_injectivityAnn :: InjectivityAnn GhcPs -> R ()
80p_injectivityAnn (InjectivityAnn a bs) = do
79p_injectivityAnn (InjectivityAnn a bs) = do
81− txt "| "
80+ txt "|"
81+ space
82 p_rdrName a
82 p_rdrName a
83 space
83 space
84− txt "-> "
84+ txt "->"
85− spaceSep p_rdrName bs
85+ space
86+ sep space p_rdrName bs
86
87
87p_tyFamInstEqn :: TyFamInstEqn GhcPs -> R ()
88p_tyFamInstEqn :: TyFamInstEqn GhcPs -> R ()
88−p_tyFamInstEqn HsIB {..} = do
89+p_tyFamInstEqn HsIB {hsib_body = FamEqn {..}} = do
89− let FamEqn {..} = hsib_body
90+ case feqn_bndrs of
90− combinedSpans = combineSrcSpans' $
91+ Nothing -> return ()
91− getLoc feqn_tycon :| fmap getLoc feqn_pats
92+ Just bndrs -> do
92− switchLayout combinedSpans $ p_infixDefHelper
93+ p_forallBndrs ForallInvis p_hsTyVarBndr bndrs
93− (isInfix feqn_fixity)
94+ breakpoint
94− inci
95+ inciIf (not $ null feqn_bndrs) $ do
95− (p_rdrName feqn_tycon)
96+ let famLhsSpn = getLoc feqn_tycon : fmap (getLoc . typeArgToType) feqn_pats
96− (located' p_hsType <$> feqn_pats)
97+ switchLayout famLhsSpn $
97− txt " ="
98+ p_infixDefHelper
98− breakpoint
99+ (isInfix feqn_fixity)
99− inci (located feqn_rhs p_hsType)
100+ True
100−p_tyFamInstEqn (XHsImplicitBndrs NoExt) = notImplemented "XHsImplicitBndrs"
101+ (p_rdrName feqn_tycon)
102+ (located' p_hsType . typeArgToType <$> feqn_pats)
103+ space
104+ equals
105+ breakpoint
106+ inci (located feqn_rhs p_hsType)
107+p_tyFamInstEqn HsIB {hsib_body = XFamEqn x} = noExtCon x
108+p_tyFamInstEqn (XHsImplicitBndrs x) = noExtCon x
101
109
102----------------------------------------------------------------------------
110----------------------------------------------------------------------------
103-- Helpers
111-- Helpers
src/Ormolu/Printer/Meat/Declaration/Value.hs+1052−515
@@ -1,33 +1,43 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE MultiWayIf #-}
2{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
4+{-# LANGUAGE RecordWildCards #-}
5+{-# LANGUAGE TypeApplications #-}
4
6
5module Ormolu.Printer.Meat.Declaration.Value
7module Ormolu.Printer.Meat.Declaration.Value
6− ( p_valDecl
8+ ( p_valDecl,
7− , p_pat
9+ p_pat,
8− , p_hsExpr
10+ p_hsExpr,
9− , p_hsSplice
11+ p_hsSplice,
12+ p_stringLit,
10 )
13 )
11where
14where
12
15
13import Bag (bagToList)
16import Bag (bagToList)
14import BasicTypes
17import BasicTypes
15import Control.Monad
18import Control.Monad
19+import Ctype (is_space)
16import Data.Bool (bool)
20import Data.Bool (bool)
21+import Data.Char (isPunctuation, isSymbol)
17import Data.Data hiding (Infix, Prefix)
22import Data.Data hiding (Infix, Prefix)
23+import Data.Functor ((<&>))
18import Data.List (intersperse, sortOn)
24import Data.List (intersperse, sortOn)
25+import Data.List.NonEmpty (NonEmpty (..), (<|))
26+import qualified Data.List.NonEmpty as NE
19import Data.Text (Text)
27import Data.Text (Text)
28+import qualified Data.Text as Text
20import GHC
29import GHC
30+import OccName (occNameString)
21import Ormolu.Printer.Combinators
31import Ormolu.Printer.Combinators
32+import Ormolu.Printer.Internal
22import Ormolu.Printer.Meat.Common
33import Ormolu.Printer.Meat.Common
34+import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration
23import Ormolu.Printer.Meat.Declaration.Signature
35import Ormolu.Printer.Meat.Declaration.Signature
24import Ormolu.Printer.Meat.Type
36import Ormolu.Printer.Meat.Type
37+import Ormolu.Printer.Operators
25import Ormolu.Utils
38import Ormolu.Utils
26−import Outputable (Outputable (..))
27−import SrcLoc (combineSrcSpans, isOneLineSpan)
28−import qualified Data.List.NonEmpty as NE
29−import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration
30
39
40+-- | Style of a group of equations.
31data MatchGroupStyle
41data MatchGroupStyle
32 = Function (Located RdrName)
42 = Function (Located RdrName)
33 | PatternBind
43 | PatternBind
@@ -35,714 +45,1062 @@ data MatchGroupStyle
35 | Lambda
45 | Lambda
36 | LambdaCase
46 | LambdaCase
37
47
48+-- | Style of equations in a group.
38data GroupStyle
49data GroupStyle
39 = EqualSign
50 = EqualSign
40 | RightArrow
51 | RightArrow
41
52
42-- | Expression placement. This marks the places where expressions that
53-- | Expression placement. This marks the places where expressions that
43-- implement handing forms may use them.
54-- implement handing forms may use them.
44−
45data Placement
55data Placement
46− = Normal -- ^ Multi-line layout should cause
56+ = -- | Multi-line layout should cause
47− -- insertion of a newline and indentation
57+ -- insertion of a newline and indentation
48− -- bump
58+ -- bump
49− | Hanging -- ^ Expressions that have hanging form
59+ Normal
50− -- should use it and avoid bumping one level
60+ | -- | Expressions that have hanging form
51− -- of indentation
61+ -- should use it and avoid bumping one level
62+ -- of indentation
63+ Hanging
64+ deriving (Eq, Show)
52
65
53p_valDecl :: HsBindLR GhcPs GhcPs -> R ()
66p_valDecl :: HsBindLR GhcPs GhcPs -> R ()
54−p_valDecl = line . p_valDecl'
67+p_valDecl = \case
55−
68+ FunBind NoExtField funId funMatches _ _ -> p_funBind funId funMatches
56−p_valDecl' :: HsBindLR GhcPs GhcPs -> R ()
69+ PatBind NoExtField pat grhss _ -> p_match PatternBind False NoSrcStrict [pat] grhss
57−p_valDecl' = \case
58− FunBind NoExt funId funMatches _ _ -> p_funBind funId funMatches
59− PatBind NoExt pat grhss _ -> p_match PatternBind False [pat] grhss
60 VarBind {} -> notImplemented "VarBinds" -- introduced by the type checker
70 VarBind {} -> notImplemented "VarBinds" -- introduced by the type checker
61 AbsBinds {} -> notImplemented "AbsBinds" -- introduced by the type checker
71 AbsBinds {} -> notImplemented "AbsBinds" -- introduced by the type checker
62− PatSynBind NoExt psb -> p_patSynBind psb
72+ PatSynBind NoExtField psb -> p_patSynBind psb
63− XHsBindsLR NoExt -> notImplemented "XHsBindsLR"
73+ XHsBindsLR x -> noExtCon x
64−
74+
65−p_funBind
75+p_funBind ::
66− :: Located RdrName
76+ Located RdrName ->
67− -> MatchGroup GhcPs (LHsExpr GhcPs)
77+ MatchGroup GhcPs (LHsExpr GhcPs) ->
68− -> R ()
78+ R ()
69−p_funBind name mgroup =
79+p_funBind name = p_matchGroup (Function name)
70− p_matchGroup (Function name) mgroup
80+
71−
81+p_matchGroup ::
72−p_matchGroup
82+ MatchGroupStyle ->
73− :: MatchGroupStyle
83+ MatchGroup GhcPs (LHsExpr GhcPs) ->
74− -> MatchGroup GhcPs (LHsExpr GhcPs)
84+ R ()
75− -> R ()
76p_matchGroup = p_matchGroup' exprPlacement p_hsExpr
85p_matchGroup = p_matchGroup' exprPlacement p_hsExpr
77
86
78−p_matchGroup'
87+p_matchGroup' ::
79− :: Data body
88+ Data body =>
80− => (body -> Placement)
89+ -- | How to get body placement
81− -> (body -> R ())
90+ (body -> Placement) ->
82− -> MatchGroupStyle
91+ -- | How to print body
83− -> MatchGroup GhcPs (Located body)
92+ (body -> R ()) ->
84− -> R ()
93+ -- | Style of this group of equations
85−p_matchGroup' placer pretty style MG {..} =
94+ MatchGroupStyle ->
86− locatedVia Nothing mg_alts $
95+ -- | Match group
87− newlineSep (located' (\m@Match {..} ->
96+ MatchGroup GhcPs (Located body) ->
88− p_match' placer pretty style (isInfixMatch m) m_pats m_grhss))
97+ R ()
89−p_matchGroup' _ _ _ (XMatchGroup NoExt) = notImplemented "XMatchGroup"
98+p_matchGroup' placer render style MG {..} = do
90−
99+ let ob = case style of
91−p_match
100+ Case -> id
92− :: MatchGroupStyle
101+ LambdaCase -> id
93− -> Bool -- ^ Is this an infix match?
102+ _ -> dontUseBraces
94− -> [LPat GhcPs]
103+ -- Since we are forcing braces on 'sepSemi' based on 'ob', we have to
95− -> GRHSs GhcPs (LHsExpr GhcPs)
104+ -- restore the brace state inside the sepsemi.
96− -> R ()
105+ ub <- bool dontUseBraces useBraces <$> canUseBraces
106+ ob $ sepSemi (located' (ub . p_Match)) (unLoc mg_alts)
107+ where
108+ p_Match m@Match {..} =
109+ p_match'
110+ placer
111+ render
112+ (adjustMatchGroupStyle m style)
113+ (isInfixMatch m)
114+ (matchStrictness m)
115+ m_pats
116+ m_grhss
117+ p_Match (XMatch x) = noExtCon x
118+p_matchGroup' _ _ _ (XMatchGroup x) = noExtCon x
119+
120+-- | Function id obtained through pattern matching on 'FunBind' should not
121+-- be used to print the actual equations because the different ‘RdrNames’
122+-- used in the equations may have different “decorations” (such as backticks
123+-- and paretheses) associated with them. It is necessary to use per-equation
124+-- names obtained from 'm_ctxt' of 'Match'. This function replaces function
125+-- name inside of 'Function' accordingly.
126+adjustMatchGroupStyle ::
127+ Match GhcPs body ->
128+ MatchGroupStyle ->
129+ MatchGroupStyle
130+adjustMatchGroupStyle m = \case
131+ Function _ -> (Function . mc_fun . m_ctxt) m
132+ style -> style
133+
134+matchStrictness :: Match id body -> SrcStrictness
135+matchStrictness match =
136+ case m_ctxt match of
137+ FunRhs {mc_strictness = s} -> s
138+ _ -> NoSrcStrict
139+
140+p_match ::
141+ -- | Style of the group
142+ MatchGroupStyle ->
143+ -- | Is this an infix match?
144+ Bool ->
145+ -- | Strictness prefix (FunBind)
146+ SrcStrictness ->
147+ -- | Argument patterns
148+ [LPat GhcPs] ->
149+ -- | Equations
150+ GRHSs GhcPs (LHsExpr GhcPs) ->
151+ R ()
97p_match = p_match' exprPlacement p_hsExpr
152p_match = p_match' exprPlacement p_hsExpr
98
153
99−p_match'
154+p_match' ::
100− :: Data body
155+ Data body =>
101− => (body -> Placement)
156+ -- | How to get body placement
102− -> (body -> R ())
157+ (body -> Placement) ->
103− -> MatchGroupStyle
158+ -- | How to print body
104− -> Bool -- ^ Is this an infix match?
159+ (body -> R ()) ->
105− -> [LPat GhcPs]
160+ -- | Style of this group of equations
106− -> GRHSs GhcPs (Located body)
161+ MatchGroupStyle ->
107− -> R ()
162+ -- | Is this an infix match?
108−p_match' placer pretty style isInfix m_pats m_grhss = do
163+ Bool ->
109− -- NOTE Normally, since patterns may be placed in a multi-line layout, it
164+ -- | Strictness prefix (FunBind)
110− -- is necessary to bump indentation for the pattern group so it's more
165+ SrcStrictness ->
166+ -- | Argument patterns
167+ [LPat GhcPs] ->
168+ -- | Equations
169+ GRHSs GhcPs (Located body) ->
170+ R ()
171+p_match' placer render style isInfix strictness m_pats GRHSs {..} = do
172+ -- Normally, since patterns may be placed in a multi-line layout, it is
173+ -- necessary to bump indentation for the pattern group so it's more
111 -- indented than function name. This in turn means that indentation for
174 -- indented than function name. This in turn means that indentation for
112 -- the body should also be bumped. Normally this would mean that bodies
175 -- the body should also be bumped. Normally this would mean that bodies
113 -- would start with two indentation steps applied, which is ugly, so we
176 -- would start with two indentation steps applied, which is ugly, so we
114 -- need to be a bit more clever here and bump indentation level only when
177 -- need to be a bit more clever here and bump indentation level only when
115 -- pattern group is multiline.
178 -- pattern group is multiline.
116− inci' <- case NE.nonEmpty m_pats of
179+ case strictness of
117− Nothing -> id <$ case style of
180+ NoSrcStrict -> return ()
118− Function name -> p_rdrName name
181+ SrcStrict -> txt "!"
119− _ -> return ()
182+ SrcLazy -> txt "~"
183+ indentBody <- case NE.nonEmpty m_pats of
184+ Nothing ->
185+ False <$ case style of
186+ Function name -> p_rdrName name
187+ _ -> return ()
120 Just ne_pats -> do
188 Just ne_pats -> do
121− let combinedSpans = combineSrcSpans' $
189+ let combinedSpans = case style of
122− getLoc <$> ne_pats
190+ Function name -> combineSrcSpans (getLoc name) patSpans
123− inci' = if isOneLineSpan combinedSpans
191+ _ -> patSpans
124− then id
192+ patSpans = combineSrcSpans' (getLoc <$> ne_pats)
125− else inci
193+ indentBody = not (isOneLineSpan combinedSpans)
126− switchLayout combinedSpans $ do
194+ switchLayout [combinedSpans] $ do
127− let stdCase = velt' (located' p_pat <$> m_pats)
195+ let stdCase = sep breakpoint (located' p_pat) m_pats
128 case style of
196 case style of
129 Function name ->
197 Function name ->
130 p_infixDefHelper
198 p_infixDefHelper
131 isInfix
199 isInfix
132− inci'
200+ indentBody
133 (p_rdrName name)
201 (p_rdrName name)
134 (located' p_pat <$> m_pats)
202 (located' p_pat <$> m_pats)
135 PatternBind -> stdCase
203 PatternBind -> stdCase
136 Case -> stdCase
204 Case -> stdCase
137 Lambda -> do
205 Lambda -> do
138− case unLoc (NE.head ne_pats) of
206+ let needsSpace = case unLoc (NE.head ne_pats) of
139− LazyPat _ _ -> txt "\\ "
207+ LazyPat _ _ -> True
140− _ -> txt "\\"
208+ BangPat _ _ -> True
141− stdCase
209+ SplicePat _ _ -> True
210+ _ -> False
211+ txt "\\"
212+ when needsSpace space
213+ sitcc stdCase
142 LambdaCase -> stdCase
214 LambdaCase -> stdCase
143− return inci'
215+ return indentBody
144−
216+ let -- Calculate position of end of patterns. This is useful when we decide
145− let
217+ -- about putting certain constructions in hanging positions.
146− -- Calculate position of end of patterns. This is useful when we decide
218+ endOfPats = case NE.nonEmpty m_pats of
147− -- about putting certain constructions in hanging positions.
219+ Nothing -> case style of
148− endOfPats = case NE.nonEmpty m_pats of
220+ Function name -> Just (getLoc name)
149− Nothing -> case style of
221+ _ -> Nothing
150− Function name -> (Just . srcSpanEnd . getLoc) name
222+ Just pats -> (Just . getLoc . NE.last) pats
151− _ -> Nothing
223+ isCase = \case
152− Just pats -> (Just . srcSpanEnd . getLoc . NE.last) pats
224+ Case -> True
153− isCase = \case
225+ LambdaCase -> True
154− Case -> True
226+ _ -> False
155− LambdaCase -> True
227+ hasGuards = withGuards grhssGRHSs
156− _ -> False
228+ grhssSpan =
157− inci' $ do
229+ combineSrcSpans' $
158− let GRHSs {..} = m_grhss
159− hasGuards = withGuards grhssGRHSs
160− unless (length grhssGRHSs > 1) $ do
161− case style of
162− Function _ | hasGuards -> return ()
163− Function _ -> txt " ="
164− PatternBind -> txt " ="
165− s | isCase s && hasGuards -> return ()
166− _ -> txt " ->"
167− let grhssSpan = combineSrcSpans' $
168 getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
230 getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
169− patGrhssSpan = maybe grhssSpan
231+ patGrhssSpan =
170− (combineSrcSpans grhssSpan . srcLocSpan) endOfPats
232+ maybe
171− placement =
233+ grhssSpan
172− case endOfPats of
234+ (combineSrcSpans grhssSpan . srcLocSpan . srcSpanEnd)
173− Nothing -> blockPlacement placer grhssGRHSs
235+ endOfPats
174− Just spn ->
236+ placement =
175− if isOneLineSpan
237+ case endOfPats of
176− (mkSrcSpan spn (srcSpanStart grhssSpan))
238+ Nothing -> blockPlacement placer grhssGRHSs
177− then blockPlacement placer grhssGRHSs
239+ Just spn ->
178− else Normal
240+ if onTheSameLine spn grhssSpan
179− inciLocalBinds = case placement of
241+ then blockPlacement placer grhssGRHSs
180− Normal -> id
242+ else Normal
181− Hanging -> inci
243+ p_body = do
182− p_body = do
244+ let groupStyle =
183− let groupStyle =
245+ if isCase style && hasGuards
184− if isCase style && hasGuards
185 then RightArrow
246 then RightArrow
186 else EqualSign
247 else EqualSign
187− newlineSep (located' (p_grhs' pretty groupStyle)) grhssGRHSs
248+ sep newline (located' (p_grhs' placer render groupStyle)) grhssGRHSs
188− unless
249+ p_where = do
189− (GHC.isEmptyLocalBindsPR (unLoc grhssLocalBinds))
250+ let whereIsEmpty = GHC.isEmptyLocalBindsPR (unLoc grhssLocalBinds)
190− (inciLocalBinds $ do
251+ unless (GHC.eqEmptyLocalBinds (unLoc grhssLocalBinds)) $ do
191− newline
252+ breakpoint
192− line (txt "where")
253+ txt "where"
193− inci (located grhssLocalBinds p_hsLocalBinds)
254+ unless whereIsEmpty breakpoint
194− )
255+ inci $ located grhssLocalBinds p_hsLocalBinds
195− case style of
256+ inciIf indentBody $ do
196− Lambda -> placeHanging placement $
257+ unless (length grhssGRHSs > 1) $
197− switchLayout patGrhssSpan p_body
258+ case style of
198− _ -> switchLayout patGrhssSpan $
259+ Function _ | hasGuards -> return ()
199− placeHanging placement p_body
260+ Function _ -> space >> inci equals
261+ PatternBind -> space >> inci equals
262+ s | isCase s && hasGuards -> return ()
263+ _ -> space >> txt "->"
264+ switchLayout [patGrhssSpan] $
265+ placeHanging placement p_body
266+ inci p_where
267+p_match' _ _ _ _ _ _ (XGRHSs x) = noExtCon x
200
268
201p_grhs :: GroupStyle -> GRHS GhcPs (LHsExpr GhcPs) -> R ()
269p_grhs :: GroupStyle -> GRHS GhcPs (LHsExpr GhcPs) -> R ()
202−p_grhs = p_grhs' p_hsExpr
270+p_grhs = p_grhs' exprPlacement p_hsExpr
203−
271+
204−p_grhs'
272+p_grhs' ::
205− :: Data body
273+ Data body =>
206− => (body -> R ())
274+ -- | How to get body placement
207− -> GroupStyle
275+ (body -> Placement) ->
208− -> GRHS GhcPs (Located body)
276+ -- | How to print body
209− -> R ()
277+ (body -> R ()) ->
210−p_grhs' pretty style (GRHS NoExt guards body) =
278+ GroupStyle ->
279+ GRHS GhcPs (Located body) ->
280+ R ()
281+p_grhs' placer render style (GRHS NoExtField guards body) =
211 case guards of
282 case guards of
212 [] -> p_body
283 [] -> p_body
213 xs -> do
284 xs -> do
214− txt "| "
285+ txt "|"
215− velt $ withSep comma (located' p_stmt) xs
216 space
286 space
217− txt $ case style of
287+ sitcc (sep commaDel (sitcc . located' p_stmt) xs)
218− EqualSign -> "="
288+ space
219− RightArrow -> "->"
289+ inci $ case style of
220− breakpoint
290+ EqualSign -> equals
221− inci p_body
291+ RightArrow -> txt "->"
292+ placeHanging placement p_body
222 where
293 where
223− p_body = located body pretty
294+ placement =
224−p_grhs' _ _ (XGRHS NoExt) = notImplemented "XGRHS"
295+ case endOfGuards of
296+ Nothing -> placer (unLoc body)
297+ Just spn ->
298+ if onTheSameLine spn (getLoc body)
299+ then placer (unLoc body)
300+ else Normal
301+ endOfGuards =
302+ case NE.nonEmpty guards of
303+ Nothing -> Nothing
304+ Just gs -> (Just . getLoc . NE.last) gs
305+ p_body = located body render
306+p_grhs' _ _ _ (XGRHS x) = noExtCon x
225
307
226p_hsCmd :: HsCmd GhcPs -> R ()
308p_hsCmd :: HsCmd GhcPs -> R ()
227p_hsCmd = \case
309p_hsCmd = \case
228− HsCmdArrApp NoExt body input arrType _ -> do
310+ HsCmdArrApp NoExtField body input arrType _ -> do
229 located body p_hsExpr
311 located body p_hsExpr
230− txt $ case arrType of
312+ breakpoint
231− HsFirstOrderApp -> " -<"
313+ inci $ do
232− HsHigherOrderApp -> " -<<"
314+ case arrType of
233− placeHanging (exprPlacement (unLoc input)) $
315+ HsFirstOrderApp -> txt "-<"
234− located input p_hsExpr
316+ HsHigherOrderApp -> txt "-<<"
235− HsCmdArrForm NoExt form Prefix _ cmds -> banana $ sitcc $ do
317+ placeHanging (exprPlacement (unLoc input)) $
318+ located input p_hsExpr
319+ HsCmdArrForm NoExtField form Prefix _ cmds -> banana $ do
236 located form p_hsExpr
320 located form p_hsExpr
237− unless (null cmds) $ do
321+ unless (null cmds) $ do
238 breakpoint
322 breakpoint
239 inci (sequence_ (intersperse breakpoint (located' p_hsCmdTop <$> cmds)))
323 inci (sequence_ (intersperse breakpoint (located' p_hsCmdTop <$> cmds)))
240− HsCmdArrForm NoExt form Infix _ [left, right] -> do
324+ HsCmdArrForm NoExtField form Infix _ [left, right] -> do
241 located left p_hsCmdTop
325 located left p_hsCmdTop
242 space
326 space
243 located form p_hsExpr
327 located form p_hsExpr
244 placeHanging (cmdTopPlacement (unLoc right)) $
328 placeHanging (cmdTopPlacement (unLoc right)) $
245 located right p_hsCmdTop
329 located right p_hsCmdTop
246− HsCmdArrForm NoExt _ Infix _ _ -> notImplemented "HsCmdArrForm"
330+ HsCmdArrForm NoExtField _ Infix _ _ -> notImplemented "HsCmdArrForm"
247 HsCmdApp {} ->
331 HsCmdApp {} ->
248 -- 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
249 -- 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.
250 notImplemented "HsCmdApp"
334 notImplemented "HsCmdApp"
251− HsCmdLam NoExt mgroup -> p_matchGroup' cmdPlacement p_hsCmd Lambda mgroup
335+ HsCmdLam NoExtField mgroup -> p_matchGroup' cmdPlacement p_hsCmd Lambda mgroup
252− HsCmdPar NoExt c -> parens (located c p_hsCmd)
336+ HsCmdPar NoExtField c -> parens N (located c p_hsCmd)
253− HsCmdCase NoExt e mgroup -> do
337+ HsCmdCase NoExtField e mgroup ->
254− txt "case "
338+ p_case cmdPlacement p_hsCmd e mgroup
255− located e p_hsExpr
339+ HsCmdIf NoExtField _ if' then' else' ->
256− txt " of"
340+ p_if cmdPlacement p_hsCmd if' then' else'
257− breakpoint
341+ HsCmdLet NoExtField localBinds c ->
258− inci (p_matchGroup' cmdPlacement p_hsCmd Case mgroup)
342+ p_let p_hsCmd localBinds c
259− HsCmdIf NoExt _ if' then' else' -> do
343+ HsCmdDo NoExtField es -> do
260− txt "if "
261− located if' p_hsExpr
262− breakpoint
263− txt "then"
264− located then' $ \x -> do
265− breakpoint
266− inci (p_hsCmd x)
267− breakpoint
268− txt "else"
269− located else' $ \x -> do
270− breakpoint
271− inci (p_hsCmd x)
272− HsCmdLet NoExt localBinds c -> do
273− txt "let "
274− sitcc (located localBinds p_hsLocalBinds)
275− breakpoint
276− txt "in "
277− sitcc (located c p_hsCmd)
278− HsCmdDo NoExt es -> do
279 txt "do"
344 txt "do"
280 newline
345 newline
281− inci (located es (newlineSep (located' (sitcc . p_stmt' p_hsCmd))))
346+ inci . located es $
347+ sitcc . sep newline (sitcc . withSpacing (p_stmt' cmdPlacement p_hsCmd))
282 HsCmdWrap {} -> notImplemented "HsCmdWrap"
348 HsCmdWrap {} -> notImplemented "HsCmdWrap"
283− XCmd {} -> notImplemented "XCmd"
349+ XCmd x -> noExtCon x
284
350
285p_hsCmdTop :: HsCmdTop GhcPs -> R ()
351p_hsCmdTop :: HsCmdTop GhcPs -> R ()
286p_hsCmdTop = \case
352p_hsCmdTop = \case
287− HsCmdTop NoExt cmd -> located cmd p_hsCmd
353+ HsCmdTop NoExtField cmd -> located cmd p_hsCmd
288− XCmdTop {} -> notImplemented "XHsCmdTop"
354+ XCmdTop x -> noExtCon x
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)
289
384
290p_stmt :: Stmt GhcPs (LHsExpr GhcPs) -> R ()
385p_stmt :: Stmt GhcPs (LHsExpr GhcPs) -> R ()
291−p_stmt = p_stmt' p_hsExpr
386+p_stmt = p_stmt' exprPlacement p_hsExpr
292−
387+
293−p_stmt'
388+p_stmt' ::
294− :: Data body
389+ Data body =>
295− => (body -> R ())
390+ -- | Placer
296− -> Stmt GhcPs (Located body)
391+ (body -> Placement) ->
297− -> R ()
392+ -- | Render
298−p_stmt' pretty = \case
393+ (body -> R ()) ->
299− LastStmt NoExt body _ _ -> located body pretty
394+ -- | Statement to render
300− BindStmt NoExt l f _ _ -> do
395+ Stmt GhcPs (Located body) ->
301− located l p_pat
396+ R ()
397+p_stmt' placer render = \case
398+ LastStmt NoExtField body _ _ -> located body render
399+ BindStmt NoExtField p f _ _ -> do
400+ located p p_pat
302 space
401 space
303 txt "<-"
402 txt "<-"
304− breakpoint
403+ let loc = getLoc p
305− inci (located f pretty)
404+ placement =
306− ApplicativeStmt {} -> notImplemented "ApplicativeStmt"
405+ case f of
307− BodyStmt NoExt body _ _ -> located body pretty
406+ L l' x ->
308− LetStmt NoExt binds -> do
407+ if isOneLineSpan
309− txt "let "
408+ (mkSrcSpan (srcSpanEnd loc) (srcSpanStart l'))
409+ then placer x
410+ else Normal
411+ switchLayout [loc, getLoc f] $
412+ placeHanging placement (located f render)
413+ ApplicativeStmt {} -> notImplemented "ApplicativeStmt" -- generated by renamer
414+ BodyStmt NoExtField body _ _ -> located body render
415+ LetStmt NoExtField binds -> do
416+ txt "let"
417+ space
310 sitcc $ located binds p_hsLocalBinds
418 sitcc $ located binds p_hsLocalBinds
311− ParStmt NoExt stmts _ _ ->
419+ ParStmt {} ->
312− sequence_ $ intersperse breakpoint $
420+ -- 'ParStmt' should always be eliminated in 'gatherStmt' already, such
313− withSep (txt "| ") p_parStmtBlock stmts
421+ -- that it never occurs in 'p_stmt''. Consequently, handling it here
314− TransStmt {} -> notImplemented "TransStmt"
422+ -- would be redundant.
423+ notImplemented "ParStmt"
424+ TransStmt {..} ->
425+ -- 'TransStmt' only needs to account for render printing itself, since
426+ -- pretty printing of relevant statements (e.g., in 'trS_stmts') is
427+ -- handled through 'gatherStmt'.
428+ case (trS_form, trS_by) of
429+ (ThenForm, Nothing) -> do
430+ txt "then"
431+ breakpoint
432+ inci $ located trS_using p_hsExpr
433+ (ThenForm, Just e) -> do
434+ txt "then"
435+ breakpoint
436+ inci $ located trS_using p_hsExpr
437+ breakpoint
438+ txt "by"
439+ breakpoint
440+ inci $ located e p_hsExpr
441+ (GroupForm, Nothing) -> do
442+ txt "then group using"
443+ breakpoint
444+ inci $ located trS_using p_hsExpr
445+ (GroupForm, Just e) -> do
446+ txt "then group by"
447+ breakpoint
448+ inci $ located e p_hsExpr
449+ breakpoint
450+ txt "using"
451+ breakpoint
452+ inci $ located trS_using p_hsExpr
315 RecStmt {..} -> do
453 RecStmt {..} -> do
316− txt "rec "
454+ txt "rec"
317− sitcc $ newlineSep (located' (p_stmt' pretty)) recS_stmts
455+ space
318− XStmtLR {} -> notImplemented "XStmtLR"
456+ sitcc $ sepSemi (withSpacing (p_stmt' placer render)) recS_stmts
457+ XStmtLR c -> noExtCon c
458+
459+gatherStmt :: ExprLStmt GhcPs -> [[ExprLStmt GhcPs]]
460+gatherStmt (L _ (ParStmt NoExtField block _ _)) =
461+ foldr ((<>) . gatherStmtBlock) [] block
462+gatherStmt (L s stmt@TransStmt {..}) =
463+ foldr liftAppend [] ((gatherStmt <$> trS_stmts) <> pure [[L s stmt]])
464+gatherStmt stmt = [[stmt]]
319
465
320−p_parStmtBlock :: ParStmtBlock GhcPs GhcPs -> R ()
466+gatherStmtBlock :: ParStmtBlock GhcPs GhcPs -> [[ExprLStmt GhcPs]]
321−p_parStmtBlock = \case
467+gatherStmtBlock (ParStmtBlock _ stmts _ _) =
322− ParStmtBlock NoExt stmts _ _ ->
468+ foldr (liftAppend . gatherStmt) [] stmts
323− velt $ withSep comma (located' (sitcc . p_stmt)) stmts
469+gatherStmtBlock (XParStmtBlock x) = noExtCon x
324− XParStmtBlock {} -> notImplemented "XParStmtBlock"
325
470
326p_hsLocalBinds :: HsLocalBindsLR GhcPs GhcPs -> R ()
471p_hsLocalBinds :: HsLocalBindsLR GhcPs GhcPs -> R ()
327p_hsLocalBinds = \case
472p_hsLocalBinds = \case
328− HsValBinds NoExt (ValBinds NoExt bag lsigs) -> do
473+ HsValBinds NoExtField (ValBinds NoExtField bag lsigs) -> do
329− let ssStart = either
474+ -- When in a single-line layout, there is a chance that the inner
330− (srcSpanStart . getLoc)
475+ -- elements will also contain semicolons and they will confuse the
331− (srcSpanStart . getLoc)
476+ -- parser. so we request braces around every element except the last.
332− items =
477+ br <- layoutToBraces <$> getLayout
333− (Left <$> bagToList bag) ++ (Right <$> lsigs)
478+ let items =
334− p_item (Left x) = located x p_valDecl'
479+ let injectLeft (L l x) = L l (Left x)
335− p_item (Right x) = located x p_sigDecl'
480+ injectRight (L l x) = L l (Right x)
336− newlineSep p_item (sortOn ssStart items)
481+ in (injectLeft <$> bagToList bag) ++ (injectRight <$> lsigs)
337− HsValBinds NoExt _ -> notImplemented "HsValBinds"
482+ positionToBracing = \case
338− HsIPBinds NoExt _ -> notImplemented "HsIPBinds"
483+ SinglePos -> id
339− EmptyLocalBinds NoExt -> return ()
484+ FirstPos -> br
340− XHsLocalBindsLR _ -> notImplemented "XHsLocalBindsLR"
485+ MiddlePos -> br
341−
486+ LastPos -> id
342−p_hsRecField
487+ p_item' (p, item) =
343− :: (Data id, Outputable id)
488+ positionToBracing p $
344− => HsRecField' id (LHsExpr GhcPs)
489+ withSpacing (either p_valDecl p_sigDecl) item
345− -> R ()
490+ binds = sortOn (srcSpanStart . getLoc) items
346−p_hsRecField = \HsRecField {..} -> do
491+ sitcc $ sepSemi p_item' (attachRelativePos binds)
347− located hsRecFieldLbl atom
492+ HsValBinds NoExtField _ -> notImplemented "HsValBinds"
348− unless hsRecPun $ do
493+ HsIPBinds NoExtField (IPBinds NoExtField xs) ->
349− txt " = "
494+ -- Second argument of IPBind is always Left before type-checking.
350− located hsRecFieldArg p_hsExpr
495+ let p_ipBind (IPBind NoExtField (Left name) expr) = do
351−
496+ atom name
352−p_hsTupArg :: HsTupArg GhcPs -> R ()
497+ space
353−p_hsTupArg = \case
498+ equals
354− Present NoExt x -> located x p_hsExpr
499+ breakpoint
355− Missing NoExt -> pure ()
500+ useBraces $ inci $ located expr p_hsExpr
356− XTupArg {} -> notImplemented "XTupArg"
501+ p_ipBind (IPBind NoExtField (Right _) _) =
502+ -- Should only occur after the type checker
503+ notImplemented "IPBind _ (Right _) _"
504+ p_ipBind (XIPBind x) = noExtCon x
505+ in sepSemi (located' p_ipBind) xs
506+ HsIPBinds NoExtField _ -> notImplemented "HsIpBinds"
507+ EmptyLocalBinds NoExtField -> return ()
508+ XHsLocalBindsLR x -> noExtCon x
509+
510+p_hsRecField ::
511+ HsRecField' RdrName (LHsExpr GhcPs) ->
512+ R ()
513+p_hsRecField HsRecField {..} = do
514+ p_rdrName hsRecFieldLbl
515+ unless hsRecPun $ do
516+ space
517+ equals
518+ let placement =
519+ if onTheSameLine (getLoc hsRecFieldLbl) (getLoc hsRecFieldArg)
520+ then exprPlacement (unLoc hsRecFieldArg)
521+ else Normal
522+ placeHanging placement (located hsRecFieldArg p_hsExpr)
357
523
358p_hsExpr :: HsExpr GhcPs -> R ()
524p_hsExpr :: HsExpr GhcPs -> R ()
359−p_hsExpr = \case
525+p_hsExpr = p_hsExpr' N
360− HsVar NoExt name -> p_rdrName name
526+
361− HsUnboundVar NoExt _ -> notImplemented "HsUnboundVar"
527+p_hsExpr' :: BracketStyle -> HsExpr GhcPs -> R ()
362− HsConLikeOut NoExt _ -> notImplemented "HsConLikeOut"
528+p_hsExpr' s = \case
363− HsRecFld NoExt x ->
529+ HsVar NoExtField name -> p_rdrName name
530+ HsUnboundVar NoExtField v -> atom (unboundVarOcc v)
531+ HsConLikeOut NoExtField _ -> notImplemented "HsConLikeOut"
532+ HsRecFld NoExtField x ->
364 case x of
533 case x of
365− Unambiguous NoExt name -> p_rdrName name
534+ Unambiguous NoExtField name -> p_rdrName name
366− Ambiguous NoExt name -> p_rdrName name
535+ Ambiguous NoExtField name -> p_rdrName name
367− XAmbiguousFieldOcc NoExt -> notImplemented "XAmbiguousFieldOcc"
536+ XAmbiguousFieldOcc xx -> noExtCon xx
368− HsOverLabel NoExt _ v -> do
537+ HsOverLabel NoExtField _ v -> do
369 txt "#"
538 txt "#"
370 atom v
539 atom v
371− HsIPVar NoExt (HsIPName name) -> do
540+ HsIPVar NoExtField (HsIPName name) -> do
372 txt "?"
541 txt "?"
373 atom name
542 atom name
374− HsOverLit NoExt v -> atom (ol_val v)
543+ HsOverLit NoExtField v -> atom (ol_val v)
375− HsLit NoExt lit -> atom lit
544+ HsLit NoExtField lit ->
376− HsLam NoExt mgroup ->
545+ case lit of
546+ HsString (SourceText stxt) _ -> p_stringLit stxt
547+ HsStringPrim (SourceText stxt) _ -> p_stringLit stxt
548+ r -> atom r
549+ HsLam NoExtField mgroup ->
377 p_matchGroup Lambda mgroup
550 p_matchGroup Lambda mgroup
378− HsLamCase NoExt mgroup -> do
551+ HsLamCase NoExtField mgroup -> do
379 txt "\\case"
552 txt "\\case"
380− newline
381− inci (p_matchGroup LambdaCase mgroup)
382− HsApp NoExt f x -> do
383− located f p_hsExpr
384 breakpoint
553 breakpoint
385− inci (located x p_hsExpr)
554+ inci (p_matchGroup LambdaCase mgroup)
386− HsAppType a e -> do
555+ HsApp NoExtField f x -> do
556+ let -- In order to format function applications with multiple parameters
557+ -- nicer, traverse the AST to gather the function and all the
558+ -- parameters together.
559+ gatherArgs f' knownArgs =
560+ case f' of
561+ L _ (HsApp _ l r) -> gatherArgs l (r <| knownArgs)
562+ _ -> (f', knownArgs)
563+ (func, args) = gatherArgs f (x :| [])
564+ -- We need to handle the last argument specially if it is a
565+ -- hanging construct, so separate it from the rest.
566+ (initp, lastp) = (NE.init args, NE.last args)
567+ initSpan =
568+ combineSrcSpans' $
569+ getLoc f :| [(srcLocSpan . srcSpanStart . getLoc) lastp]
570+ -- Hang the last argument only if the initial arguments span one
571+ -- line.
572+ placement =
573+ if isOneLineSpan initSpan
574+ then exprPlacement (unLoc lastp)
575+ else Normal
576+ -- If the last argument is not hanging, just separate every argument as
577+ -- usual. If it is hanging, print the initial arguments and hang the
578+ -- last one. Also, use braces around the every argument except the last
579+ -- one.
580+ case placement of
581+ 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
596+ MultiLine -> id
597+ ub $ do
598+ located func (p_hsExpr' s)
599+ breakpoint
600+ inciIf doIndent $ sep breakpoint (located' p_hsExpr) initp
601+ inciIf doIndent $ do
602+ unless (null initp) breakpoint
603+ located lastp p_hsExpr
604+ Hanging -> do
605+ useBraces . switchLayout [initSpan] $ do
606+ located func (p_hsExpr' s)
607+ breakpoint
608+ sep breakpoint (located' p_hsExpr) initp
609+ placeHanging placement $
610+ located lastp p_hsExpr
611+ HsAppType NoExtField e a -> do
387 located e p_hsExpr
612 located e p_hsExpr
388 breakpoint
613 breakpoint
389 inci $ do
614 inci $ do
390 txt "@"
615 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 ()
391 located (hswc_body a) p_hsType
621 located (hswc_body a) p_hsType
392− OpApp NoExt x op y -> do
622+ OpApp NoExtField x op y -> do
393− located x p_hsExpr
623+ let opTree = OpBranch (exprOpTree x) op (exprOpTree y)
394− space
624+ p_exprOpTree s (reassociateOpTree getOpName opTree)
395− located op p_hsExpr
625+ NegApp NoExtField e _ -> do
396− placeHanging (exprPlacement (unLoc y)) $
397− located y p_hsExpr
398− NegApp NoExt e _ -> do
399 txt "-"
626 txt "-"
627+ space
400 located e p_hsExpr
628 located e p_hsExpr
401− HsPar NoExt e -> parens (located e p_hsExpr)
629+ HsPar NoExtField e ->
402− SectionL NoExt x op -> do
630+ parens s (located e (dontUseBraces . p_hsExpr))
631+ SectionL NoExtField x op -> do
403 located x p_hsExpr
632 located x p_hsExpr
404 breakpoint
633 breakpoint
405 inci (located op p_hsExpr)
634 inci (located op p_hsExpr)
406− SectionR NoExt op x -> do
635+ SectionR NoExtField op x -> do
407 located op p_hsExpr
636 located op p_hsExpr
408− breakpoint
637+ useRecordDot' <- useRecordDot
638+ let isRecordDot' = isRecordDot (unLoc op) (getLoc x)
639+ unless (useRecordDot' && isRecordDot') breakpoint
409 inci (located x p_hsExpr)
640 inci (located x p_hsExpr)
410− ExplicitTuple NoExt args boxity -> do
641+ ExplicitTuple NoExtField args boxity ->
411 let isSection = any (isMissing . unLoc) args
642 let isSection = any (isMissing . unLoc) args
412 isMissing = \case
643 isMissing = \case
413− Missing NoExt -> True
644+ Missing NoExtField -> True
414 _ -> False
645 _ -> False
415− let parens' =
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' =
416 case boxity of
652 case boxity of
417 Boxed -> parens
653 Boxed -> parens
418 Unboxed -> parensHash
654 Unboxed -> parensHash
419− parens' $ if isSection
655+ in if isSection
420− then sequence_ (withSep (txt ",") (located' p_hsTupArg) args)
656+ then
421− else velt (withSep comma (located' p_hsTupArg) args)
657+ switchLayout [] . parens' s $
422− ExplicitSum NoExt tag arity e -> do
658+ sep comma p_larg args
423− let before = tag - 1
659+ else
424− after = arity - before - 1
660+ switchLayout (getLoc <$> args) . parens' s $
425− args = replicate before Nothing <> [Just e] <> replicate after Nothing
661+ sep commaDel p_larg args
426− f (x,i) = do
662+ ExplicitSum NoExtField tag arity e ->
427− let isFirst = i == 0
663+ p_unboxedSum N tag arity (located e p_hsExpr)
428− isLast = i == arity - 1
664+ HsCase NoExtField e mgroup ->
429− case x of
665+ p_case exprPlacement p_hsExpr e mgroup
430− Nothing ->
666+ HsIf NoExtField _ if' then' else' ->
431− unless (isFirst || isLast) space
667+ p_if exprPlacement p_hsExpr if' then' else'
432− Just l -> do
668+ HsMultiIf NoExtField guards -> do
433− unless isFirst space
669+ txt "if"
434− located l p_hsExpr
435− unless isLast space
436− parensHash $ sequence_ (withSep (txt "|") f (zip args [0..]))
437− HsCase NoExt e mgroup -> do
438− txt "case "
439− located e p_hsExpr
440− txt " of"
441 breakpoint
670 breakpoint
442− inci (p_matchGroup Case mgroup)
671+ inci . inci $ sep newline (located' (p_grhs RightArrow)) guards
443− HsIf NoExt _ if' then' else' -> do
672+ HsLet NoExtField localBinds e ->
444− txt "if "
673+ p_let p_hsExpr localBinds e
445− located if' p_hsExpr
674+ HsDo NoExtField ctx es -> do
446− breakpoint
447− txt "then"
448− located then' $ \x -> do
449− breakpoint
450− inci (p_hsExpr x)
451− breakpoint
452− txt "else"
453− located else' $ \x -> do
454− breakpoint
455− inci (p_hsExpr x)
456− HsMultiIf NoExt guards -> do
457− txt "if "
458− sitcc $ newlineSep (located' (p_grhs RightArrow)) guards
459− HsLet NoExt localBinds e -> do
460− txt "let "
461− sitcc (located localBinds p_hsLocalBinds)
462− vlayout space (newline >> space)
463− txt "in "
464− sitcc (located e p_hsExpr)
465− HsDo NoExt ctx es -> do
466 let doBody header = do
675 let doBody header = do
467 txt header
676 txt header
468− newline
677+ breakpoint
469− inci $ located es (newlineSep (located' (sitcc . p_stmt)))
678+ ub <- layoutToBraces <$> getLayout
470− compBody = brackets $ located es $ \xs -> do
679+ inci $
471− let stmts = init xs
680+ sepSemi
681+ (ub . withSpacing (p_stmt' exprPlacement (p_hsExpr' S)))
682+ (unLoc es)
683+ compBody = brackets N . located es $ \xs -> do
684+ let p_parBody =
685+ sep
686+ (breakpoint >> txt "|" >> space)
687+ p_seqBody
688+ p_seqBody =
689+ sitcc
690+ . sep
691+ commaDel
692+ (located' (sitcc . p_stmt))
693+ stmts = init xs
472 yield = last xs
694 yield = last xs
695+ lists = foldr (liftAppend . gatherStmt) [] stmts
473 located yield p_stmt
696 located yield p_stmt
474 breakpoint
697 breakpoint
475− txt "| "
698+ txt "|"
476− case stmts of
699+ space
477− [stmt] | ParStmt {} <- unLoc stmt -> located stmt p_stmt
700+ p_parBody lists
478− _ -> velt $ withSep comma (located' (sitcc . p_stmt)) stmts
479 case ctx of
701 case ctx of
480 DoExpr -> doBody "do"
702 DoExpr -> doBody "do"
481 MDoExpr -> doBody "mdo"
703 MDoExpr -> doBody "mdo"
482 ListComp -> compBody
704 ListComp -> compBody
483 MonadComp -> notImplemented "MonadComp"
705 MonadComp -> notImplemented "MonadComp"
484− ArrowExpr -> notImplemented "ArrowExpr"
706+ ArrowExpr -> notImplemented "ArrowExpr"
485 GhciStmtCtxt -> notImplemented "GhciStmtCtxt"
707 GhciStmtCtxt -> notImplemented "GhciStmtCtxt"
486 PatGuard _ -> notImplemented "PatGuard"
708 PatGuard _ -> notImplemented "PatGuard"
487 ParStmtCtxt _ -> notImplemented "ParStmtCtxt"
709 ParStmtCtxt _ -> notImplemented "ParStmtCtxt"
488 TransStmtCtxt _ -> notImplemented "TransStmtCtxt"
710 TransStmtCtxt _ -> notImplemented "TransStmtCtxt"
489 ExplicitList _ _ xs ->
711 ExplicitList _ _ xs ->
490− brackets $ velt (withSep comma (located' p_hsExpr) xs)
712+ brackets s $
713+ sep commaDel (sitcc . located' p_hsExpr) xs
491 RecordCon {..} -> do
714 RecordCon {..} -> do
492 located rcon_con_name atom
715 located rcon_con_name atom
493 breakpoint
716 breakpoint
494 let HsRecFields {..} = rcon_flds
717 let HsRecFields {..} = rcon_flds
495− fields = located' p_hsRecField <$> rec_flds
718+ updName f =
719+ (f :: HsRecField GhcPs (LHsExpr GhcPs))
720+ { hsRecFieldLbl = case unLoc $ hsRecFieldLbl f of
721+ FieldOcc _ n -> n
722+ XFieldOcc x -> noExtCon x
723+ }
724+ fields = located' (p_hsRecField . updName) <$> rec_flds
496 dotdot =
725 dotdot =
497 case rec_dotdot of
726 case rec_dotdot of
498 Just {} -> [txt ".."]
727 Just {} -> [txt ".."]
499 Nothing -> []
728 Nothing -> []
500− inci $ braces $ velt (withSep comma id (fields <> dotdot))
729+ inci . braces N $
730+ sep commaDel sitcc (fields <> dotdot)
501 RecordUpd {..} -> do
731 RecordUpd {..} -> do
502 located rupd_expr p_hsExpr
732 located rupd_expr p_hsExpr
503− breakpoint
733+ useRecordDot' <- useRecordDot
504− inci $ braces $ velt (withSep comma (located' p_hsRecField) rupd_flds)
734+ let mrs sp = case getLoc sp of
505− ExprWithTySig affix x -> sitcc $ do
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
741+ let updName f =
742+ (f :: HsRecUpdField GhcPs)
743+ { hsRecFieldLbl = case unLoc $ hsRecFieldLbl f of
744+ Ambiguous _ n -> n
745+ Unambiguous _ n -> n
746+ XAmbiguousFieldOcc x -> noExtCon x
747+ }
748+ inci . braces N $
749+ sep
750+ commaDel
751+ (sitcc . located' (p_hsRecField . updName))
752+ rupd_flds
753+ ExprWithTySig NoExtField x HsWC {hswc_body = HsIB {..}} -> sitcc $ do
506 located x p_hsExpr
754 located x p_hsExpr
755+ space
756+ txt "::"
507 breakpoint
757 breakpoint
508− inci $ do
758+ inci $ located hsib_body p_hsType
509− txt ":: "
759+ ExprWithTySig NoExtField _ HsWC {hswc_body = XHsImplicitBndrs x} -> noExtCon x
510− let HsWC {..} = affix
760+ ExprWithTySig NoExtField _ (XHsWildCardBndrs x) -> noExtCon x
511− HsIB {..} = hswc_body
761+ ArithSeq NoExtField _ x ->
512− located hsib_body p_hsType
513− ArithSeq NoExt _ x -> do
514 case x of
762 case x of
515− From from -> brackets $ do
763+ From from -> brackets s $ do
516 located from p_hsExpr
764 located from p_hsExpr
517− breakpoint'
765+ breakpoint
518 txt ".."
766 txt ".."
519− FromThen from next -> brackets $ do
767+ FromThen from next -> brackets s $ do
520− velt (withSep comma (located' p_hsExpr) [from, next])
768+ sep commaDel (located' p_hsExpr) [from, next]
521− breakpoint'
769+ breakpoint
522 txt ".."
770 txt ".."
523− FromTo from to -> brackets $ do
771+ FromTo from to -> brackets s $ do
524 located from p_hsExpr
772 located from p_hsExpr
525− breakpoint'
773+ breakpoint
526− txt ".. "
774+ txt ".."
775+ space
527 located to p_hsExpr
776 located to p_hsExpr
528− FromThenTo from next to -> brackets $ do
777+ FromThenTo from next to -> brackets s $ do
529− velt (withSep comma (located' p_hsExpr) [from, next])
778+ sep commaDel (located' p_hsExpr) [from, next]
530− breakpoint'
779+ breakpoint
531− txt ".. "
780+ txt ".."
781+ space
532 located to p_hsExpr
782 located to p_hsExpr
533− HsSCC NoExt _ name x -> do
783+ HsSCC NoExtField _ name x -> do
534 txt "{-# SCC "
784 txt "{-# SCC "
535 atom name
785 atom name
536 txt " #-}"
786 txt " #-}"
537 breakpoint
787 breakpoint
538 located x p_hsExpr
788 located x p_hsExpr
539− HsCoreAnn NoExt _ value x -> do
789+ HsCoreAnn NoExtField _ value x -> do
540 txt "{-# CORE "
790 txt "{-# CORE "
541 atom value
791 atom value
542 txt " #-}"
792 txt " #-}"
543 breakpoint
793 breakpoint
544 located x p_hsExpr
794 located x p_hsExpr
545− HsBracket NoExt x -> p_hsBracket x
795+ HsBracket NoExtField x -> p_hsBracket x
546 HsRnBracketOut {} -> notImplemented "HsRnBracketOut"
796 HsRnBracketOut {} -> notImplemented "HsRnBracketOut"
547 HsTcBracketOut {} -> notImplemented "HsTcBracketOut"
797 HsTcBracketOut {} -> notImplemented "HsTcBracketOut"
548− HsSpliceE NoExt splice -> p_hsSplice splice
798+ HsSpliceE NoExtField splice -> p_hsSplice splice
549− HsProc NoExt p e -> do
799+ HsProc NoExtField p e -> do
550 txt "proc"
800 txt "proc"
551− located p $ \x -> do
801+ located p $ \x -> do
552 breakpoint
802 breakpoint
553 inci (p_pat x)
803 inci (p_pat x)
554 breakpoint
804 breakpoint
555 txt "->"
805 txt "->"
556− placeHanging (cmdTopPlacement (unLoc e)) (located e p_hsCmdTop)
806+ placeHanging (cmdTopPlacement (unLoc e)) $
557− HsStatic _ e -> do
807+ located e p_hsCmdTop
808+ HsStatic _ e -> do
558 txt "static"
809 txt "static"
559 breakpoint
810 breakpoint
560 inci (located e p_hsExpr)
811 inci (located e p_hsExpr)
561− HsArrApp NoExt body input arrType cond ->
562− p_hsCmd (HsCmdArrApp NoExt body input arrType cond)
563− HsArrForm NoExt form mfixity cmds ->
564− p_hsCmd (HsCmdArrForm NoExt form Prefix mfixity cmds)
565 HsTick {} -> notImplemented "HsTick"
812 HsTick {} -> notImplemented "HsTick"
566 HsBinTick {} -> notImplemented "HsBinTick"
813 HsBinTick {} -> notImplemented "HsBinTick"
567 HsTickPragma {} -> notImplemented "HsTickPragma"
814 HsTickPragma {} -> notImplemented "HsTickPragma"
568− EWildPat NoExt -> txt "_"
569− EAsPat {} -> notImplemented "EAsPat"
570− EViewPat {} -> notImplemented "EViewPat"
571− ELazyPat {} -> notImplemented "ELazyPat"
572 HsWrap {} -> notImplemented "HsWrap"
815 HsWrap {} -> notImplemented "HsWrap"
573− XExpr {} -> notImplemented "XExpr"
816+ XExpr x -> noExtCon x
574
817
575p_patSynBind :: PatSynBind GhcPs GhcPs -> R ()
818p_patSynBind :: PatSynBind GhcPs GhcPs -> R ()
576p_patSynBind PSB {..} = do
819p_patSynBind PSB {..} = do
577− txt "pattern "
820+ let rhs = do
578− let nonEmptySynDetails = \case
821+ space
579− PrefixCon (_:_) -> True
822+ case psb_dir of
580− RecCon (_:_) -> True
823+ Unidirectional -> do
581− _ -> False
824+ txt "<-"
582− case psb_dir of
825+ breakpoint
583− Unidirectional -> do
826+ located psb_def p_pat
584− p_rdrName psb_id
827+ ImplicitBidirectional -> do
585− when (nonEmptySynDetails psb_args) space
828+ equals
586− p_patSynDetails psb_args
829+ breakpoint
587− txt " <-"
830+ located psb_def p_pat
588− breakpoint
831+ ExplicitBidirectional mgroup -> do
589− inci (located psb_def p_pat)
832+ txt "<-"
590− ImplicitBidirectional -> do
833+ breakpoint
834+ located psb_def p_pat
835+ newline
836+ txt "where"
837+ newline
838+ inci (p_matchGroup (Function psb_id) mgroup)
839+ txt "pattern"
840+ case psb_args of
841+ PrefixCon xs -> do
842+ space
591 p_rdrName psb_id
843 p_rdrName psb_id
592− when (nonEmptySynDetails psb_args) space
844+ inci $ do
593− p_patSynDetails psb_args
845+ switchLayout (getLoc <$> xs) $ do
594− txt " ="
846+ unless (null xs) breakpoint
595− breakpoint
847+ sitcc (sep breakpoint p_rdrName xs)
596− inci (located psb_def p_pat)
848+ rhs
597− ExplicitBidirectional mgroup -> do
849+ RecCon xs -> do
850+ space
598 p_rdrName psb_id
851 p_rdrName psb_id
599− when (nonEmptySynDetails psb_args) space
600− p_patSynDetails psb_args
601− txt " <-"
602− breakpoint
603− inci (located psb_def p_pat)
604− newline
605 inci $ do
852 inci $ do
606− line (txt "where")
853+ switchLayout (getLoc . recordPatSynPatVar <$> xs) $ do
607− inci (p_matchGroup (Function psb_id) mgroup)
854+ unless (null xs) breakpoint
608−p_patSynBind (XPatSynBind NoExt) = notImplemented "XPatSynBind"
855+ braces N $
609−
856+ sep commaDel (p_rdrName . recordPatSynPatVar) xs
610−p_patSynDetails :: HsPatSynDetails (Located RdrName) -> R ()
857+ rhs
611−p_patSynDetails = \case
858+ InfixCon l r -> do
612− PrefixCon xs ->
859+ switchLayout [getLoc l, getLoc r] $ do
613− velt' (p_rdrName <$> xs)
860+ space
614− RecCon xs ->
861+ p_rdrName l
615− velt' (p_rdrName . recordPatSynPatVar <$> xs)
862+ breakpoint
616− InfixCon _ _ -> notImplemented "InfixCon"
863+ inci $ do
864+ p_rdrName psb_id
865+ space
866+ p_rdrName r
867+ inci rhs
868+p_patSynBind (XPatSynBind x) = noExtCon x
869+
870+p_case ::
871+ Data body =>
872+ -- | Placer
873+ (body -> Placement) ->
874+ -- | Render
875+ (body -> R ()) ->
876+ -- | Expression
877+ LHsExpr GhcPs ->
878+ -- | Match group
879+ MatchGroup GhcPs (Located body) ->
880+ R ()
881+p_case placer render e mgroup = do
882+ txt "case"
883+ space
884+ located e p_hsExpr
885+ space
886+ txt "of"
887+ breakpoint
888+ inci (p_matchGroup' placer render Case mgroup)
889+
890+p_if ::
891+ Data body =>
892+ -- | Placer
893+ (body -> Placement) ->
894+ -- | Render
895+ (body -> R ()) ->
896+ -- | If
897+ LHsExpr GhcPs ->
898+ -- | Then
899+ Located body ->
900+ -- | Else
901+ Located body ->
902+ R ()
903+p_if placer render if' then' else' = do
904+ txt "if"
905+ space
906+ located if' p_hsExpr
907+ breakpoint
908+ inci $ do
909+ txt "then"
910+ space
911+ located then' $ \x ->
912+ placeHanging (placer x) (render x)
913+ breakpoint
914+ txt "else"
915+ space
916+ located else' $ \x ->
917+ placeHanging (placer x) (render x)
918+
919+p_let ::
920+ Data body =>
921+ -- | Render
922+ (body -> R ()) ->
923+ Located (HsLocalBindsLR GhcPs GhcPs) ->
924+ Located body ->
925+ R ()
926+p_let render localBinds e = sitcc $ do
927+ txt "let"
928+ space
929+ dontUseBraces $ sitcc (located localBinds p_hsLocalBinds)
930+ vlayout space (newline >> txt " ")
931+ txt "in"
932+ space
933+ sitcc (located e render)
617
934
618p_pat :: Pat GhcPs -> R ()
935p_pat :: Pat GhcPs -> R ()
619p_pat = \case
936p_pat = \case
620− WildPat NoExt -> txt "_"
937+ WildPat NoExtField -> txt "_"
621− VarPat NoExt name -> p_rdrName name
938+ VarPat NoExtField name -> p_rdrName name
622− LazyPat NoExt pat -> do
939+ LazyPat NoExtField pat -> do
623 txt "~"
940 txt "~"
624 located pat p_pat
941 located pat p_pat
625− AsPat NoExt name pat -> do
942+ AsPat NoExtField name pat -> do
626 p_rdrName name
943 p_rdrName name
627 txt "@"
944 txt "@"
628 located pat p_pat
945 located pat p_pat
629− ParPat NoExt pat ->
946+ ParPat NoExtField pat ->
630− located pat (parens . p_pat)
947+ located pat (parens S . p_pat)
631− BangPat NoExt pat -> do
948+ BangPat NoExtField pat -> do
632 txt "!"
949 txt "!"
633 located pat p_pat
950 located pat p_pat
634− ListPat NoExt pats -> do
951+ ListPat NoExtField pats ->
635− brackets $ velt (withSep comma (located' p_pat) pats)
952+ brackets S $ sep commaDel (located' p_pat) pats
636− TuplePat NoExt pats boxing -> do
953+ TuplePat NoExtField pats boxing -> do
637− let f =
954+ let parens' =
638 case boxing of
955 case boxing of
639− Boxed -> parens
956+ Boxed -> parens S
640− Unboxed -> parensHash
957+ Unboxed -> parensHash S
641− f $ velt (withSep comma (located' p_pat) pats)
958+ parens' $ sep commaDel (sitcc . located' p_pat) pats
642− SumPat NoExt pat _ _ -> do
959+ SumPat NoExtField pat tag arity ->
643− -- XXX I'm not sure about this one.
960+ p_unboxedSum S tag arity (located pat p_pat)
644− located pat p_pat
645 ConPatIn pat details ->
961 ConPatIn pat details ->
646 case details of
962 case details of
647 PrefixCon xs -> sitcc $ do
963 PrefixCon xs -> sitcc $ do
648 p_rdrName pat
964 p_rdrName pat
649 unless (null xs) $ do
965 unless (null xs) $ do
650 breakpoint
966 breakpoint
651− inci $ velt' (located' p_pat <$> xs)
967+ inci . sitcc $ sep breakpoint (sitcc . located' p_pat) xs
652 RecCon (HsRecFields fields dotdot) -> do
968 RecCon (HsRecFields fields dotdot) -> do
653 p_rdrName pat
969 p_rdrName pat
654 breakpoint
970 breakpoint
655 let f = \case
971 let f = \case
656 Nothing -> txt ".."
972 Nothing -> txt ".."
657 Just x -> located x p_pat_hsRecField
973 Just x -> located x p_pat_hsRecField
658− inci . braces . velt . withSep comma f $ case dotdot of
974+ inci . braces N . sep commaDel f $
659− Nothing -> Just <$> fields
975+ case dotdot of
660− Just n -> (Just <$> take n fields) ++ [Nothing]
976+ Nothing -> Just <$> fields
661− InfixCon x y -> do
977+ Just (L _ n) -> (Just <$> take n fields) ++ [Nothing]
662− located x p_pat
978+ InfixCon l r -> do
663− space
979+ switchLayout [getLoc l, getLoc r] $ do
664− p_rdrName pat
980+ located l p_pat
665− breakpoint
981+ breakpoint
666− inci (located y p_pat)
982+ inci $ do
983+ p_rdrName pat
984+ space
985+ located r p_pat
667 ConPatOut {} -> notImplemented "ConPatOut" -- presumably created by renamer?
986 ConPatOut {} -> notImplemented "ConPatOut" -- presumably created by renamer?
668− ViewPat NoExt expr pat -> sitcc $ do
987+ ViewPat NoExtField expr pat -> sitcc $ do
669 located expr p_hsExpr
988 located expr p_hsExpr
670− txt " ->"
989+ space
990+ txt "->"
671 breakpoint
991 breakpoint
672 inci (located pat p_pat)
992 inci (located pat p_pat)
673− SplicePat NoExt splice -> p_hsSplice splice
993+ SplicePat NoExtField splice -> p_hsSplice splice
674− LitPat NoExt p -> atom p
994+ LitPat NoExtField p -> atom p
675− NPat NoExt v _ _ -> located v (atom . ol_val)
995+ NPat NoExtField v _ _ -> located v (atom . ol_val)
676− NPlusKPat NoExt n k _ _ _ -> sitcc $ do
996+ NPlusKPat NoExtField n k _ _ _ -> sitcc $ do
677 p_rdrName n
997 p_rdrName n
678 breakpoint
998 breakpoint
679 inci $ do
999 inci $ do
680− txt "+ "
1000+ txt "+"
1001+ space
681 located k (atom . ol_val)
1002 located k (atom . ol_val)
682− SigPat hswc pat -> do
1003+ SigPat NoExtField pat hswc -> do
683 located pat p_pat
1004 located pat p_pat
684 p_typeAscription hswc
1005 p_typeAscription hswc
685 CoPat {} -> notImplemented "CoPat" -- apparently created at some later stage
1006 CoPat {} -> notImplemented "CoPat" -- apparently created at some later stage
686− XPat NoExt -> notImplemented "XPat"
1007+ XPat x -> noExtCon x
687
1008
688p_pat_hsRecField :: HsRecField' (FieldOcc GhcPs) (LPat GhcPs) -> R ()
1009p_pat_hsRecField :: HsRecField' (FieldOcc GhcPs) (LPat GhcPs) -> R ()
689p_pat_hsRecField HsRecField {..} = do
1010p_pat_hsRecField HsRecField {..} = do
690 located hsRecFieldLbl $ \x ->
1011 located hsRecFieldLbl $ \x ->
691 p_rdrName (rdrNameFieldOcc x)
1012 p_rdrName (rdrNameFieldOcc x)
692 unless hsRecPun $ do
1013 unless hsRecPun $ do
693− txt " ="
1014+ space
1015+ equals
694 breakpoint
1016 breakpoint
695 inci (located hsRecFieldArg p_pat)
1017 inci (located hsRecFieldArg p_pat)
696
1018
1019+p_unboxedSum :: BracketStyle -> ConTag -> Arity -> R () -> R ()
1020+p_unboxedSum s tag arity m = do
1021+ let before = tag - 1
1022+ after = arity - before - 1
1023+ args = replicate before Nothing <> [Just m] <> replicate after Nothing
1024+ f x =
1025+ case x :: Maybe (R ()) of
1026+ Nothing ->
1027+ space
1028+ Just m' -> do
1029+ space
1030+ m'
1031+ space
1032+ parensHash s $ sep (txt "|") f args
1033+
697p_hsSplice :: HsSplice GhcPs -> R ()
1034p_hsSplice :: HsSplice GhcPs -> R ()
698p_hsSplice = \case
1035p_hsSplice = \case
699− HsTypedSplice NoExt deco _ expr -> p_hsSpliceTH True expr deco
1036+ HsTypedSplice NoExtField deco _ expr -> p_hsSpliceTH True expr deco
700− HsUntypedSplice NoExt deco _ expr -> p_hsSpliceTH False expr deco
1037+ HsUntypedSplice NoExtField deco _ expr -> p_hsSpliceTH False expr deco
701− HsQuasiQuote NoExt _ quoterName srcSpan str -> do
1038+ HsQuasiQuote NoExtField _ quoterName srcSpan str -> do
702 txt "["
1039 txt "["
703 p_rdrName (L srcSpan quoterName)
1040 p_rdrName (L srcSpan quoterName)
704 txt "|"
1041 txt "|"
705− -- NOTE QuasiQuoters often rely on precise custom strings. We cannot do
1042+ -- QuasiQuoters often rely on precise custom strings. We cannot do any
706− -- any formatting here without potentially breaking someone's code.
1043+ -- formatting here without potentially breaking someone's code.
707 atom str
1044 atom str
708 txt "|]"
1045 txt "|]"
709 HsSpliced {} -> notImplemented "HsSpliced"
1046 HsSpliced {} -> notImplemented "HsSpliced"
710− XSplice {} -> notImplemented "XSplice"
1047+ HsSplicedT {} -> notImplemented "HsSplicedT"
1048+ XSplice x -> noExtCon x
711
1049
712−p_hsSpliceTH
1050+p_hsSpliceTH ::
713− :: Bool -- ^ Typed splice?
1051+ -- | Typed splice?
714− -> LHsExpr GhcPs -- ^ Splice expression
1052+ Bool ->
715− -> SpliceDecoration -- ^ Splice decoration
1053+ -- | Splice expression
716− -> R ()
1054+ LHsExpr GhcPs ->
1055+ -- | Splice decoration
1056+ SpliceDecoration ->
1057+ R ()
717p_hsSpliceTH isTyped expr = \case
1058p_hsSpliceTH isTyped expr = \case
718 HasParens -> do
1059 HasParens -> do
719 txt decoSymbol
1060 txt decoSymbol
720− parens (located expr (sitcc . p_hsExpr))
1061+ parens N (located expr (sitcc . p_hsExpr))
721 HasDollar -> do
1062 HasDollar -> do
722 txt decoSymbol
1063 txt decoSymbol
723 located expr (sitcc . p_hsExpr)
1064 located expr (sitcc . p_hsExpr)
724− NoParens -> do
1065+ NoParens ->
725 located expr (sitcc . p_hsExpr)
1066 located expr (sitcc . p_hsExpr)
726 where
1067 where
727 decoSymbol = if isTyped then "$$" else "$"
1068 decoSymbol = if isTyped then "$$" else "$"
728
1069
729p_hsBracket :: HsBracket GhcPs -> R ()
1070p_hsBracket :: HsBracket GhcPs -> R ()
730p_hsBracket = \case
1071p_hsBracket = \case
731− ExpBr NoExt expr -> quote "e" (located expr p_hsExpr)
1072+ ExpBr NoExtField expr -> do
732− PatBr NoExt pat -> quote "p" (located pat p_pat)
1073+ anns <- getEnclosingAnns
733− DecBrL NoExt decls -> quote "d" (p_hsDecls Free decls)
1074+ let name = case anns of
734− DecBrG NoExt _ -> notImplemented "DecBrG" -- result of renamer
1075+ AnnOpenEQ : _ -> ""
735− TypBr NoExt ty -> quote "t" (located ty p_hsType)
1076+ _ -> "e"
736− VarBr NoExt isSingleQuote name -> do
1077+ quote name (located expr p_hsExpr)
1078+ PatBr NoExtField pat -> located pat (quote "p" . p_pat)
1079+ DecBrL NoExtField decls -> quote "d" (p_hsDecls Free decls)
1080+ DecBrG NoExtField _ -> notImplemented "DecBrG" -- result of renamer
1081+ TypBr NoExtField ty -> quote "t" (located ty p_hsType)
1082+ VarBr NoExtField isSingleQuote name -> do
737 txt (bool "''" "'" isSingleQuote)
1083 txt (bool "''" "'" isSingleQuote)
738− p_rdrName (noLoc name)
1084+ -- HACK As you can see we use 'noLoc' here to be able to pass name into
739− TExpBr NoExt expr -> do
1085+ -- 'p_rdrName' since the latter expects a "located" thing. The problem
1086+ -- is that 'VarBr' doesn't provide us with location of the name. This in
1087+ -- turn makes it impossible to detect if there are parentheses around
1088+ -- it, etc. So we have to add parentheses manually assuming they are
1089+ -- necessary for all operators.
1090+ let isOperator =
1091+ all
1092+ (\i -> isPunctuation i || isSymbol i)
1093+ (showOutputable (rdrNameOcc name))
1094+ && not (doesNotNeedExtraParens name)
1095+ wrapper = if isOperator then parens N else id
1096+ wrapper $ p_rdrName (noLoc name)
1097+ TExpBr NoExtField expr -> do
740 txt "[||"
1098 txt "[||"
741 breakpoint'
1099 breakpoint'
742 located expr p_hsExpr
1100 located expr p_hsExpr
743 breakpoint'
1101 breakpoint'
744 txt "||]"
1102 txt "||]"
745− XBracket {} -> notImplemented "XBracket"
1103+ XBracket x -> noExtCon x
746 where
1104 where
747 quote :: Text -> R () -> R ()
1105 quote :: Text -> R () -> R ()
748 quote name body = do
1106 quote name body = do
@@ -750,23 +1108,86 @@ p_hsBracket = \case
750 txt name
1108 txt name
751 txt "|"
1109 txt "|"
752 breakpoint'
1110 breakpoint'
753− body
1111+ inci $ do
754− breakpoint'
1112+ dontUseBraces body
755− txt "|]"
1113+ breakpoint'
1114+ txt "|]"
1115+
1116+-- Print the source text of a string literal while indenting
1117+-- gaps correctly.
1118+
1119+p_stringLit :: String -> R ()
1120+p_stringLit src =
1121+ let s = splitGaps src
1122+ singleLine =
1123+ txt $ Text.pack (mconcat s)
1124+ multiLine =
1125+ sitcc $ sep breakpoint (txt . Text.pack) (backslashes s)
1126+ in vlayout singleLine multiLine
1127+ where
1128+ -- Split a string on gaps (backslash delimited whitespaces)
1129+ --
1130+ -- > splitGaps "bar\\ \\fo\\&o" == ["bar", "fo\\&o"]
1131+ splitGaps :: String -> [String]
1132+ splitGaps "" = []
1133+ splitGaps s =
1134+ let -- A backslash and a whitespace starts a "gap"
1135+ p (Just '\\', _, _) = True
1136+ p (_, '\\', Just c) | ghcSpace c = False
1137+ p _ = True
1138+ in case span p (zipPrevNext s) of
1139+ (l, r) ->
1140+ let -- drop the initial '\', any amount of 'ghcSpace', and another '\'
1141+ r' = drop 1 . dropWhile ghcSpace . drop 1 $ map orig r
1142+ in map orig l : splitGaps r'
1143+ -- GHC's definition of whitespaces in strings
1144+ -- See: https://gitlab.haskell.org/ghc/ghc/blob/86753475/compiler/parser/Lexer.x#L1653
1145+ ghcSpace :: Char -> Bool
1146+ ghcSpace c = c <= '\x7f' && is_space c
1147+ -- Add backslashes to the inner side of the strings
1148+ --
1149+ -- > backslashes ["a", "b", "c"] == ["a\\", "\\b\\", "\\c"]
1150+ backslashes :: [String] -> [String]
1151+ backslashes (x : y : xs) = (x ++ "\\") : backslashes (('\\' : y) : xs)
1152+ backslashes xs = xs
1153+ -- Attaches previous and next items to each list element
1154+ zipPrevNext :: [a] -> [(Maybe a, a, Maybe a)]
1155+ zipPrevNext xs =
1156+ let z =
1157+ zip
1158+ (zip (Nothing : map Just xs) xs)
1159+ (map Just (tail xs) ++ repeat Nothing)
1160+ in map (\((p, x), n) -> (p, x, n)) z
1161+ orig (_, x, _) = x
756
1162
757----------------------------------------------------------------------------
1163----------------------------------------------------------------------------
758-- Helpers
1164-- Helpers
759
1165
1166+-- | Return the wrapping function controlling the use of braces according to
1167+-- the current layout.
1168+layoutToBraces :: Layout -> R () -> R ()
1169+layoutToBraces = \case
1170+ SingleLine -> useBraces
1171+ MultiLine -> id
1172+
1173+-- | Append each element in both lists with semigroups. If one list is shorter
1174+-- than the other, return the rest of the longer list unchanged.
1175+liftAppend :: Semigroup a => [a] -> [a] -> [a]
1176+liftAppend [] [] = []
1177+liftAppend [] (y : ys) = y : ys
1178+liftAppend (x : xs) [] = x : xs
1179+liftAppend (x : xs) (y : ys) = x <> y : liftAppend xs ys
1180+
760getGRHSSpan :: GRHS GhcPs (Located body) -> SrcSpan
1181getGRHSSpan :: GRHS GhcPs (Located body) -> SrcSpan
761−getGRHSSpan (GRHS NoExt _ body) = getLoc body
1182+getGRHSSpan (GRHS NoExtField guards body) =
762−getGRHSSpan (XGRHS NoExt) = notImplemented "XGRHS"
1183+ combineSrcSpans' $ getLoc body :| map getLoc guards
1184+getGRHSSpan (XGRHS x) = noExtCon x
763
1185
764-- | Place a thing that may have a hanging form. This function handles how
1186-- | Place a thing that may have a hanging form. This function handles how
765-- to separate it from preceding expressions and whether to bump indentation
1187-- to separate it from preceding expressions and whether to bump indentation
766-- depending on what sort of expression we have.
1188-- depending on what sort of expression we have.
767−
768placeHanging :: Placement -> R () -> R ()
1189placeHanging :: Placement -> R () -> R ()
769−placeHanging placement m = do
1190+placeHanging placement m =
770 case placement of
1191 case placement of
771 Hanging -> do
1192 Hanging -> do
772 space
1193 space
@@ -777,49 +1198,165 @@ placeHanging placement m = do
777
1198
778-- | Check if given block contains single expression which has a hanging
1199-- | Check if given block contains single expression which has a hanging
779-- form.
1200-- form.
780−
1201+blockPlacement ::
781−blockPlacement
1202+ (body -> Placement) ->
782− :: (body -> Placement)
1203+ [LGRHS GhcPs (Located body)] ->
783− -> [LGRHS GhcPs (Located body)]
1204+ Placement
784− -> Placement
1205+blockPlacement placer [L _ (GRHS NoExtField _ (L _ x))] = placer x
785−blockPlacement placer [(L _ (GRHS NoExt _ (L _ x)))] = placer x
786blockPlacement _ _ = Normal
1206blockPlacement _ _ = Normal
787
1207
788-- | Check if given command has a hanging form.
1208-- | Check if given command has a hanging form.
789−
790cmdPlacement :: HsCmd GhcPs -> Placement
1209cmdPlacement :: HsCmd GhcPs -> Placement
791cmdPlacement = \case
1210cmdPlacement = \case
792− HsCmdLam NoExt _ -> Hanging
1211+ HsCmdLam NoExtField _ -> Hanging
793− HsCmdCase NoExt _ _ -> Hanging
1212+ HsCmdCase NoExtField _ _ -> Hanging
794− HsCmdDo NoExt _ -> Hanging
1213+ HsCmdDo NoExtField _ -> Hanging
795 _ -> Normal
1214 _ -> Normal
796
1215
797cmdTopPlacement :: HsCmdTop GhcPs -> Placement
1216cmdTopPlacement :: HsCmdTop GhcPs -> Placement
798cmdTopPlacement = \case
1217cmdTopPlacement = \case
799− HsCmdTop NoExt (L _ x) -> cmdPlacement x
1218+ HsCmdTop NoExtField (L _ x) -> cmdPlacement x
800− XCmdTop {} -> notImplemented "XCmdTop"
1219+ XCmdTop x -> noExtCon x
801
1220
802-- | Check if given expression has a hanging form.
1221-- | Check if given expression has a hanging form.
803−
804exprPlacement :: HsExpr GhcPs -> Placement
1222exprPlacement :: HsExpr GhcPs -> Placement
805exprPlacement = \case
1223exprPlacement = \case
806− HsLam NoExt _ -> Hanging
1224+ -- Only hang lambdas with single line parameter lists
807− HsLamCase NoExt _ -> Hanging
1225+ HsLam NoExtField mg -> case mg of
808− HsCase NoExt _ _ -> Hanging
1226+ MG _ (L _ [L _ (Match NoExtField _ (x : xs) _)]) _
809− HsDo NoExt DoExpr _ -> Hanging
1227+ | isOneLineSpan (combineSrcSpans' $ fmap getLoc (x :| xs)) ->
810− HsDo NoExt MDoExpr _ -> Hanging
1228+ Hanging
811− RecordCon NoExt _ _ -> Hanging
1229+ _ -> Normal
812− HsProc NoExt (L s _) _ ->
1230+ HsLamCase NoExtField _ -> Hanging
813− -- Indentation breaks if pattern is longer than one line and left hanging.
1231+ HsCase NoExtField _ _ -> Hanging
814− -- Consequentally, once apply hanging when it is safe.
1232+ HsDo NoExtField DoExpr _ -> Hanging
815− if isOneLineSpan s
1233+ HsDo NoExtField MDoExpr _ -> Hanging
816− then Hanging
1234+ OpApp NoExtField _ op y ->
817− else Normal
1235+ case (fmap getOpNameStr . getOpName . unLoc) op of
1236+ Just "$" -> exprPlacement (unLoc y)
1237+ _ -> Normal
1238+ HsApp NoExtField _ y -> exprPlacement (unLoc y)
1239+ HsProc NoExtField p _ ->
1240+ -- Indentation breaks if pattern is longer than one line and left
1241+ -- hanging. Consequently, only apply hanging when it is safe.
1242+ if isOneLineSpan (getLoc p)
1243+ then Hanging
1244+ else Normal
818 _ -> Normal
1245 _ -> Normal
819
1246
820withGuards :: [LGRHS GhcPs (Located body)] -> Bool
1247withGuards :: [LGRHS GhcPs (Located body)] -> Bool
821withGuards = any (checkOne . unLoc)
1248withGuards = any (checkOne . unLoc)
822 where
1249 where
823 checkOne :: GRHS GhcPs (Located body) -> Bool
1250 checkOne :: GRHS GhcPs (Located body) -> Bool
824− checkOne (GRHS NoExt [] _) = False
1251+ checkOne (GRHS NoExtField [] _) = False
825 checkOne _ = True
1252 checkOne _ = True
1253+
1254+exprOpTree :: LHsExpr GhcPs -> OpTree (LHsExpr GhcPs) (LHsExpr GhcPs)
1255+exprOpTree (L _ (OpApp NoExtField x op y)) = OpBranch (exprOpTree x) op (exprOpTree y)
1256+exprOpTree n = OpNode n
1257+
1258+getOpName :: HsExpr GhcPs -> Maybe RdrName
1259+getOpName = \case
1260+ HsVar NoExtField (L _ a) -> Just a
1261+ _ -> Nothing
1262+
1263+getOpNameStr :: RdrName -> String
1264+getOpNameStr = occNameString . rdrNameOcc
1265+
1266+p_exprOpTree ::
1267+ -- | Bracket style to use
1268+ BracketStyle ->
1269+ OpTree (LHsExpr GhcPs) (LHsExpr GhcPs) ->
1270+ R ()
1271+p_exprOpTree s (OpNode x) = located x (p_hsExpr' s)
1272+p_exprOpTree s (OpBranch x op y) = do
1273+ -- If the beginning of the first argument and the second argument are on
1274+ -- the same line, and the second argument has a hanging form, use hanging
1275+ -- placement.
1276+ let placement =
1277+ if isOneLineSpan
1278+ (mkSrcSpan (srcSpanStart (opTreeLoc x)) (srcSpanStart (opTreeLoc y)))
1279+ then case y of
1280+ OpNode (L _ n) -> exprPlacement n
1281+ _ -> Normal
1282+ else Normal
1283+ -- Distinguish holes used in infix notation.
1284+ -- eg. '1 _foo 2' and '1 `_foo` 2'
1285+ opWrapper = case unLoc op of
1286+ HsUnboundVar NoExtField _ -> backticks
1287+ _ -> id
1288+ layout <- getLayout
1289+ let ub = case layout of
1290+ SingleLine -> useBraces
1291+ MultiLine -> case placement of
1292+ Hanging -> useBraces
1293+ Normal -> dontUseBraces
1294+ opNameStr = (fmap getOpNameStr . getOpName . unLoc) op
1295+ gotDollar = opNameStr == Just "$"
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
1307+ isDoBlock = \case
1308+ OpNode (L _ HsDo {}) -> True
1309+ _ -> False
1310+ useRecordDot' <- useRecordDot
1311+ if
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)
1325+ && placement == Normal -> do
1326+ useBraces lhs
1327+ space
1328+ p_op
1329+ breakpoint
1330+ inci p_y
1331+ | useRecordDot' && gotRecordDot -> do
1332+ lhs
1333+ when isSection space
1334+ p_op
1335+ p_y
1336+ | otherwise -> do
1337+ ub lhs
1338+ placeHanging placement $ do
1339+ p_op
1340+ space
1341+ p_y
1342+
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+
1356+-- | Get annotations for the enclosing element.
1357+getEnclosingAnns :: R [AnnKeywordId]
1358+getEnclosingAnns = do
1359+ e <- getEnclosingSpan (const True)
1360+ case e of
1361+ Nothing -> return []
1362+ Just e' -> getAnns (RealSrcSpan e')
src/Ormolu/Printer/Meat/Declaration/Value.hs-bootnew file+17
@@ -0,0 +1,17 @@
1+module Ormolu.Printer.Meat.Declaration.Value
2+ ( p_valDecl,
3+ p_pat,
4+ p_hsExpr,
5+ p_hsSplice,
6+ p_stringLit,
7+ )
8+where
9+
10+import GHC
11+import Ormolu.Printer.Combinators
12+
13+p_valDecl :: HsBindLR GhcPs GhcPs -> R ()
14+p_pat :: Pat GhcPs -> R ()
15+p_hsExpr :: HsExpr GhcPs -> R ()
16+p_hsSplice :: HsSplice GhcPs -> R ()
17+p_stringLit :: String -> R ()
src/Ormolu/Printer/Meat/Declaration/Warning.hs+12−20
@@ -1,45 +1,40 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3
3
4module Ormolu.Printer.Meat.Declaration.Warning
4module Ormolu.Printer.Meat.Declaration.Warning
5− ( p_warnDecls
5+ ( p_warnDecls,
6− , p_moduleWarning
6+ p_moduleWarning,
7 )
7 )
8where
8where
9
9
10import BasicTypes
10import BasicTypes
11import Data.Foldable
11import Data.Foldable
12−import qualified Data.List.NonEmpty as NE
13import Data.Text (Text)
12import Data.Text (Text)
14import GHC
13import GHC
15import Ormolu.Printer.Combinators
14import Ormolu.Printer.Combinators
16import Ormolu.Printer.Meat.Common
15import Ormolu.Printer.Meat.Common
17−import Ormolu.Utils
18−import SrcLoc (combineSrcSpans)
19
16
20p_warnDecls :: WarnDecls GhcPs -> R ()
17p_warnDecls :: WarnDecls GhcPs -> R ()
21−p_warnDecls (Warnings NoExt _ warnings) =
18+p_warnDecls (Warnings NoExtField _ warnings) =
22 traverse_ (located' p_warnDecl) warnings
19 traverse_ (located' p_warnDecl) warnings
23−p_warnDecls XWarnDecls {} = notImplemented "XWarnDecls"
20+p_warnDecls (XWarnDecls x) = noExtCon x
24
21
25p_warnDecl :: WarnDecl GhcPs -> R ()
22p_warnDecl :: WarnDecl GhcPs -> R ()
26−p_warnDecl (Warning NoExt functions warningTxt) =
23+p_warnDecl (Warning NoExtField functions warningTxt) =
27 p_topLevelWarning functions warningTxt
24 p_topLevelWarning functions warningTxt
28−p_warnDecl XWarnDecl {} = notImplemented "XWarnDecl"
25+p_warnDecl (XWarnDecl x) = noExtCon x
29
26
30p_moduleWarning :: WarningTxt -> R ()
27p_moduleWarning :: WarningTxt -> R ()
31p_moduleWarning wtxt = do
28p_moduleWarning wtxt = do
32 let (pragmaText, lits) = warningText wtxt
29 let (pragmaText, lits) = warningText wtxt
33− switchLayout (listSpan lits) $ do
30+ inci $ pragma pragmaText $ inci $ p_lits lits
34− breakpoint
35− inci $ pragma pragmaText (p_lits lits)
36
31
37p_topLevelWarning :: [Located RdrName] -> WarningTxt -> R ()
32p_topLevelWarning :: [Located RdrName] -> WarningTxt -> R ()
38p_topLevelWarning fnames wtxt = do
33p_topLevelWarning fnames wtxt = do
39 let (pragmaText, lits) = warningText wtxt
34 let (pragmaText, lits) = warningText wtxt
40− switchLayout (combineSrcSpans (listSpan fnames) (listSpan lits)) $ do
35+ switchLayout (fmap getLoc fnames ++ fmap getLoc lits) $
41− pragma pragmaText $ do
36+ pragma pragmaText . inci $ do
42− velt (withSep comma p_rdrName fnames)
37+ sep commaDel p_rdrName fnames
43 breakpoint
38 breakpoint
44 p_lits lits
39 p_lits lits
45
40
@@ -48,10 +43,7 @@ warningText = \case
48 WarningTxt _ lits -> ("WARNING", lits)
43 WarningTxt _ lits -> ("WARNING", lits)
49 DeprecatedTxt _ lits -> ("DEPRECATED", lits)
44 DeprecatedTxt _ lits -> ("DEPRECATED", lits)
50
45
51−listSpan :: [Located a] -> SrcSpan
52−listSpan xs = combineSrcSpans' (getLoc <$> NE.fromList xs)
53−
54p_lits :: [Located StringLiteral] -> R ()
46p_lits :: [Located StringLiteral] -> R ()
55p_lits = \case
47p_lits = \case
56 [l] -> atom l
48 [l] -> atom l
57− ls -> brackets . velt $ withSep comma atom ls
49+ ls -> brackets N $ sep commaDel atom ls
src/Ormolu/Printer/Meat/ImportExport.hs+100−54
@@ -1,21 +1,19 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
4
4
5-- | Rendering of import and export lists.
5-- | Rendering of import and export lists.
6−
7module Ormolu.Printer.Meat.ImportExport
6module Ormolu.Printer.Meat.ImportExport
8− ( p_hsmodExports
7+ ( p_hsmodExports,
9− , p_hsmodImport
8+ p_hsmodImport,
10 )
9 )
11where
10where
12
11
13import Control.Monad
12import Control.Monad
14import GHC
13import GHC
15−import HsImpExp (IE (..))
16import Ormolu.Printer.Combinators
14import Ormolu.Printer.Combinators
17import Ormolu.Printer.Meat.Common
15import Ormolu.Printer.Meat.Common
18−import Ormolu.Utils
16+import Ormolu.Utils (RelativePos (..), attachRelativePos)
19
17
20p_hsmodExports :: [LIE GhcPs] -> R ()
18p_hsmodExports :: [LIE GhcPs] -> R ()
21p_hsmodExports [] = do
19p_hsmodExports [] = do
@@ -23,58 +21,106 @@ p_hsmodExports [] = do
23 breakpoint'
21 breakpoint'
24 txt ")"
22 txt ")"
25p_hsmodExports xs =
23p_hsmodExports xs =
26− parens . velt $ withSep comma (sitcc . located' p_lie) xs
24+ parens N $ do
25+ layout <- getLayout
26+ sep
27+ breakpoint
28+ (\(p, l) -> sitcc (located l (p_lie layout p)))
29+ (attachRelativePos xs)
27
30
28−p_hsmodImport :: ImportDecl GhcPs -> R ()
31+p_hsmodImport :: Bool -> ImportDecl GhcPs -> R ()
29−p_hsmodImport ImportDecl {..} = line $ do
32+p_hsmodImport useQualifiedPost ImportDecl {..} = do
30− txt "import "
33+ txt "import"
31− when ideclSource $
34+ space
32− txt "{-# SOURCE #-} "
35+ when ideclSource (txt "{-# SOURCE #-}")
33− when ideclSafe $
36+ space
34− txt "safe "
37+ when ideclSafe (txt "safe")
35− when ideclQualified $
38+ space
36− txt "qualified "
39+ when
40+ (isImportDeclQualified ideclQualified && not useQualifiedPost)
41+ (txt "qualified")
42+ space
37 case ideclPkgQual of
43 case ideclPkgQual of
38 Nothing -> return ()
44 Nothing -> return ()
39− Just slit -> do
45+ Just slit -> atom slit
40− atom slit
46+ space
41− space
47+ inci $ do
42− located ideclName atom
48+ located ideclName atom
43− case ideclAs of
49+ when
44− Nothing -> return ()
50+ (isImportDeclQualified ideclQualified && useQualifiedPost)
45− Just l -> do
51+ (space >> txt "qualified")
46− txt " as "
52+ case ideclAs of
47− located l atom
53+ Nothing -> return ()
48− case ideclHiding of
54+ Just l -> do
49− Nothing -> return ()
55+ space
50− Just (hiding, _) ->
56+ txt "as"
51− when hiding $
57+ space
52− txt " hiding"
58+ located l atom
53− case ideclHiding of
59+ space
54− Nothing -> return ()
60+ case ideclHiding of
55− Just (_, l) -> do
61+ Nothing -> return ()
56− breakpoint
62+ Just (hiding, _) ->
57− inci . locatedVia Nothing l $
63+ when hiding (txt "hiding")
58− parens . velt . withSep comma (located' p_lie)
64+ case ideclHiding of
59−p_hsmodImport (XImportDecl NoExt) = notImplemented "XImportDecl"
65+ Nothing -> return ()
66+ Just (_, L _ xs) -> do
67+ breakpoint
68+ parens N $ do
69+ layout <- getLayout
70+ sep
71+ breakpoint
72+ (\(p, l) -> sitcc (located l (p_lie layout p)))
73+ (attachRelativePos xs)
74+ newline
75+p_hsmodImport _ (XImportDecl x) = noExtCon x
60
76
61−p_lie :: IE GhcPs -> R ()
77+p_lie :: Layout -> RelativePos -> IE GhcPs -> R ()
62−p_lie = \case
78+p_lie encLayout relativePos = \case
63− IEVar NoExt l1 -> located l1 p_ieWrappedName
79+ IEVar NoExtField l1 -> do
64− IEThingAbs NoExt l1 -> located l1 p_ieWrappedName
80+ located l1 p_ieWrappedName
65− IEThingAll NoExt l1 -> do
81+ p_comma
82+ IEThingAbs NoExtField l1 -> do
83+ located l1 p_ieWrappedName
84+ p_comma
85+ IEThingAll NoExtField l1 -> do
66 located l1 p_ieWrappedName
86 located l1 p_ieWrappedName
67− txt " (..)"
87+ space
68− IEThingWith NoExt l1 w xs _ -> sitcc $ do
88+ txt "(..)"
89+ p_comma
90+ IEThingWith NoExtField l1 w xs _ -> sitcc $ do
69 located l1 p_ieWrappedName
91 located l1 p_ieWrappedName
70 breakpoint
92 breakpoint
71− -- XXX I have no idea what field labels are in this context.
72 inci $ do
93 inci $ do
73− p_ieWildcard w
94+ let names :: [R ()]
74− parens . velt $ withSep comma (located' p_ieWrappedName) xs
95+ names = located' p_ieWrappedName <$> xs
75− IEModuleContents NoExt l1 -> located l1 p_hsmodName
96+ parens N . sep commaDel sitcc $
76− -- XXX I have no idea what these things are for.
97+ case w of
77− IEGroup NoExt _ _ -> return ()
98+ NoIEWildcard -> names
78− IEDoc NoExt _ -> return ()
99+ IEWildcard n ->
79− IEDocNamed NoExt _ -> return ()
100+ let (before, after) = splitAt n names
80− XIE NoExt -> notImplemented "XIE"
101+ in before ++ [txt ".."] ++ after
102+ p_comma
103+ IEModuleContents NoExtField l1 -> do
104+ located l1 p_hsmodName
105+ p_comma
106+ IEGroup NoExtField n str -> do
107+ case relativePos of
108+ SinglePos -> return ()
109+ FirstPos -> return ()
110+ MiddlePos -> newline
111+ LastPos -> newline
112+ p_hsDocString (Asterisk n) False (noLoc str)
113+ IEDoc NoExtField str ->
114+ p_hsDocString Pipe False (noLoc str)
115+ IEDocNamed NoExtField str -> p_hsDocName str
116+ XIE x -> noExtCon x
117+ where
118+ p_comma =
119+ case encLayout of
120+ SingleLine ->
121+ case relativePos of
122+ SinglePos -> return ()
123+ FirstPos -> comma
124+ MiddlePos -> comma
125+ LastPos -> return ()
126+ MultiLine -> comma
src/Ormolu/Printer/Meat/LanguagePragma.hsdeleted−23
@@ -1,23 +0,0 @@
1−-- | Pretty-printing of language pragmas.
2−
3−{-# LANGUAGE LambdaCase #-}
4−{-# LANGUAGE OverloadedStrings #-}
5−
6−module Ormolu.Printer.Meat.LanguagePragma
7− ( p_langPragmas
8− )
9−where
10−
11−import Data.Set (Set)
12−import Ormolu.Printer.Combinators
13−import qualified Data.Set as S
14−import qualified Data.Text as T
15−
16−p_langPragmas :: Set String -> R ()
17−p_langPragmas = mapM_ p_langPragma . S.toAscList
18−
19−p_langPragma :: String -> R ()
20−p_langPragma ext = line $ do
21− txt "{-# LANGUAGE "
22− txt (T.pack ext)
23− txt " #-}"
src/Ormolu/Printer/Meat/Module.hs+55−39
@@ -1,61 +1,77 @@
1+{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
3
4
4-- | Rendering of modules.
5-- | Rendering of modules.
5−
6module Ormolu.Printer.Meat.Module
6module Ormolu.Printer.Meat.Module
7− ( p_hsModule
7+ ( p_hsModule,
8 )
8 )
9where
9where
10
10
11import Control.Monad
11import Control.Monad
12−import Data.Maybe (isJust)
12+import qualified Data.Text as T
13−import Data.Set (Set)
14import GHC
13import GHC
15−import Ormolu.Imports
14+import Ormolu.Imports (normalizeImports)
15+import Ormolu.Parser.CommentStream
16+import Ormolu.Parser.Pragma
17+import Ormolu.Parser.Shebang
16import Ormolu.Printer.Combinators
18import Ormolu.Printer.Combinators
17import Ormolu.Printer.Comments
19import Ormolu.Printer.Comments
18import Ormolu.Printer.Meat.Common
20import Ormolu.Printer.Meat.Common
19import Ormolu.Printer.Meat.Declaration
21import Ormolu.Printer.Meat.Declaration
20import Ormolu.Printer.Meat.Declaration.Warning
22import Ormolu.Printer.Meat.Declaration.Warning
21import Ormolu.Printer.Meat.ImportExport
23import Ormolu.Printer.Meat.ImportExport
22−import Ormolu.Printer.Meat.LanguagePragma
24+import Ormolu.Printer.Meat.Pragma
23−import SrcLoc (combineSrcSpans)
24
25
25−p_hsModule :: Set String -> ParsedSource -> R ()
26+-- | Render a module.
26−p_hsModule exts loc@(L moduleSpan hsModule) = do
27+p_hsModule ::
27− -- NOTE If span of exports in multiline, the whole thing is multiline.
28+ -- | Stack header
28− -- This is especially important because span of module itself always seems
29+ Maybe (RealLocated Comment) ->
29− -- to have length zero, so it's not reliable for layout selection.
30+ -- | Shebangs
30− let spn =
31+ [Shebang] ->
31− case hsmodExports hsModule of
32+ -- | Pragmas and the associated comments
32− Nothing -> moduleSpan
33+ [([RealLocated Comment], Pragma)] ->
33− Just (L exportsSpan _) -> combineSrcSpans moduleSpan exportsSpan
34+ -- | Whether to use postfix qualified imports
34− locatedVia (Just spn) loc $ \HsModule {..} -> do
35+ Bool ->
35− let hasLangPragmas = not (null exts)
36+ -- | AST to print
36− hasModuleHeader = isJust hsmodName
37+ HsModule GhcPs ->
37− hasImports = not (null hsmodImports)
38+ R ()
38− hasDecls = not (null hsmodDecls)
39+p_hsModule mstackHeader shebangs pragmas qualifiedPost HsModule {..} = do
39− p_langPragmas exts
40+ let deprecSpan = maybe [] (\(L s _) -> [s]) hsmodDeprecMessage
40− when (hasLangPragmas &&
41+ exportSpans = maybe [] (\(L s _) -> [s]) hsmodExports
41− (hasModuleHeader || hasImports || hasDecls)) $
42+ switchLayout (deprecSpan <> exportSpans) $ 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
42 newline
49 newline
50+ newline
51+ p_pragmas pragmas
52+ newline
43 case hsmodName of
53 case hsmodName of
44− Nothing -> pure ()
54+ Nothing -> return ()
45− Just hsmodName' -> line $ do
55+ Just hsmodName' -> do
46− located hsmodName' p_hsmodName
56+ located hsmodName' $ \name -> do
47− forM_ hsmodDeprecMessage (located' p_moduleWarning)
57+ forM_ hsmodHaddockModHeader (p_hsDocString Pipe True)
58+ p_hsmodName name
59+ breakpoint
60+ forM_ hsmodDeprecMessage $ \w -> do
61+ located' p_moduleWarning w
62+ breakpoint
48 case hsmodExports of
63 case hsmodExports of
49 Nothing -> return ()
64 Nothing -> return ()
50− Just hsmodExports' -> do
65+ Just l -> do
66+ located l $ \exports -> do
67+ inci (p_hsmodExports exports)
51 breakpoint
68 breakpoint
52− inci (locatedVia Nothing hsmodExports' p_hsmodExports)
53− breakpoint
54 txt "where"
69 txt "where"
55− when (hasImports || hasDecls) newline
70+ newline
56− forM_ (sortImports hsmodImports) (located' p_hsmodImport)
71+ newline
57− when (hasImports && hasDecls) newline
72+ forM_ (normalizeImports hsmodImports) (located' (p_hsmodImport qualifiedPost))
58− p_hsDecls Free hsmodDecls
73+ newline
59− trailingComments <- hasMoreComments
74+ switchLayout (getLoc <$> hsmodDecls) $ do
60− when (trailingComments && hasModuleHeader) newline
75+ p_hsDecls Free hsmodDecls
61− spitRemainingComments
76+ newline
77+ spitRemainingComments
src/Ormolu/Printer/Meat/Pragma.hsnew file+91
@@ -0,0 +1,91 @@
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE TupleSections #-}
4+
5+-- | Pretty-printing of language pragmas.
6+module Ormolu.Printer.Meat.Pragma
7+ ( p_pragmas,
8+ )
9+where
10+
11+import Control.Monad
12+import Data.Char (isUpper)
13+import qualified Data.List as L
14+import Data.Maybe (listToMaybe)
15+import qualified Data.Text as T
16+import Ormolu.Parser.CommentStream
17+import Ormolu.Parser.Pragma (Pragma (..))
18+import Ormolu.Printer.Combinators
19+import Ormolu.Printer.Comments
20+import SrcLoc
21+
22+-- | Pragma classification.
23+data PragmaTy
24+ = Language LanguagePragmaClass
25+ | OptionsGHC
26+ | OptionsHaddock
27+ deriving (Eq, Ord)
28+
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 ()
51+p_pragmas ps = do
52+ let prepare = L.sortOn snd . L.nub . concatMap analyze
53+ analyze = \case
54+ (cs, PragmaLanguage xs) ->
55+ let f x = (cs, (Language (classifyLanguagePragma x), x))
56+ in f <$> xs
57+ (cs, PragmaOptionsGHC x) -> [(cs, (OptionsGHC, x))]
58+ (cs, PragmaOptionsHaddock x) -> [(cs, (OptionsHaddock, x))]
59+ forM_ (prepare ps) $ \(cs, (pragmaTy, x)) ->
60+ p_pragma cs pragmaTy x
61+
62+p_pragma :: [RealLocated Comment] -> PragmaTy -> String -> R ()
63+p_pragma comments ty x = do
64+ forM_ comments $ \(L l comment) -> do
65+ spitCommentNow l comment
66+ newline
67+ txt "{-# "
68+ txt $ case ty of
69+ Language _ -> "LANGUAGE"
70+ OptionsGHC -> "OPTIONS_GHC"
71+ OptionsHaddock -> "OPTIONS_HADDOCK"
72+ space
73+ txt (T.pack x)
74+ txt " #-}"
75+ 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+212−96
@@ -1,159 +1,275 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
4
4
5-- | Rendering of types.
5-- | Rendering of types.
6−
7module Ormolu.Printer.Meat.Type
6module Ormolu.Printer.Meat.Type
8− ( p_hsType
7+ ( p_hsType,
9− , p_hsContext
8+ p_hsTypePostDoc,
10− , p_hsTyVarBndr
9+ hasDocStrings,
11− , p_conDeclFields
10+ p_hsContext,
12− , tyVarsToTypes
11+ p_hsTyVarBndr,
12+ p_forallBndrs,
13+ p_conDeclFields,
14+ tyVarsToTypes,
13 )
15 )
14where
16where
15
17
16−import GHC
18+import Data.Data (Data)
19+import GHC hiding (isPromoted)
17import Ormolu.Printer.Combinators
20import Ormolu.Printer.Combinators
18import Ormolu.Printer.Meat.Common
21import Ormolu.Printer.Meat.Common
22+import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration.Value (p_hsSplice, p_stringLit)
23+import Ormolu.Printer.Operators
19import Ormolu.Utils
24import Ormolu.Utils
20
25
21p_hsType :: HsType GhcPs -> R ()
26p_hsType :: HsType GhcPs -> R ()
22−p_hsType = \case
27+p_hsType t = p_hsType' (hasDocStrings t) PipeStyle t
23− HsForAllTy NoExt bndrs t -> do
28+
24− txt "forall "
29+p_hsTypePostDoc :: HsType GhcPs -> R ()
25− spaceSep (located' p_hsTyVarBndr) bndrs
30+p_hsTypePostDoc t = p_hsType' (hasDocStrings t) CaretStyle t
26− txt ". "
31+
27− locatedVia Nothing t p_hsType
32+-- | How to render Haddocks associated with a type.
28− HsQualTy NoExt qs t -> do
33+data TypeDocStyle
34+ = PipeStyle
35+ | CaretStyle
36+
37+p_hsType' :: Bool -> TypeDocStyle -> HsType GhcPs -> R ()
38+p_hsType' multilineArgs docStyle = \case
39+ HsForAllTy NoExtField visibility bndrs t -> do
40+ p_forallBndrs visibility p_hsTyVarBndr bndrs
41+ interArgBreak
42+ p_hsTypeR (unLoc t)
43+ HsQualTy NoExtField qs t -> do
29 located qs p_hsContext
44 located qs p_hsContext
30− breakpoint
45+ space
31− txt "=> "
46+ txt "=>"
47+ interArgBreak
32 case unLoc t of
48 case unLoc t of
33− HsQualTy {} -> locatedVia Nothing t p_hsType
49+ HsQualTy {} -> p_hsTypeR (unLoc t)
34− HsFunTy {} -> locatedVia Nothing t p_hsType
50+ HsFunTy {} -> p_hsTypeR (unLoc t)
35− _ -> located t p_hsType
51+ _ -> located t p_hsTypeR
36− HsTyVar NoExt p n -> do
52+ HsTyVar NoExtField p n -> do
37 case p of
53 case p of
38− Promoted -> txt "'"
54+ IsPromoted -> do
55+ txt "'"
56+ case showOutputable (unLoc n) of
57+ _ : '\'' : _ -> space
58+ _ -> return ()
39 NotPromoted -> return ()
59 NotPromoted -> return ()
40 p_rdrName n
60 p_rdrName n
41− HsAppTy NoExt f x -> sitcc $ do
61+ HsAppTy NoExtField f x -> do
42− located f p_hsType
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
43 breakpoint
80 breakpoint
44− inci (located x p_hsType)
81+ inci $ do
45− HsFunTy NoExt x y@(L _ y') -> do
82+ txt "@"
83+ located kd p_hsType
84+ HsFunTy NoExtField x y@(L _ y') -> do
46 located x p_hsType
85 located x p_hsType
47− breakpoint
86+ space
48− txt "-> "
87+ txt "->"
88+ interArgBreak
49 case y' of
89 case y' of
50− HsFunTy{} -> p_hsType y'
90+ HsFunTy {} -> p_hsTypeR y'
51− _ -> located y p_hsType
91+ _ -> located y p_hsTypeR
52− HsListTy NoExt t -> located t (brackets . p_hsType)
92+ HsListTy NoExtField t ->
53− HsTupleTy NoExt tsort xs ->
93+ located t (brackets N . p_hsType)
94+ HsTupleTy NoExtField tsort xs ->
54 let parens' =
95 let parens' =
55 case tsort of
96 case tsort of
56− HsUnboxedTuple -> parensHash
97+ HsUnboxedTuple -> parensHash N
57− HsBoxedTuple -> parens
98+ HsBoxedTuple -> parens N
58− HsConstraintTuple -> parens
99+ HsConstraintTuple -> parens N
59− HsBoxedOrConstraintTuple -> parens
100+ HsBoxedOrConstraintTuple -> parens N
60− in parens' . velt $ withSep comma (located' p_hsType) xs
101+ in parens' $ sep commaDel (sitcc . located' p_hsType) xs
61− HsSumTy NoExt xs ->
102+ HsSumTy NoExtField xs ->
62− parensHash . velt $ withSep (txt "| ") (located' p_hsType) xs
103+ parensHash N $
63− HsOpTy NoExt x op y -> do
104+ sep (txt "|" >> breakpoint) (sitcc . located' p_hsType) xs
64− located x p_hsType
105+ HsOpTy NoExtField x op y ->
65− breakpoint
106+ sitcc $
66− inci $ do
107+ let opTree = OpBranch (tyOpTree x) op (tyOpTree y)
67− p_rdrName op
108+ in p_tyOpTree (reassociateOpTree Just opTree)
68− space
109+ HsParTy NoExtField t ->
69− located y p_hsType
110+ parens N (located t p_hsType)
70− HsParTy NoExt t ->
111+ HsIParamTy NoExtField n t -> sitcc $ do
71− parens (located t p_hsType)
72− HsIParamTy NoExt n t -> sitcc $ do
73 located n atom
112 located n atom
113+ space
114+ txt "::"
74 breakpoint
115 breakpoint
75− inci $ do
116+ inci (located t p_hsType)
76− txt ":: "
117+ HsStarTy NoExtField _ -> txt "*"
77− located t p_hsType
118+ HsKindSig NoExtField t k -> sitcc $ do
78− HsStarTy NoExt _ -> txt "*"
79− HsKindSig NoExt t k -> sitcc $ do
80 located t p_hsType
119 located t p_hsType
81− space -- FIXME
120+ space
82− inci $ do
121+ txt "::"
83− txt ":: "
122+ breakpoint
84− located k p_hsType
123+ inci (located k p_hsType)
85− HsSpliceTy _ _ -> error "HsSpliceTy"
124+ HsSpliceTy NoExtField splice -> p_hsSplice splice
86− HsDocTy NoExt _ _ -> error "HsDocTy"
125+ HsDocTy NoExtField t str ->
87− HsBangTy NoExt (HsSrcBang _ u s) t -> do
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
88 case u of
135 case u of
89− SrcUnpack -> txt "{-# UNPACK #-} "
136+ SrcUnpack -> txt "{-# UNPACK #-}" >> space
90− SrcNoUnpack -> txt "{-# NOUNPACK #-} "
137+ SrcNoUnpack -> txt "{-# NOUNPACK #-}" >> space
91 NoSrcUnpack -> return ()
138 NoSrcUnpack -> return ()
92 case s of
139 case s of
93 SrcLazy -> txt "~"
140 SrcLazy -> txt "~"
94 SrcStrict -> txt "!"
141 SrcStrict -> txt "!"
95 NoSrcStrict -> return ()
142 NoSrcStrict -> return ()
96 located t p_hsType
143 located t p_hsType
97− HsRecTy NoExt fields ->
144+ HsRecTy NoExtField fields ->
98 p_conDeclFields fields
145 p_conDeclFields fields
99− HsExplicitListTy NoExt p xs -> do
146+ HsExplicitListTy NoExtField p xs -> do
100 case p of
147 case p of
101− Promoted -> txt "'"
148+ IsPromoted -> txt "'"
102 NotPromoted -> return ()
149 NotPromoted -> return ()
103− brackets . velt $ withSep comma (located' p_hsType) xs
150+ brackets N $ do
104− HsExplicitTupleTy NoExt xs -> do
151+ -- 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.
153+ case (p, xs) of
154+ (IsPromoted, L _ t : _) | isPromoted t -> space
155+ _ -> return ()
156+ sep commaDel (sitcc . located' p_hsType) xs
157+ HsExplicitTupleTy NoExtField xs -> do
105 txt "'"
158 txt "'"
106− parens . velt $ withSep comma (located' p_hsType) xs
159+ parens N $ do
107− HsTyLit NoExt t -> atom t
160+ case xs of
108− HsWildCardTy NoExt -> txt "_"
161+ L _ t : _ | isPromoted t -> space
162+ _ -> return ()
163+ sep commaDel (located' p_hsType) xs
164+ HsTyLit NoExtField t ->
165+ case t of
166+ HsStrTy (SourceText s) _ -> p_stringLit s
167+ a -> atom a
168+ HsWildCardTy NoExtField -> txt "_"
109 XHsType (NHsCoreTy t) -> atom t
169 XHsType (NHsCoreTy t) -> atom t
170+ where
171+ isPromoted = \case
172+ HsTyVar _ IsPromoted _ -> True
173+ HsExplicitTupleTy {} -> True
174+ HsExplicitListTy {} -> True
175+ _ -> False
176+ interArgBreak =
177+ if multilineArgs
178+ then newline
179+ else breakpoint
180+ p_hsTypeR = p_hsType' multilineArgs docStyle
181+
182+-- | Return 'True' if at least one argument in 'HsType' has a doc string
183+-- attached to it.
184+hasDocStrings :: HsType GhcPs -> Bool
185+hasDocStrings = \case
186+ HsDocTy {} -> True
187+ HsFunTy _ (L _ x) (L _ y) -> hasDocStrings x || hasDocStrings y
188+ _ -> False
110
189
111p_hsContext :: HsContext GhcPs -> R ()
190p_hsContext :: HsContext GhcPs -> R ()
112p_hsContext = \case
191p_hsContext = \case
113 [] -> txt "()"
192 [] -> txt "()"
114 [x] -> located x p_hsType
193 [x] -> located x p_hsType
115− xs -> parens . velt $ withSep comma (located' p_hsType) xs
194+ xs -> parens N $ sep commaDel (sitcc . located' p_hsType) xs
116
195
117p_hsTyVarBndr :: HsTyVarBndr GhcPs -> R ()
196p_hsTyVarBndr :: HsTyVarBndr GhcPs -> R ()
118p_hsTyVarBndr = \case
197p_hsTyVarBndr = \case
119− UserTyVar NoExt x ->
198+ UserTyVar NoExtField x ->
120 p_rdrName x
199 p_rdrName x
121− KindedTyVar NoExt l k -> parens $ do
200+ KindedTyVar NoExtField l k -> parens N $ do
122 located l atom
201 located l atom
202+ space
203+ txt "::"
204+ breakpoint
205+ inci (located k p_hsType)
206+ XTyVarBndr x -> noExtCon x
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"
123 breakpoint
215 breakpoint
124 inci $ do
216 inci $ do
125− txt ":: "
217+ sitcc $ sep breakpoint (sitcc . located' p) tyvars
126− located k p_hsType
218+ case vis of
127− XTyVarBndr NoExt -> notImplemented "XTyVarBndr"
219+ ForallInvis -> txt "."
220+ ForallVis -> space >> txt "->"
128
221
129p_conDeclFields :: [LConDeclField GhcPs] -> R ()
222p_conDeclFields :: [LConDeclField GhcPs] -> R ()
130−p_conDeclFields =
223+p_conDeclFields xs =
131− braces . velt . withSep comma (sitcc . located' p_conDeclField)
224+ braces N $ sep commaDel (sitcc . located' p_conDeclField) xs
132
225
133p_conDeclField :: ConDeclField GhcPs -> R ()
226p_conDeclField :: ConDeclField GhcPs -> R ()
134p_conDeclField ConDeclField {..} = do
227p_conDeclField ConDeclField {..} = do
135− sitcc . velt $ withSep
228+ mapM_ (p_hsDocString Pipe True) cd_fld_doc
136− comma
229+ sitcc $
137− (located' (p_rdrName . rdrNameFieldOcc))
230+ sep
138− cd_fld_names
231+ commaDel
232+ (located' (p_rdrName . rdrNameFieldOcc))
233+ cd_fld_names
234+ space
235+ txt "::"
236+ breakpoint
237+ sitcc . inci $ p_hsType (unLoc cd_fld_type)
238+p_conDeclField (XConDeclField x) = noExtCon x
239+
240+tyOpTree :: LHsType GhcPs -> OpTree (LHsType GhcPs) (Located RdrName)
241+tyOpTree (L _ (HsOpTy NoExtField l op r)) =
242+ OpBranch (tyOpTree l) op (tyOpTree r)
243+tyOpTree n = OpNode n
244+
245+p_tyOpTree :: OpTree (LHsType GhcPs) (Located RdrName) -> R ()
246+p_tyOpTree (OpNode n) = located n p_hsType
247+p_tyOpTree (OpBranch l op r) = do
248+ switchLayout [opTreeLoc l] $
249+ p_tyOpTree l
139 breakpoint
250 breakpoint
140− sitcc . inci $ do
251+ inci . switchLayout [opTreeLoc r] $ do
141− txt ":: "
252+ p_rdrName op
142− locatedVia Nothing cd_fld_type p_hsType
253+ space
143−p_conDeclField (XConDeclField NoExt) = notImplemented "XConDeclField"
254+ p_tyOpTree r
144
255
145----------------------------------------------------------------------------
256----------------------------------------------------------------------------
146−-- Convertion functions
257+-- Conversion functions
147
258
148tyVarsToTypes :: LHsQTyVars GhcPs -> [LHsType GhcPs]
259tyVarsToTypes :: LHsQTyVars GhcPs -> [LHsType GhcPs]
149tyVarsToTypes = \case
260tyVarsToTypes = \case
150− HsQTvs {..} -> fmap tyVarToType <$> hsq_explicit
261+ HsQTvs {..} -> fmap tyVarToType <$> hsq_explicit
151− XLHsQTyVars {} -> notImplemented "XLHsQTyVars"
262+ XLHsQTyVars x -> noExtCon x
152
263
153tyVarToType :: HsTyVarBndr GhcPs -> HsType GhcPs
264tyVarToType :: HsTyVarBndr GhcPs -> HsType GhcPs
154tyVarToType = \case
265tyVarToType = \case
155− UserTyVar NoExt tvar -> HsTyVar NoExt NotPromoted tvar
266+ UserTyVar NoExtField tvar -> HsTyVar NoExtField NotPromoted tvar
156− KindedTyVar NoExt tvar kind ->
267+ KindedTyVar NoExtField tvar kind ->
157− HsParTy NoExt $ noLoc $
268+ -- Note: we always add parentheses because for whatever reason GHC does
158− HsKindSig NoExt (noLoc (HsTyVar NoExt NotPromoted tvar)) kind
269+ -- not use HsParTy for left-hand sides of declarations. Please see
159− XTyVarBndr {} -> notImplemented "XTyVarBndr"
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
275+ XTyVarBndr x -> noExtCon x
src/Ormolu/Printer/Operators.hsnew file+177
@@ -0,0 +1,177 @@
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE ScopedTypeVariables #-}
3+
4+-- | This module helps handle operator chains composed of different
5+-- operators that may have different precedence and fixities.
6+module Ormolu.Printer.Operators
7+ ( OpTree (..),
8+ opTreeLoc,
9+ reassociateOpTree,
10+ )
11+where
12+
13+import Data.Function (on)
14+import qualified Data.List as L
15+import Data.Map.Strict (Map)
16+import qualified Data.Map.Strict as M
17+import Data.Maybe (fromMaybe, mapMaybe)
18+import GHC
19+import OccName (occNameString)
20+import Ormolu.Utils (unSrcSpan)
21+
22+-- | Intermediate representation of operator trees. It has two type
23+-- parameters: @ty@ is the type of sub-expressions, while @op@ is the type
24+-- of operators.
25+data OpTree ty op
26+ = OpNode ty
27+ | OpBranch
28+ (OpTree ty op)
29+ op
30+ (OpTree ty op)
31+
32+-- | Return combined 'SrcSpan's of all elements in this 'OpTree'.
33+opTreeLoc :: OpTree (Located a) b -> SrcSpan
34+opTreeLoc (OpNode (L l _)) = l
35+opTreeLoc (OpBranch l _ r) = combineSrcSpans (opTreeLoc l) (opTreeLoc r)
36+
37+-- | Re-associate an 'OpTree' taking into account automagically inferred
38+-- relative precedence of operators. Users are expected to first construct
39+-- an initial 'OpTree', then re-associate it using this function before
40+-- printing.
41+reassociateOpTree ::
42+ -- | How to get name of an operator
43+ (op -> Maybe RdrName) ->
44+ -- | Original 'OpTree'
45+ OpTree (Located ty) (Located op) ->
46+ -- | Re-associated 'OpTree'
47+ OpTree (Located ty) (Located op)
48+reassociateOpTree getOpName opTree =
49+ reassociateOpTreeWith
50+ (buildFixityMap getOpName normOpTree)
51+ (getOpName . unLoc)
52+ normOpTree
53+ where
54+ normOpTree = normalizeOpTree opTree
55+
56+-- | Re-associate an 'OpTree' given the map with operator fixities.
57+reassociateOpTreeWith ::
58+ forall ty op.
59+ -- | Fixity map for operators
60+ Map String Fixity ->
61+ -- | How to get the name of an operator
62+ (op -> Maybe RdrName) ->
63+ -- | Original 'OpTree'
64+ OpTree ty op ->
65+ -- | Re-associated 'OpTree'
66+ OpTree ty op
67+reassociateOpTreeWith fixityMap getOpName = go
68+ where
69+ fixityOf :: op -> Fixity
70+ fixityOf op = fromMaybe defaultFixity $ do
71+ s <- occNameString . rdrNameOcc <$> getOpName op
72+ M.lookup s fixityMap
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
75+ -- from the right and inserts it correctly to the left.
76+ --
77+ -- Also, we are using the 'compareFixity' function which tells if the
78+ -- expression should associate to right.
79+ go :: OpTree ty op -> OpTree ty op
80+ -- base cases
81+ go t@(OpNode _) = t
82+ go t@(OpBranch (OpNode _) _ (OpNode _)) = t
83+ -- shift one operator to the left at the beginning
84+ go (OpBranch l@(OpNode _) op (OpBranch l' op' r')) =
85+ go (OpBranch (OpBranch l op l') op' r')
86+ -- at the last operator, place the operator and don't recurse
87+ go (OpBranch (OpBranch l op r) op' r'@(OpNode _)) =
88+ if snd $ compareFixity (fixityOf op) (fixityOf op')
89+ then OpBranch l op (go $ OpBranch r op' r')
90+ else OpBranch (OpBranch l op r) op' r'
91+ -- else, shift one operator to left and recurse.
92+ go (OpBranch (OpBranch l op r) op' (OpBranch l' op'' r')) =
93+ if snd $ compareFixity (fixityOf op) (fixityOf op')
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'
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'.
108+buildFixityMap ::
109+ forall ty op.
110+ -- | How to get the name of an operator
111+ (op -> Maybe RdrName) ->
112+ -- | Operator tree
113+ OpTree (Located ty) (Located op) ->
114+ -- | Fixity map
115+ Map String Fixity
116+buildFixityMap getOpName opTree =
117+ addOverrides
118+ . M.fromList
119+ . concatMap (\(i, ns) -> map (\(n, _) -> (n, fixity i InfixL)) ns)
120+ . zip [2 ..]
121+ . L.groupBy ((==) `on` snd)
122+ . selectScores
123+ $ score opTree
124+ where
125+ addOverrides :: Map String Fixity -> Map String Fixity
126+ addOverrides m =
127+ M.fromList
128+ [ ("$", fixity 0 InfixR),
129+ (":", fixity 1 InfixR),
130+ (".", fixity 100 InfixL)
131+ ]
132+ `M.union` m
133+ fixity = Fixity NoSourceText
134+ score :: OpTree (Located ty) (Located op) -> [(String, Score)]
135+ score (OpNode _) = []
136+ score (OpBranch l o r) = fromMaybe (score r) $ do
137+ -- If we fail to get any of these, 'defaultFixity' will be used by
138+ -- 'reassociateOpTreeWith'.
139+ le <- srcSpanEndLine <$> unSrcSpan (opTreeLoc l) -- left end
140+ ob <- srcSpanStartLine <$> unSrcSpan (getLoc o) -- operator begin
141+ oe <- srcSpanEndLine <$> unSrcSpan (getLoc o) -- operator end
142+ rb <- srcSpanStartLine <$> unSrcSpan (opTreeLoc r) -- right begin
143+ oc <- srcSpanStartCol <$> unSrcSpan (getLoc o) -- operator column
144+ opName <- occNameString . rdrNameOcc <$> getOpName (unLoc o)
145+ let s
146+ | le < ob = AtBeginning oc
147+ | oe < rb = AtEnd
148+ | otherwise = InBetween
149+ return $ (opName, s) : score r
150+ selectScores :: [(String, Score)] -> [(String, Score)]
151+ selectScores =
152+ L.sortOn snd
153+ . mapMaybe
154+ ( \case
155+ [] -> Nothing
156+ xs@((n, _) : _) -> Just (n, selectScore $ map snd xs)
157+ )
158+ . L.groupBy ((==) `on` fst)
159+ . L.sort
160+ selectScore :: [Score] -> Score
161+ selectScore xs =
162+ case filter (/= InBetween) xs of
163+ [] -> InBetween
164+ xs' -> maximum xs'
165+
166+----------------------------------------------------------------------------
167+-- Helpers
168+
169+-- | Convert an 'OpTree' to with all operators having the same fixity and
170+-- associativity (left infix).
171+normalizeOpTree :: OpTree ty op -> OpTree ty op
172+normalizeOpTree (OpNode n) =
173+ OpNode n
174+normalizeOpTree (OpBranch (OpNode l) lop r) =
175+ OpBranch (OpNode l) lop (normalizeOpTree r)
176+normalizeOpTree (OpBranch (OpBranch l' lop' r') lop r) =
177+ normalizeOpTree (OpBranch l' lop' (OpBranch r' lop r))
src/Ormolu/Printer/SpanStream.hs+18−20
@@ -1,46 +1,44 @@
1−{-# LANGUAGE DeriveDataTypeable #-}
1+{-# LANGUAGE DeriveDataTypeable #-}
2{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3
3
4-- | Build span stream from AST.
4-- | Build span stream from AST.
5−
6module Ormolu.Printer.SpanStream
5module Ormolu.Printer.SpanStream
7− ( SpanStream (..)
6+ ( SpanStream (..),
8− , mkSpanStream
7+ mkSpanStream,
9 )
8 )
10where
9where
11
10
12import Data.DList (DList)
11import Data.DList (DList)
12+import qualified Data.DList as D
13import Data.Data (Data)
13import Data.Data (Data)
14import Data.Generics (everything, ext2Q)
14import Data.Generics (everything, ext2Q)
15import Data.List (sortOn)
15import Data.List (sortOn)
16import Data.Typeable (cast)
16import Data.Typeable (cast)
17import SrcLoc
17import SrcLoc
18−import qualified Data.DList as D
19
18
20-- | A stream of 'RealSrcSpan's in ascending order. This allows us to tell
19-- | A stream of 'RealSrcSpan's in ascending order. This allows us to tell
21-- e.g. whether there is another \"located\" element of AST between current
20-- e.g. whether there is another \"located\" element of AST between current
22-- element and comment we're considering for printing.
21-- element and comment we're considering for printing.
23−
24newtype SpanStream = SpanStream [RealSrcSpan]
22newtype SpanStream = SpanStream [RealSrcSpan]
25 deriving (Eq, Show, Data, Semigroup, Monoid)
23 deriving (Eq, Show, Data, Semigroup, Monoid)
26
24
27-- | Create 'SpanStream' from a data structure containing \"located\"
25-- | Create 'SpanStream' from a data structure containing \"located\"
28-- elements.
26-- elements.
29−
27+mkSpanStream ::
30−mkSpanStream
28+ Data a =>
31− :: Data a
29+ -- | Data structure to inspect (AST)
32− => a -- ^ Data structure to inspect (AST)
30+ a ->
33− -> SpanStream
31+ SpanStream
34−mkSpanStream a
32+mkSpanStream a =
35− = SpanStream
33+ SpanStream
36− . sortOn realSrcSpanStart
34+ . sortOn realSrcSpanStart
37− . D.toList
35+ . D.toList
38− $ everything mappend (const mempty `ext2Q` queryLocated) a
36+ $ everything mappend (const mempty `ext2Q` queryLocated) a
39 where
37 where
40− queryLocated
38+ queryLocated ::
41− :: (Data e0, Data e1)
39+ (Data e0) =>
42− => GenLocated e0 e1
40+ GenLocated e0 e1 ->
43− -> DList RealSrcSpan
41+ DList RealSrcSpan
44 queryLocated (L mspn _) =
42 queryLocated (L mspn _) =
45 case cast mspn :: Maybe SrcSpan of
43 case cast mspn :: Maybe SrcSpan of
46 Nothing -> mempty
44 Nothing -> mempty
src/Ormolu/Processing/Common.hsnew file+27
@@ -0,0 +1,27 @@
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.hsnew file+70
@@ -0,0 +1,70 @@
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.hsnew file+31
@@ -0,0 +1,31 @@
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.hsnew file+149
@@ -0,0 +1,149 @@
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+138−17
@@ -1,34 +1,155 @@
1−-- | Random utilities used by the code.
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE ViewPatterns #-}
2
4
5+-- | Random utilities used by the code.
3module Ormolu.Utils
6module Ormolu.Utils
4− ( combineSrcSpans'
7+ ( RelativePos (..),
5− , isModule
8+ attachRelativePos,
6− , notImplemented
9+ combineSrcSpans',
7− , showOutputable
10+ notImplemented,
11+ showOutputable,
12+ splitDocString,
13+ typeArgToType,
14+ unSrcSpan,
15+ incSpanLine,
16+ separatedByBlank,
17+ separatedByBlankNE,
18+ onTheSameLine,
19+ removeIndentation,
8 )
20 )
9where
21where
10
22
11−import Data.Data (Data, showConstr, toConstr)
23+import Data.Char (isSpace)
24+import Data.List (dropWhileEnd)
12import Data.List.NonEmpty (NonEmpty (..))
25import Data.List.NonEmpty (NonEmpty (..))
13−import SrcLoc
26+import qualified Data.List.NonEmpty as NE
27+import Data.Maybe (fromMaybe)
28+import Data.Text (Text)
29+import qualified Data.Text as T
30+import GHC
31+import GHC.DynFlags (baseDynFlags)
14import qualified Outputable as GHC
32import qualified Outputable as GHC
15
33
16−-- | Combine all source spans from the given list.
34+-- | Relative positions in a list.
17−
35+data RelativePos
18−combineSrcSpans' :: NonEmpty SrcSpan -> SrcSpan
36+ = SinglePos
19−combineSrcSpans' (x:|xs) = foldr combineSrcSpans x xs
37+ | FirstPos
38+ | MiddlePos
39+ | LastPos
40+ deriving (Eq, Show)
20
41
21−-- | Return 'True' if given element of AST is module.
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
22
52
23−isModule :: Data a => a -> Bool
53+-- | Combine all source spans from the given list.
24−isModule x = showConstr (toConstr x) == "HsModule"
54+combineSrcSpans' :: NonEmpty SrcSpan -> SrcSpan
55+combineSrcSpans' (x :| xs) = foldr combineSrcSpans x xs
25
56
26-- | Placeholder for things that are not yet implemented.
57-- | Placeholder for things that are not yet implemented.
27−
28notImplemented :: String -> a
58notImplemented :: String -> a
29notImplemented msg = error $ "not implemented yet: " ++ msg
59notImplemented msg = error $ "not implemented yet: " ++ msg
30
60
31-- | Pretty-print an 'GHC.Outputable' thing.
61-- | Pretty-print an 'GHC.Outputable' thing.
32−
33showOutputable :: GHC.Outputable o => o -> String
62showOutputable :: GHC.Outputable o => o -> String
34−showOutputable = GHC.showSDocUnsafe . GHC.ppr
63+showOutputable = GHC.showSDoc baseDynFlags . GHC.ppr
64+
65+-- | Split and normalize a doc string. The result is a list of lines that
66+-- make up the comment.
67+splitDocString :: HsDocString -> [Text]
68+splitDocString docStr =
69+ case r of
70+ [] -> [""]
71+ _ -> r
72+ where
73+ r =
74+ fmap escapeLeadingDollar
75+ . dropPaddingSpace
76+ . dropWhileEnd T.null
77+ . fmap (T.stripEnd . T.pack)
78+ . lines
79+ $ unpackHDS docStr
80+ -- We cannot have the first character to be a dollar because in that
81+ -- case it'll be a parse error (apparently collides with named docs
82+ -- syntax @-- $name@ somehow).
83+ escapeLeadingDollar txt =
84+ case T.uncons txt of
85+ Just ('$', _) -> T.cons '\\' txt
86+ _ -> txt
87+ dropPaddingSpace xs =
88+ case dropWhile T.null xs of
89+ [] -> []
90+ (x : _) ->
91+ let leadingSpace txt = case T.uncons txt of
92+ Just (' ', _) -> True
93+ _ -> False
94+ dropSpace txt =
95+ if leadingSpace txt
96+ then T.drop 1 txt
97+ else txt
98+ in if leadingSpace x
99+ then dropSpace <$> xs
100+ 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/LanguagePragmaSpec.hsdeleted−22
@@ -1,22 +0,0 @@
1−module Ormolu.Parser.LanguagePragmaSpec (spec) where
2−
3−import Ormolu.Parser.LanguagePragma
4−import Test.Hspec
5−import qualified Data.Set as S
6−
7−spec :: Spec
8−spec = do
9− describe "parseLanguagePragma" $ do
10− stdTest "{-# LANGUAGE Foo #-}" (Just ["Foo"])
11− stdTest "{-# language Foo #-}" (Just ["Foo"])
12− stdTest "{-# lAngUAGe Foo #-}" (Just ["Foo"])
13− stdTest "{-# LANGUAGE Foo, Bar #-}" (Just ["Bar", "Foo"])
14− stdTest "{-# LANGUAGE Foo Bar #-}" Nothing
15− stdTest "{-# BOO Foo #-}" Nothing
16− stdTest "something" Nothing
17− stdTest "{-# LANGUAGE foo, Bar #-}" Nothing
18−
19−stdTest :: String -> Maybe [String] -> Spec
20−stdTest input result = it input $
21− (S.toAscList <$> parseLanguagePragma input) `shouldBe`
22− result
tests/Ormolu/Parser/PragmaSpec.hsnew file+26
@@ -0,0 +1,26 @@
1+module Ormolu.Parser.PragmaSpec (spec) where
2+
3+import Ormolu.Parser.Pragma
4+import Test.Hspec
5+
6+spec :: Spec
7+spec =
8+ describe "parsePragma" $ do
9+ stdTest "{-# LANGUAGE Foo #-}" (Just (PragmaLanguage ["Foo"]))
10+ stdTest "{-# language Foo #-}" (Just (PragmaLanguage ["Foo"]))
11+ stdTest "{-#LANGUAGE Foo#-}" (Just (PragmaLanguage ["Foo"]))
12+ stdTest "{-# LANGUAGE Foo#-}" (Just (PragmaLanguage ["Foo"]))
13+ stdTest "{-#language Foo#-}" (Just (PragmaLanguage ["Foo"]))
14+ stdTest "{-# lAngUAGe Foo #-}" (Just (PragmaLanguage ["Foo"]))
15+ stdTest "{-# LANGUAGE Foo, Bar #-}" (Just (PragmaLanguage ["Foo", "Bar"]))
16+ stdTest "{-# LANGUAGE Foo Bar #-}" Nothing
17+ stdTest "{-# BOO Foo #-}" Nothing
18+ stdTest "something" Nothing
19+ stdTest "{-# LANGUAGE foo, Bar #-}" Nothing
20+ stdTest "{-# OPTIONS_GHC foo bar baz #-}" (Just $ PragmaOptionsGHC "foo bar baz")
21+ stdTest "{-#OPTIONS_HADDOCK foo, bar, baz #-}" (Just $ PragmaOptionsHaddock "foo, bar, baz")
22+
23+stdTest :: String -> Maybe Pragma -> Spec
24+stdTest input result =
25+ it input $
26+ parsePragma input `shouldBe` result
tests/Ormolu/Printer/CombinatorsSpec.hsdeleted−110
@@ -1,110 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−
3−module Ormolu.Printer.CombinatorsSpec (spec) where
4−
5−import Ormolu.Parser.Anns
6−import Ormolu.Printer.Combinators
7−import Ormolu.Printer.Internal
8−import Test.Hspec
9−import qualified Data.Text.IO as T
10−
11−-- NOTE Testing combinators in separation is easy, but it's not very useful
12−-- either because interesting things happen only when combinators are used
13−-- together. However, there are too many combinations to test, so we test
14−-- just a few things here and expect new tests to be added on demand when
15−-- particularly tricky or problematic use cases are discovered.
16−--
17−-- The printing logic is indirectly tested in the main bulk of reformatting
18−-- tests.
19−
20−spec :: Spec
21−spec = do
22− stdTest "simple signature" rSimpleSig "ssig"
23− stdTest "list" rList0 "list0"
24− stdTest "list with annotated name in it" rList1 "list1"
25− stdTest "module header" rModuleHeader "mhdr"
26−
27−-- | Do a standard test prodedure testing both single-line and multi-line
28−-- layouts.
29−
30−stdTest
31− :: String -- ^ Test name
32− -> R () -- ^ Computation to test
33− -> FilePath -- ^ Base file name where expected result is stored
34− -> Spec
35−stdTest name m path = describe name $ do
36− let spath = "data/printer/" ++ path ++ "-single.hs"
37− mpath = "data/printer/" ++ path ++ "-multi.hs"
38− it "single-line works" $
39− singleLine m `shouldRender` spath
40− it "multi-line works" $
41− multiLine m `shouldRender` mpath
42−
43−----------------------------------------------------------------------------
44−-- Test computations
45−
46−rSimpleSig :: R ()
47−rSimpleSig = line rFn
48−
49−rList0 :: R ()
50−rList0 = line . brackets $
51− velt
52− [ txt "foo"
53− , comma >> txt "bar"
54− , comma >> txt "baz"
55− ]
56−
57−rList1 :: R ()
58−rList1 = line . brackets $
59− velt
60− [ txt "foo"
61− , comma >> txt "bar"
62− , comma >> rFn
63− ]
64−
65−rFn :: R ()
66−rFn = velt'
67− [ txt "foo"
68− , inci $ velt'
69− [ do txt ":: "
70− parens $ velt'
71− [ txt "Int"
72− , txt "-> " >> txt "Int"
73− ]
74− , txt "-> " >> txt "Bool"
75− ]
76− ]
77−
78−rModuleHeader :: R ()
79−rModuleHeader = do
80− line $ do
81− txt "module "
82− txt "MyModule"
83− line . inci . parens . velt $
84− [ txt "R"
85− , comma >> txt "runR"
86− , comma >> txt "txt"
87− , comma >> txt "blah"
88− ]
89− line (txt "where")
90−
91−----------------------------------------------------------------------------
92−-- Helpers
93−
94−-- | Run given computation in @'R' ()@ monad and compare result of rendering
95−-- with contents of a given file.
96−
97−shouldRender :: R () -> FilePath -> Expectation
98−shouldRender m path = do
99− expected <- T.readFile path
100− runR False m mempty mempty emptyAnns `shouldBe` expected
101−
102−-- | Render using single-line layout.
103−
104−singleLine :: R () -> R ()
105−singleLine = enterLayout SingleLine
106−
107−-- | Render using multi-line layout.
108−
109−multiLine :: R () -> R ()
110−multiLine = enterLayout MultiLine
tests/Ormolu/PrinterSpec.hs+32−22
@@ -2,17 +2,18 @@
2
2
3module Ormolu.PrinterSpec (spec) where
3module Ormolu.PrinterSpec (spec) where
4
4
5+import Control.Exception
5import Control.Monad
6import Control.Monad
6import Control.Monad.IO.Class
7import Control.Monad.IO.Class
7import Data.List (isSuffixOf)
8import Data.List (isSuffixOf)
8import Data.Text (Text)
9import Data.Text (Text)
10+import qualified Data.Text as T
11+import qualified Data.Text.IO as T
9import Ormolu
12import Ormolu
10import Path
13import Path
11import Path.IO
14import Path.IO
12−import System.FilePath (addExtension, dropExtensions, splitExtensions)
15+import qualified System.FilePath as F
13import Test.Hspec
16import Test.Hspec
14−import qualified Data.Text as T
15−import qualified Data.Text.IO as T
16
17
17spec :: Spec
18spec :: Spec
18spec = do
19spec = do
@@ -20,9 +21,8 @@ spec = do
20 forM_ es checkExample
21 forM_ es checkExample
21
22
22-- | Check a single given example.
23-- | Check a single given example.
23−
24checkExample :: Path Rel File -> Spec
24checkExample :: Path Rel File -> Spec
25−checkExample srcPath' = it (fromRelFile srcPath' ++ " works") $ do
25+checkExample srcPath' = it (fromRelFile srcPath' ++ " works") . withNiceExceptions $ do
26 let srcPath = examplesDir </> srcPath'
26 let srcPath = examplesDir </> srcPath'
27 expectedOutputPath <- deriveOutput srcPath
27 expectedOutputPath <- deriveOutput srcPath
28 -- 1. Given input snippet of source code parse it and pretty print it.
28 -- 1. Given input snippet of source code parse it and pretty print it.
@@ -32,6 +32,7 @@ checkExample srcPath' = it (fromRelFile srcPath' ++ " works") $ do
32 formatted0 <- ormoluFile defaultConfig (fromRelFile srcPath)
32 formatted0 <- ormoluFile defaultConfig (fromRelFile srcPath)
33 -- 3. Check the output against expected output. Thus all tests should
33 -- 3. Check the output against expected output. Thus all tests should
34 -- include two files: input and expected output.
34 -- include two files: input and expected output.
35+ -- T.writeFile (fromRelFile expectedOutputPath) formatted0
35 expected <- (liftIO . T.readFile . fromRelFile) expectedOutputPath
36 expected <- (liftIO . T.readFile . fromRelFile) expectedOutputPath
36 shouldMatch False formatted0 expected
37 shouldMatch False formatted0 expected
37 -- 4. Check that running the formatter on the output produces the same
38 -- 4. Check that running the formatter on the output produces the same
@@ -40,42 +41,51 @@ checkExample srcPath' = it (fromRelFile srcPath' ++ " works") $ do
40 shouldMatch True formatted1 formatted0
41 shouldMatch True formatted1 formatted0
41
42
42-- | Build list of examples for testing.
43-- | Build list of examples for testing.
43−
44locateExamples :: IO [Path Rel File]
44locateExamples :: IO [Path Rel File]
45locateExamples =
45locateExamples =
46 filter isInput . snd <$> listDirRecurRel examplesDir
46 filter isInput . snd <$> listDirRecurRel examplesDir
47
47
48-- | Does given path look like input path (as opposed to expected output
48-- | Does given path look like input path (as opposed to expected output
49-- path)?
49-- path)?
50−
51isInput :: Path Rel File -> Bool
50isInput :: Path Rel File -> Bool
52isInput path =
51isInput path =
53 let s = fromRelFile path
52 let s = fromRelFile path
54− (s', exts) = splitExtensions s
53+ (s', exts) = F.splitExtensions s
55− in exts == ".hs" && not ("-out" `isSuffixOf` s')
54+ in exts == ".hs" && not ("-out" `isSuffixOf` s')
56
55
57-- | For given path of input file return expected name of output.
56-- | For given path of input file return expected name of output.
58−
59deriveOutput :: Path Rel File -> IO (Path Rel File)
57deriveOutput :: Path Rel File -> IO (Path Rel File)
60−deriveOutput path = parseRelFile $
58+deriveOutput path =
61− addExtension (dropExtensions (fromRelFile path) ++ "-out") "hs"
59+ parseRelFile $
60+ F.addExtension (F.dropExtensions (fromRelFile path) ++ "-out") "hs"
62
61
63-- | A version of 'shouldBe' that is specialized to comparing 'Text' values.
62-- | A version of 'shouldBe' that is specialized to comparing 'Text' values.
64-- It also prints multi-line snippets in a more readable form.
63-- It also prints multi-line snippets in a more readable form.
65−
66shouldMatch :: Bool -> Text -> Text -> Expectation
64shouldMatch :: Bool -> Text -> Text -> Expectation
67−shouldMatch idempotencyTest actual expected =
65+shouldMatch idempotenceTest actual expected =
68− when (actual /= expected) . expectationFailure $ unlines
66+ when (actual /= expected) . expectationFailure $
69− [ ">>>>>>>>>>>>>>>>>>>>>> expected (" ++ pass ++ "):"
67+ unlines
70− , T.unpack expected
68+ [ ">>>>>>>>>>>>>>>>>>>>>> expected (" ++ pass ++ "):",
71− , ">>>>>>>>>>>>>>>>>>>>>> but got:"
69+ T.unpack expected,
72− , T.unpack actual
70+ ">>>>>>>>>>>>>>>>>>>>>> but got:",
73− ]
71+ T.unpack actual
72+ ]
74 where
73 where
75 pass =
74 pass =
76− if idempotencyTest
75+ if idempotenceTest
77− then "idempotency pass"
76+ then "idempotence pass"
78 else "first pass"
77 else "first pass"
79
78
80examplesDir :: Path Rel Dir
79examplesDir :: Path Rel Dir
81examplesDir = $(mkRelDir "data/examples")
80examplesDir = $(mkRelDir "data/examples")
81+
82+-- | Inside this wrapper 'OrmoluException' will be caught and displayed
83+-- nicely using 'displayException'.
84+withNiceExceptions ::
85+ -- | Action that may throw the exception
86+ Expectation ->
87+ Expectation
88+withNiceExceptions m = m `catch` h
89+ where
90+ h :: OrmoluException -> IO ()
91+ h = expectationFailure . displayException