on ca8cb04 help sign in
282 files changed+2094−4236
since splitsnapshots
unifiedsplit
.buildkite/pipeline.yml−18 .circleci/config.yml+49 .github/workflows/binaries.yml−39 .github/workflows/build.sh−7 CHANGELOG.md−155 CONTRIBUTING.md+1−1 DESIGN.md+11−11 README.md+13−57 app/Main.hs+95−133 data/examples/declaration/annotation/annotation-out.hs−1 data/examples/declaration/class/dependency-super-classes-out.hs+1−2 data/examples/declaration/class/functional-dependencies-out.hs+1−2 data/examples/declaration/class/multi-parameters2-out.hs+1−2 data/examples/declaration/data/existential-multiline-out.hs−12 data/examples/declaration/data/existential-multiline.hs−7 data/examples/declaration/data/field-layout/gadt-out.hs+1−2 data/examples/declaration/data/field-layout/record-out.hs+9−9 data/examples/declaration/data/gadt/multiline-out.hs+1−1 data/examples/declaration/data/gadt/multiline-where-out.hs−7 data/examples/declaration/data/gadt/multiline-where.hs−6 data/examples/declaration/data/multiline-arg-parens-out.hs+1−1 data/examples/declaration/data/partly-documented-out.hs−5 data/examples/declaration/data/partly-documented.hs−2 data/examples/declaration/data/record-multi-const-out.hs−17 data/examples/declaration/data/record-multi-const.hs−13 data/examples/declaration/data/record-out.hs+20−19 data/examples/declaration/data/simple-broken-out.hs+2−1 data/examples/declaration/data/unnamed-field-comment-0-out.hs−7 data/examples/declaration/data/unnamed-field-comment-0.hs−5 data/examples/declaration/data/unnamed-field-comment-1-out.hs−5 data/examples/declaration/data/unnamed-field-comment-1.hs−4 data/examples/declaration/data/with-comment-out.hs−4 data/examples/declaration/data/with-comment.hs−5 data/examples/declaration/data/with-weird-haddock-out.hs−4 data/examples/declaration/data/with-weird-haddock.hs−2 data/examples/declaration/instance/data-family-instances-gadt-out.hs+2−4 data/examples/declaration/instance/data-family-instances-newtype-out.hs+4−3 data/examples/declaration/signature/standalone-kind-out.hs−13 data/examples/declaration/signature/standalone-kind.hs−13 data/examples/declaration/signature/type/infix-promoted-type-constructor-out.hs+1 data/examples/declaration/signature/type/multi-value-out.hs−5 data/examples/declaration/signature/type/multi-value.hs−5 data/examples/declaration/signature/type/unrelated-out.hs−4 data/examples/declaration/signature/type/unrelated.hs−4 data/examples/declaration/splice/grouped-splices-out.hs−3 data/examples/declaration/splice/grouped-splices.hs−3 data/examples/declaration/splice/splice-decl.hs+1 data/examples/declaration/type-families/closed-type-family/multi-line-out.hs+5−6 data/examples/declaration/type-synonyms/with-weird-haddock-out.hs−3 data/examples/declaration/type-synonyms/with-weird-haddock.hs−1 data/examples/declaration/type/visible-forall-out.hs−2 data/examples/declaration/type/visible-forall.hs−2 data/examples/declaration/value/function/arg-breakpoints-out.hs−3 data/examples/declaration/value/function/arg-breakpoints.hs−3 data/examples/declaration/value/function/arrow/expression-applications-out.hs+9 data/examples/declaration/value/function/arrow/expression-applications.hs+9 data/examples/declaration/value/function/arrow/expression-forms-out.hs+14 data/examples/declaration/value/function/arrow/expression-forms.hs+11 data/examples/declaration/value/function/arrow/multiline-case-out.hs−8 data/examples/declaration/value/function/arrow/multiline-case.hs−7 data/examples/declaration/value/function/arrow/proc-applications-out.hs+5−6 data/examples/declaration/value/function/arrow/proc-do-complex-out.hs+14−18 data/examples/declaration/value/function/arrow/proc-do-simple1-out.hs+2−3 data/examples/declaration/value/function/arrow/proc-do-simple2-out.hs+7−9 data/examples/declaration/value/function/arrow/proc-forms1-out.hs+6−8 data/examples/declaration/value/function/arrow/proc-forms2-out.hs+6−10 data/examples/declaration/value/function/arrow/proc-forms2.hs+6−6 data/examples/declaration/value/function/arrow/proc-ifs-out.hs+4−6 data/examples/declaration/value/function/arrow/proc-parentheses-out.hs+4−5 data/examples/declaration/value/function/arrow/recursive-procs-out.hs+10−14 data/examples/declaration/value/function/awkward-comment-0-out.hs−6 data/examples/declaration/value/function/awkward-comment-0.hs−5 data/examples/declaration/value/function/awkward-comment-1-out.hs−9 data/examples/declaration/value/function/awkward-comment-1.hs−7 data/examples/declaration/value/function/blank-lines-let-out.hs−6 data/examples/declaration/value/function/blank-lines-let.hs−9 data/examples/declaration/value/function/blank-lines-where-out.hs−6 data/examples/declaration/value/function/blank-lines-where.hs−7 data/examples/declaration/value/function/do/blocks-out.hs−1 data/examples/declaration/value/function/do/comment-alignment-out.hs−9 data/examples/declaration/value/function/do/comment-alignment.hs−9 data/examples/declaration/value/function/do/comment-spacing-out.hs−7 data/examples/declaration/value/function/do/comment-spacing.hs−7 data/examples/declaration/value/function/do/recursive-do-rec-out.hs−5 data/examples/declaration/value/function/if-with-comment-out.hs−8 data/examples/declaration/value/function/if-with-comment.hs−8 data/examples/declaration/value/function/implicit-params-out.hs−1 data/examples/declaration/value/function/implicit-params.hs−2 data/examples/declaration/value/function/infix/dollar-chains-out.hs+3−3 data/examples/declaration/value/function/infix/hanging-out.hs+3−4 data/examples/declaration/value/function/infix/lenses-out.hs+7−8 data/examples/declaration/value/function/let-single-line-out.hs+1 data/examples/declaration/value/function/list-notation-0-out.hs−5 data/examples/declaration/value/function/list-notation-0.hs−5 data/examples/declaration/value/function/list-notation-1-out.hs−8 data/examples/declaration/value/function/list-notation-1.hs−7 data/examples/declaration/value/function/list-notation-2-out.hs−6 data/examples/declaration/value/function/list-notation-2.hs−5 data/examples/declaration/value/function/list-notation-3-out.hs−12 data/examples/declaration/value/function/list-notation-3.hs−10 data/examples/declaration/value/function/multi-way-if-out.hs+2−4 data/examples/declaration/value/function/operator-comments-2-out.hs−5 data/examples/declaration/value/function/operator-comments-2.hs−4 data/examples/declaration/value/function/operators-1-out.hs−4 data/examples/declaration/value/function/operators-1.hs−3 data/examples/declaration/value/function/operators-2-out.hs−4 data/examples/declaration/value/function/operators-2.hs−4 data/examples/declaration/value/function/operators-3-out.hs−3 data/examples/declaration/value/function/operators-3.hs−3 data/examples/declaration/value/function/operators-4-out.hs−3 data/examples/declaration/value/function/operators-4.hs−3 data/examples/declaration/value/function/operators-5-out.hs−5 data/examples/declaration/value/function/operators-5.hs−4 data/examples/declaration/value/function/operators-6-out.hs−9 data/examples/declaration/value/function/operators-6.hs−7 data/examples/declaration/value/function/operators-0-out.hs → data/examples/declaration/value/function/operators-out.hs data/examples/declaration/value/function/operators-0.hs → data/examples/declaration/value/function/operators.hs data/examples/declaration/value/function/pattern/famous-cardano-pattern-out.hs+8−8 data/examples/declaration/value/function/pattern/multiline-case-pattern-out.hs+2−2 data/examples/declaration/value/function/pattern/view-pattern-out.hs+3 data/examples/declaration/value/function/pattern/view-pattern.hs+3 data/examples/declaration/value/function/record/constructors-out.hs → data/examples/declaration/value/function/record-constructors-out.hs data/examples/declaration/value/function/record/constructors.hs → data/examples/declaration/value/function/record-constructors.hs data/examples/declaration/value/function/record/dot-out.hs → data/examples/declaration/value/function/record-dot-out.hs data/examples/declaration/value/function/record/dot.hs → data/examples/declaration/value/function/record-dot.hs data/examples/declaration/value/function/record/inter-comments-out.hs → data/examples/declaration/value/function/record-inter-comments-out.hs data/examples/declaration/value/function/record/inter-comments.hs → data/examples/declaration/value/function/record-inter-comments.hs data/examples/declaration/value/function/record/updaters-out.hs → data/examples/declaration/value/function/record-updaters-out.hs data/examples/declaration/value/function/record/updaters.hs → data/examples/declaration/value/function/record-updaters.hs data/examples/declaration/value/function/record/wildcards-out.hs → data/examples/declaration/value/function/record-wildcards-out.hs data/examples/declaration/value/function/record/wildcards.hs → data/examples/declaration/value/function/record-wildcards.hs data/examples/declaration/value/function/record/hanging-after-equal-con-out.hs−8 data/examples/declaration/value/function/record/hanging-after-equal-con.hs−7 data/examples/declaration/value/function/record/hanging-after-equal-update-out.hs−8 data/examples/declaration/value/function/record/hanging-after-equal-update.hs−7 data/examples/declaration/value/function/type-applications-and-splice-out.hs−4 data/examples/declaration/value/function/type-applications-and-splice.hs−4 data/examples/import/deduplication-bug-out.hs−6 data/examples/import/deduplication-bug.hs−6 data/examples/import/explicit-imports-out.hs+4−4 data/examples/import/explicit-imports-with-comments-out.hs+2−3 data/examples/import/merging-0-out.hs−3 data/examples/import/merging-0.hs−4 data/examples/import/merging-1-out.hs−2 data/examples/import/merging-1.hs−3 data/examples/import/merging-2-out.hs−2 data/examples/import/merging-2.hs−4 data/examples/import/misc-out.hs+6 data/examples/import/nested-explicit-imports-out.hs+6−6 data/examples/import/qualified-post-out.hs−5 data/examples/import/qualified-post.hs−5 data/examples/import/qualified-prelude-out.hs+1−1 data/examples/import/simple-out.hs+3−2 data/examples/import/simple.hs−2 data/examples/import/sorted-export-list-out.hs−1 data/examples/import/sorted-export-list.hs−1 data/examples/module-header/double-dot-with-names-out.hs+6−1 data/examples/module-header/multiline2.hs+2−2 data/examples/module-header/preceding-comment-with-haddock-out.hs+4−1 data/examples/module-header/singleline-empty-out.hs+4−1 data/examples/module-header/stack-header-0-out.hs−1 data/examples/module-header/stack-header-1-out.hs−1 data/examples/module-header/warning-pragma-multiline-out.hs+4−1 data/examples/module-header/warning-pragma-out.hs+1−3 data/examples/other/argument-comment-out.hs+1 data/examples/other/comment-glued-together-out.hs−7 data/examples/other/comment-glued-together.hs−6 data/examples/other/comment-trailing-space-out.hs−9 data/examples/other/comment-trailing-space.hs−9 data/examples/other/comment-two-blocks-out.hs+2−2 data/examples/other/cpp/continuation-out.hs−8 data/examples/other/cpp/continuation.hs−8 data/examples/other/cpp/lonely-hash-out.hs−14 data/examples/other/cpp/lonely-hash.hs−14 data/examples/other/cpp/separation-0a-out.hs−7 data/examples/other/cpp/separation-0a.hs−6 data/examples/other/cpp/separation-0b-out.hs−10 data/examples/other/cpp/separation-0b.hs−9 data/examples/other/cpp/separation-1a-out.hs−12 data/examples/other/cpp/separation-1a.hs−11 data/examples/other/cpp/separation-1b-out.hs−15 data/examples/other/cpp/separation-1b.hs−14 data/examples/other/cpp/separation-2a-out.hs−9 data/examples/other/cpp/separation-2a.hs−8 data/examples/other/cpp/separation-2b-out.hs−11 data/examples/other/cpp/separation-2b.hs−11 data/examples/other/cpp/shifted-out.hs−21 data/examples/other/cpp/shifted.hs−17 data/examples/other/cpp/simple-import-out.hs−14 data/examples/other/cpp/simple-import.hs−14 data/examples/other/disabling/indented-fragment-out.hs−7 data/examples/other/disabling/indented-fragment.hs−7 data/examples/other/disabling/single-definition-out.hs−10 data/examples/other/disabling/single-definition.hs−10 data/examples/other/disabling/whole-file-out.hs−10 data/examples/other/disabling/whole-file.hs−10 data/examples/other/inline-comment-0-out.hs−3 data/examples/other/inline-comment-0.hs−3 data/examples/other/inline-comment-1-out.hs−12 data/examples/other/inline-comment-1.hs−9 data/examples/other/multiline-forall-out.hs+2−1 data/examples/other/multiple-blank-line-comment-out.hs−9 data/examples/other/multiple-blank-line-comment.hs−10 data/examples/other/pragma-comments-after-out.hs−4 data/examples/other/pragma-comments-after.hs−3 data/examples/other/pragma-comments-out.hs−8 data/examples/other/pragma-comments.hs−11 data/examples/other/pragma-out.hs+4−1 data/examples/other/pragma-sorting-out.hs+2−1 default.nix+51−108 expected-failures/Agda.txt−11 expected-failures/aws.txt−9 expected-failures/distributed-process.txt−7 expected-failures/esqueleto.txt−7 expected-failures/fay.txt−18 expected-failures/hlint.txt−11 expected-failures/idris.txt−7 expected-failures/intero.txt−5 expected-failures/leksah.txt−5 expected-failures/lens.txt−3 expected-failures/pandoc.txt−9 expected-failures/pipes.txt−3 expected-failures/postgrest.txt−5 expected-failures/purescript.txt−18 expected-failures/tensorflow.txt−7 format.sh+3−6 nix/nixpkgs/default.nix+3−7 nix/ormolize/default.nix+13−29 nix/ormolize/ormolize.sh+17 ormolu.cabal+157−174 region-tests/expected-result-17-18.hs−17 region-tests/expected-result-6-7.hs−17 region-tests/expected-result-6-8.hs−16 region-tests/expected-result-9-12.hs−17 region-tests/expected-result-all.hs−21 region-tests/src.hs−17 shell.nix+2−4 src/GHC.hs+13−2 src/GHC/DynFlags.hs+19−30 src/Ormolu.hs+7−10 src/Ormolu/Config.hs+23−62 src/Ormolu/Diff.hs+13−23 src/Ormolu/Exception.hs+11−4 src/Ormolu/Imports.hs+51−168 src/Ormolu/Parser.hs+84−78 src/Ormolu/Parser/CommentStream.hs+61−147 src/Ormolu/Parser/Pragma.hs+4−4 src/Ormolu/Parser/Result.hs+15−26 src/Ormolu/Parser/Shebang.hs−27 src/Ormolu/Printer.hs+6−17 src/Ormolu/Printer/Combinators.hs+53−39 src/Ormolu/Printer/Comments.hs+76−62 src/Ormolu/Printer/Internal.hs+96−149 src/Ormolu/Printer/Meat/Common.hs+11−13 src/Ormolu/Printer/Meat/Declaration.hs+110−138 src/Ormolu/Printer/Meat/Declaration.hs-boot+1 src/Ormolu/Printer/Meat/Declaration/Annotation.hs+3−2 src/Ormolu/Printer/Meat/Declaration/Class.hs+29−21 src/Ormolu/Printer/Meat/Declaration/Data.hs+43−68 src/Ormolu/Printer/Meat/Declaration/Default.hs+5−4 src/Ormolu/Printer/Meat/Declaration/Foreign.hs+3−2 src/Ormolu/Printer/Meat/Declaration/Instance.hs+17−13 src/Ormolu/Printer/Meat/Declaration/RoleAnnotation.hs+5−2 src/Ormolu/Printer/Meat/Declaration/Rule.hs+13−12 src/Ormolu/Printer/Meat/Declaration/Signature.hs+33−49 src/Ormolu/Printer/Meat/Declaration/Splice.hs+3−2 src/Ormolu/Printer/Meat/Declaration/Type.hs+7−6 src/Ormolu/Printer/Meat/Declaration/TypeFamily.hs+23−22 src/Ormolu/Printer/Meat/Declaration/Value.hs+361−375 src/Ormolu/Printer/Meat/Declaration/Value.hs-boot+4 src/Ormolu/Printer/Meat/Declaration/Warning.hs+13−9 src/Ormolu/Printer/Meat/ImportExport.hs+35−44 src/Ormolu/Printer/Meat/Module.hs+20−26 src/Ormolu/Printer/Meat/Pragma.hs+12−22 src/Ormolu/Printer/Meat/Type.hs+61−85 src/Ormolu/Printer/Operators.hs+66−50 src/Ormolu/Processing/Common.hs−27 src/Ormolu/Processing/Cpp.hs−70 src/Ormolu/Processing/Postprocess.hs−31 src/Ormolu/Processing/Preprocess.hs−149 src/Ormolu/Utils.hs+16−74 tests/Ormolu/PrinterSpec.hs+10−7
.buildkite/pipeline.ymldeleted−18
@@ -1,18 +0,0 @@
1−steps:
2− - label: Build and test with GHC 8.6.5
3− command: |
4− nix-build --keep-going --no-out-link --argstr ormoluCompiler ghc865
5− timeout: 100
6− - label: Build and test with GHC 8.8.4
7− command: |
8− nix-build --keep-going --no-out-link --argstr ormoluCompiler ghc884
9− timeout: 100
10− - label: Build and test with GHC 8.10.1
11− command: |
12− nix-build --keep-going --no-out-link --argstr ormoluCompiler ghc8101
13− timeout: 100
14− - wait
15− - label: Check formatting
16− command: |
17− ./format.sh
18− git diff --exit-code --color=always
.circleci/config.ymlnew file+49
@@ -0,0 +1,49 @@
1+version: 2
2+
3+jobs:
4+ build:
5+ docker:
6+ - image: nixos/nix:2.1.3
7+ steps:
8+ - checkout
9+ - run:
10+ name: Add ca-certificates
11+ command: |
12+ apk --no-progress update
13+ apk --no-progress add ca-certificates
14+ - run:
15+ name: Setup Cachix
16+ command: |
17+ nix-env -iA cachix -f https://cachix.org/api/v1/install
18+ USER=dummy cachix use tweag
19+ - run:
20+ name: Build environment
21+ command: |
22+ nix-shell --pure --run :
23+ - run:
24+ name: Push Cachix
25+ command: |
26+ if [ -n "$CACHIX_SIGNING_KEY" ];
27+ then nix-store -qR --include-outputs $(nix-instantiate default.nix) | cachix push tweag;
28+ fi
29+ - run:
30+ name: Build the package (includes running the tests)
31+ command: nix-build --keep-going
32+ - run:
33+ name: Check formatting
34+ command: |
35+ ./format.sh
36+ nix-shell -p "(import ./nix/nixpkgs/default.nix).git" --command "git diff --exit-code --color=always"
37+ - run:
38+ name: Generate Haddocks
39+ command: nix-build --attr ormolu.doc
40+ - store_artifacts:
41+ path: result-doc/share/doc
42+ destination: haddock
43+
44+workflows:
45+ version: 2
46+ build:
47+ jobs:
48+ - build:
49+ context: org-global
.github/workflows/binaries.ymldeleted−39
@@ -1,39 +0,0 @@
1−name: Build binaries
2−on:
3− release:
4− types: [published]
5−jobs:
6− build:
7− strategy:
8− fail-fast: false
9− matrix:
10− os: [ubuntu-latest, macOS-latest, windows-latest]
11− runs-on: ${{ matrix.os }}
12− steps:
13− - uses: actions/checkout@v2
14− - uses: actions/setup-haskell@v1
15− if: runner.os != 'Linux'
16− with:
17− ghc-version: '8.10.1'
18− cabal-version: '3.2'
19− - name: Build Linux binary
20− if: runner.os == 'Linux'
21− run: |
22− docker run \
23− -v $(pwd):/mnt -w /mnt \
24− utdemir/ghc-musl:v14-ghc8101 \
25− bash .github/workflows/build.sh
26− - name: Build ${{ runner.os }} binary
27− if: runner.os != 'Linux'
28− shell: bash
29− run: |
30− cabal build exe:ormolu
31− cp $(find dist-newstyle \( -name ormolu -o -name ormolu.exe \) -type f) ormolu
32− - uses: actions/upload-release-asset@v1
33− env:
34− GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35− with:
36− upload_url: ${{ github.event.release.upload_url }}
37− asset_path: ormolu
38− asset_name: ormolu-${{ runner.os }}
39− asset_content_type: application/octet-stream
.github/workflows/build.shdeleted−7
@@ -1,7 +0,0 @@
1−set -e
2−
3−cabal update
4−cabal build exe:ormolu --enable-executable-static --ghc-options="-split-sections"
5−
6−cp $(find dist-newstyle -name ormolu -type f) .
7−strip -s ormolu
CHANGELOG.md−155
@@ -1,160 +1,5 @@
11## Unreleased
22
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−
1583* Fixed rendering of record updates with the record dot preprocessor syntax
1594 [Issue 498](https://github.com/tweag/ormolu/issues/498).
1605
CONTRIBUTING.md+1−1
@@ -30,7 +30,7 @@ Testing is performed as following:
3030* The result of printing is parsed back again and the AST is compared to the
3131 AST obtained from the original file. They should match.
3232* The output of printer is checked against the expected output.
33−* Idempotence property is verified: formatting already formatted code
33+* Idempotency property is verified: formatting already formatted code
3434 results in exactly the same output.
3535
3636Examples can be organized in sub-directories, see the existing ones for
DESIGN.md+11−11
@@ -24,7 +24,7 @@ It also includes recommendations for future implementers.
2424
2525We set for the following goals (mostly taken from
2626[brittany](https://github.com/lspitzner/brittany)):
27−* Preserve the meaning of the formatted functions when no CPP is used;
27+* Preserve the meaning of the formatted functions;
2828* Make reasonable use of screen space;
2929* Use linear space and computation time on the size of the input;
3030* Preserve comments;
@@ -140,10 +140,8 @@ impossible to guess what they'll be called on.
140140
141141### CPP
142142
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
146−do conditional compilation.
143+Formatting a module which uses CPP directives won't be supported. Instead,
144+we hope for a solution to replace CPP to do conditional compilation.
147145
148146There are the following challenges when formatting a module with CPP:
149147
@@ -182,15 +180,14 @@ True
182180```
183181
184182At the time of this writing, formatting this program with Hindent
185−or Ormolu produces the same output we would get if the CPP directives
186−were considered comments:
183+produces the same output we would get if the CPP directives were
184+considered comments:
187185
188186```
189−$ ormolu --version
190−ormolu 0.0.5.0 HEAD fc64eada5c4da7a5b07d2872e253671b48aec115
191−using ghc-lib-parser 8.10.1.20200412
187+$ hindent --version
188+hindent 5.2.7
192189
193−$ ormolu --mode inplace test.hs
190+$ hindent test.hs
194191
195192$ cat test.hs
196193{-# LANGUAGE CPP #-}
@@ -230,6 +227,9 @@ to parse Haskell modules. If CPP is replaced with some language
230227extension or mechanism to do conditional compilation, all tools
231228will benefit from it.
232229
230+Therefore, CPP won't be supported. If the CPP extension
231+is enabled, we should signal an error right away.
232+
233233### Printing
234234
235235Just pretty-printing code (following the approach of Hindent) seems sane. It
README.md+13−57
@@ -4,7 +4,7 @@
44[![Hackage](https://img.shields.io/hackage/v/ormolu.svg?style=flat)](https://hackage.haskell.org/package/ormolu)
55[![Stackage Nightly](http://stackage.org/package/ormolu/badge/nightly)](http://stackage.org/nightly/package/ormolu)
66[![Stackage LTS](http://stackage.org/package/ormolu/badge/lts)](http://stackage.org/lts/package/ormolu)
7−[![Build status](https://badge.buildkite.com/8e3b0951f3652b77e1c422b361904136a539b0522029156354.svg?branch=master)](https://buildkite.com/tweag-1/ormolu)
7+[![CircleCI](https://circleci.com/gh/tweag/ormolu/tree/master.svg?style=svg&circle-token=cfd37a39265561eb44e608f97cf953cb2a394c03)](https://circleci.com/gh/tweag/ormolu/tree/master)
88
99Ormolu is a formatter for Haskell source code. The project was created with
1010the following goals in mind:
@@ -22,7 +22,7 @@ the following goals in mind:
2222* That formatting style aims to result in minimal diffs while still
2323 remaining very close to “conventional” Haskell formatting people use.
2424* Choose a style compatible with modern dialects of Haskell. As new Haskell
25− extensions enter broad use, we may change the style to accommodate them.
25+ extensions enter broad use, we may change the style to accomodate them.
2626* Idempotence: formatting already formatted code doesn't change it.
2727* Be well-tested and robust to the point that it can be used in large
2828 projects without exposing unfortunate, disappointing bugs here and there.
@@ -45,12 +45,11 @@ Alternatively, `stack` could be used with a `stack.yaml` file as follows.
4545
4646```console
4747$ cat stack.yaml
48−resolver: lts-16.0
48+resolver: lts-14.3
4949packages:
5050- '.'
5151
52−$ stack build # to build
53−$ stack install # to install
52+$ stack build
5453```
5554
5655To use Ormolu directly from GitHub with Nix, this snippet may come in handy:
@@ -92,44 +91,20 @@ formatted output.
9291$ ormolu --mode inplace Module.hs
9392```
9493
95−Use `find` to format a tree recursively:
96−
97−```console
98−$ ormolu --mode inplace $(find . -name '*.hs')
99−```
100−
101−## Magic comments
102−
103−Ormolu understands two magic comments:
104−
105−```haskell
106−{- ORMOLU_DISABLE -}
107−```
108−
109−and
110−
111−```haskell
112−{- ORMOLU_ENABLE -}
113−```
114−
115−This allows us to disable formatting selectively for code between these
116−markers or disable it for the entire file. To achieve the latter, just put
117−`{- ORMOLU_DISABLE -}` at the very top. Note that the source code should
118−still be parseable even without the “excluded” part. Because of that the
119−magic comments cannot be placed arbitrary, but should rather enclose
120−independent top-level definitions.
121−
12294## Current limitations
12395
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.
96+* Does not handle CPP (wontfix, see [the design document][design]).
12997* Input modules should be parsable by Haddock, which is a bit stricter
13098 criterion than just being valid Haskell modules.
13199* Various minor idempotence issues, most of them are related to comments.
132100
101+## Editor integration
102+
103+We know of the following editor integrations:
104+
105+* [Emacs][emacs-package]
106+* [VS Code][vs-code-plugin]
107+
133108## Running on Hackage
134109
135110It's possible to try Ormolu on arbitrary packages from Hackage. For that
@@ -144,22 +119,6 @@ also contain formatted `.hs` files for inspection and original inputs with
144119`.hs-original` extension (those are with CPP dropped, exactly what is fed
145120into Ormolu).
146121
147−## Editor integration
148−
149−We know of the following editor integrations:
150−
151−* [Emacs][emacs-package]
152−* [VS Code][vs-code-plugin]
153−* vim: [neoformat][neoformat], [vim-ormolu][vim-ormolu]
154−
155−## Arch Linux
156−
157−To install Ormolu on Arch Linux, one can use [the package on AUR][aur]:
158−
159−```console
160−yay -S ormolu
161−```
162−
163122## Contributing
164123
165124See [CONTRIBUTING.md][contributing].
@@ -170,12 +129,9 @@ See [LICENSE.md][license].
170129
171130Copyright © 2018–present Tweag I/O
172131
173−[design-cpp]: https://github.com/tweag/ormolu/blob/master/DESIGN.md#cpp
132+[design]: https://github.com/tweag/ormolu/blob/master/DESIGN.md#cpp
174133[contributing]: https://github.com/tweag/ormolu/blob/master/CONTRIBUTING.md
175134[license]: https://github.com/tweag/ormolu/blob/master/LICENSE.md
176135[haskell-src-exts]: https://hackage.haskell.org/package/haskell-src-exts
177136[emacs-package]: https://github.com/vyorkin/ormolu.el
178137[vs-code-plugin]: https://marketplace.visualstudio.com/items?itemName=sjurmillidahl.ormolu-vscode
179−[vim-ormolu]: https://github.com/sdiehl/vim-ormolu
180−[neoformat]: https://github.com/sbdchd/neoformat
181−[aur]: https://aur.archlinux.org/packages/ormolu
app/Main.hs+95−133
@@ -1,17 +1,12 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE LambdaCase #-}
33{-# LANGUAGE RecordWildCards #-}
44{-# LANGUAGE TemplateHaskell #-}
5−{-# LANGUAGE TypeApplications #-}
65
76module Main (main) where
87
9−import Control.Exception (SomeException, displayException, try)
108import Control.Monad
11−import Data.Bool (bool)
12−import Data.Either (lefts)
139import Data.List (intercalate, sort)
14−import qualified Data.Text.IO as TIO
1510import Data.Version (showVersion)
1611import Development.GitRev
1712import Options.Applicative
@@ -21,8 +16,10 @@ import Ormolu.Utils (showOutputable)
2116import Paths_ormolu (version)
2217import System.Exit (ExitCode (..), exitWith)
2318import System.IO (hPutStrLn, stderr)
19+import qualified Data.Text.IO as TIO
2420
2521-- | Entry point of the program.
22+
2623main :: IO ()
2724main = withPrettyOrmoluExceptions $ do
2825 Opts {..} <- execParser optsParserInfo
@@ -30,50 +27,35 @@ main = withPrettyOrmoluExceptions $ do
3027 case optInputFiles of
3128 [] -> formatOne' Nothing
3229 ["-"] -> 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)
30+ xs -> mapM_ (formatOne' . Just) xs
4231
4332-- | 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 ()
33+
34+formatOne
35+ :: Mode -- ^ Mode of operation
36+ -> Config -- ^ Configuration
37+ -> Maybe FilePath -- ^ File to format or stdin as 'Nothing'
38+ -> IO ()
5239formatOne mode config = \case
5340 Nothing -> do
5441 r <- ormoluStdin config
5542 case mode of
5643 Stdout -> TIO.putStr r
57− _ -> do
58− hPutStrLn
59− stderr
44+ _ -> do
45+ hPutStrLn stderr
6046 "This feature is not supported when input comes from stdin."
61− -- 101 is different from all the other exit codes we already use.
47+ -- 101 is different from all the other exit codes we already use.
6248 exitWith (ExitFailure 101)
6349 Just inputFile -> do
64− originalInput <- TIO.readFile inputFile
65− formattedInput <- ormoluFile config inputFile
50+ r <- ormoluFile config inputFile
6651 case mode of
6752 Stdout ->
68− TIO.putStr formattedInput
69− InPlace -> do
70− -- Only write when the contents have changed, in order to avoid
71− -- updating the modified timestamp if the file was already correctly
72− -- formatted.
73− when (formattedInput /= originalInput) $
74− TIO.writeFile inputFile formattedInput
53+ TIO.putStr r
54+ InPlace ->
55+ TIO.writeFile inputFile r
7556 Check -> do
76− when (formattedInput /= originalInput) $
57+ r' <- TIO.readFile inputFile
58+ when (r /= r') $
7759 -- 100 is different to all the other exit code that are emitted
7860 -- either from an 'OrmoluException' or from 'error' and
7961 -- 'notImplemented'.
@@ -83,121 +65,101 @@ formatOne mode config = \case
8365-- Command line options parsing.
8466
8567data Opts = Opts
86− { -- | Mode of operation
87− optMode :: !Mode,
88− -- | Ormolu 'Config'
89− optConfig :: !(Config RegionIndices),
90− -- | Haskell source files to format or stdin (when the list is empty)
91− optInputFiles :: ![FilePath]
68+ { optMode :: !Mode
69+ -- ^ Mode of operation
70+ , optConfig :: !Config
71+ -- ^ Ormolu 'Config'
72+ , optInputFiles :: ![FilePath]
73+ -- ^ Haskell source files to format or stdin (when the list is empty)
9274 }
9375
9476-- | Mode of operation.
77+
9578data Mode
96− = -- | Output formatted source code to stdout
97− Stdout
98− | -- | Overwrite original file
99− InPlace
100− | -- | Exit with non-zero status code if
101− -- source is not already formatted
102− Check
79+ = Stdout -- ^ Output formatted source code to stdout
80+ | InPlace -- ^ Overwrite original file
81+ | Check -- ^ Exit with non-zero status code if
82+ -- source is not already formatted
10383 deriving (Eq, Show)
10484
10585optsParserInfo :: ParserInfo Opts
106−optsParserInfo =
107− info (helper <*> ver <*> exts <*> optsParser) . mconcat $
108− [ fullDesc,
109− progDesc "",
110− header ""
111− ]
86+optsParserInfo = info (helper <*> ver <*> exts <*> optsParser) . mconcat $
87+ [ fullDesc
88+ , progDesc ""
89+ , header ""
90+ ]
11291 where
11392 ver :: Parser (a -> a)
114− ver =
115− infoOption verStr . mconcat $
116− [ long "version",
117− short 'v',
118− help "Print version of the program"
119− ]
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
93+ ver = infoOption verStr . mconcat $
94+ [ long "version"
95+ , short 'v'
96+ , help "Print version of the program"
97+ ]
98+ verStr = intercalate "\n"
99+ [ unwords
100+ [ "ormolu"
101+ , showVersion version
102+ , $gitBranch
103+ , $gitHash
130104 ]
105+ , "using ghc-lib-parser " ++ VERSION_ghc_lib_parser
106+ ]
131107 exts :: Parser (a -> a)
132− exts =
133− infoOption displayExts . mconcat $
134− [ long "manual-exts",
135− help "Display extensions that need to be enabled manually"
136− ]
108+ exts = infoOption displayExts . mconcat $
109+ [ long "manual-exts"
110+ , help "Display extensions that need to be enabled manually"
111+ ]
137112 displayExts = unlines $ sort (showOutputable <$> manualExts)
138113
139114optsParser :: Parser Opts
140−optsParser =
141− Opts
142− <$> ( (fmap (bool Stdout InPlace) . switch . mconcat)
143− [ short 'i',
144− help "A shortcut for --mode inplace"
145− ]
146− <|> (option parseMode . mconcat)
147− [ long "mode",
148− short 'm',
149− metavar "MODE",
150− value Stdout,
151− help "Mode of operation: 'stdout' (default), 'inplace', or 'check'"
152− ]
153− )
154− <*> configParser
155− <*> (many . strArgument . mconcat)
156− [ metavar "FILE",
157− help "Haskell source files to format or stdin (default)"
158− ]
115+optsParser = Opts
116+ <$> (option parseMode . mconcat)
117+ [ long "mode"
118+ , short 'm'
119+ , metavar "MODE"
120+ , value Stdout
121+ , help "Mode of operation: 'stdout' (default), 'inplace', or 'check'"
122+ ]
123+ <*> configParser
124+ <*> (many . strArgument . mconcat)
125+ [ metavar "FILE"
126+ , help "Haskell source files to format or stdin (default)"
127+ ]
159128
160−configParser :: Parser (Config RegionIndices)
161−configParser =
162− Config
163− <$> (fmap (fmap DynOption) . many . strOption . mconcat)
164− [ long "ghc-opt",
165− short 'o',
166− metavar "OPT",
167− help "GHC options to enable (e.g. language extensions)"
168− ]
169− <*> (switch . mconcat)
170− [ long "unsafe",
171− short 'u',
172− help "Do formatting faster but without automatic detection of defects"
173− ]
174− <*> (switch . mconcat)
175− [ long "debug",
176− short 'd',
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"
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− )
129+configParser :: Parser Config
130+configParser = Config
131+ <$> (fmap (fmap DynOption) . many . strOption . mconcat)
132+ [ long "ghc-opt"
133+ , short 'o'
134+ , metavar "OPT"
135+ , help "GHC options to enable (e.g. language extensions)"
136+ ]
137+ <*> (switch . mconcat)
138+ [ long "unsafe"
139+ , short 'u'
140+ , help "Do formatting faster but without automatic detection of defects"
141+ ]
142+ <*> (switch . mconcat)
143+ [ long "debug"
144+ , short 'd'
145+ , help "Output information useful for debugging"
146+ ]
147+ <*> (switch . mconcat)
148+ [ long "tolerate-cpp"
149+ , short 'p'
150+ , help "Do not fail if CPP pragma is present"
151+ ]
152+ <*> (switch . mconcat)
153+ [ long "check-idempotency"
154+ , short 'c'
155+ , help "Fail if formatting is not idempotent"
156+ ]
196157
197158----------------------------------------------------------------------------
198159-- Helpers
199160
200161-- | Parse 'Mode'.
162+
201163parseMode :: ReadM Mode
202164parseMode = eitherReader $ \case
203165 "stdout" -> Right Stdout
data/examples/declaration/annotation/annotation-out.hs−1
@@ -18,5 +18,4 @@ foo = 5
1818
1919data Foo = Foo Int
2020{-# ANN type Foo ("HLint: ignore") #-}
21−
2221{- Comment -}
data/examples/declaration/class/dependency-super-classes-out.hs+1−2
@@ -13,8 +13,7 @@ class
1313 MonadPlus m -- Potential for failure
1414 ) =>
1515 MonadParsec e s m
16− | m -> e s
17− where
16+ | m -> e s where
1817 -- | 'getState' returns state
1918 getState ::
2019 m s
data/examples/declaration/class/functional-dependencies-out.hs+1−2
@@ -14,6 +14,5 @@ class
1414 b c -> a d, -- Bar
1515 a c -> b d, -- Baz
1616 a c d -> b,
17− a b d -> a b c d
18− where
17+ a b d -> a b c d where
1918 baz :: a -> b
data/examples/declaration/class/multi-parameters2-out.hs+1−2
@@ -10,8 +10,7 @@ class
1010 c -- Baz bar
1111 d -- Baz baz
1212 e -- Rest
13− f
14− where
13+ f where
1514 barbaz ::
1615 a -> f
1716 bazbar ::
data/examples/declaration/data/existential-multiline-out.hs−12
@@ -3,15 +3,3 @@
33data Foo
44 = forall a. MkFoo a (a -> Bool)
55 | forall a. Eq a => MkBar a
6−
7−data Bar
8− = forall x y.
9− Bar x y x y
10−
11−data Baz
12− = forall x y.
13− Baz
14− x
15− y
16− x
17− y
data/examples/declaration/data/existential-multiline.hs−7
@@ -3,10 +3,3 @@
33data Foo
44 = forall a. MkFoo a (a -> Bool)
55 | 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/field-layout/gadt-out.hs+1−2
@@ -6,6 +6,5 @@ data Foo a b where
66 Foo :: Foo Int Int
77 -- | Something else
88 Bar ::
9− Foo
10− Char
9+ Foo Char
1110 Char
data/examples/declaration/data/field-layout/record-out.hs+9−9
@@ -1,12 +1,12 @@
11module Main where
22
33-- | Foo.
4−data Foo = Foo
5− { -- | Something
6− foo :: Foo Int Int,
7− -- | Something else
8− bar ::
9− Bar
10− Char
11− Char
12− }
4+data Foo
5+ = Foo
6+ { -- | Something
7+ foo :: Foo Int Int,
8+ -- | Something else
9+ bar ::
10+ Bar Char
11+ Char
12+ }
data/examples/declaration/data/gadt/multiline-out.hs+1−1
@@ -8,7 +8,7 @@ data Foo a where
88 Foo ::
99 forall a b.
1010 (Show a, Eq b) => -- foo
11− -- bar
11+ -- bar
1212 a ->
1313 b ->
1414 Foo 'Int
data/examples/declaration/data/gadt/multiline-where-out.hsdeleted−7
@@ -1,7 +0,0 @@
1−data
2− Foo
3− a
4− b
5− c
6− where
7− Foo :: a -> b -> c -> Foo a b c
data/examples/declaration/data/gadt/multiline-where.hsdeleted−6
@@ -1,6 +0,0 @@
1−data
2− Foo
3− a
4− b
5− c where
6− Foo :: a -> b -> c -> Foo a b c
data/examples/declaration/data/multiline-arg-parens-out.hs+1−1
@@ -5,6 +5,6 @@ data Foo
55 = Foo
66 Bar
77 (Set Baz) -- and here we go
8− -- and that's it
8+ -- and that's it
99 Text
1010 deriving (Eq)
data/examples/declaration/data/partly-documented-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−data Optimisation
2− = PETransform
3− | -- | partial eval and associated transforms
4− GeneralisedNatHack
5− deriving (Show, Eq, Generic)
data/examples/declaration/data/partly-documented.hsdeleted−2
@@ -1,2 +0,0 @@
1−data Optimisation = PETransform | GeneralisedNatHack -- ^ partial eval and associated transforms
2− deriving (Show, Eq, Generic)
data/examples/declaration/data/record-multi-const-out.hsdeleted−17
@@ -1,17 +0,0 @@
1−module Main where
2−
3−-- | Something.
4−data Foo
5− = Foo
6− { -- | X
7− fooX :: Int,
8− -- | Y
9− fooY :: Int
10− }
11− | Bar
12− { -- | X
13− barX :: Int,
14− -- | Y
15− barY :: Int
16− }
17− deriving (Eq, Show)
data/examples/declaration/data/record-multi-const.hsdeleted−13
@@ -1,13 +0,0 @@
1−module Main where
2−
3−-- | Something.
4−
5−data Foo = Foo
6− { fooX :: Int -- ^ X
7− , fooY :: Int -- ^ Y
8− } |
9− Bar
10− { barX :: Int -- ^ X
11− , barY :: Int -- ^ Y
12− }
13− deriving (Eq, Show)
data/examples/declaration/data/record-out.hs+20−19
@@ -1,23 +1,24 @@
11module Main where
22
33-- | Something.
4−data Foo = Foo
5− { -- | X
6− fooX :: Int,
7− -- | Y
8− fooY :: Int,
9− -- | BarBaz
10− fooBar, fooBaz :: NonEmpty (Identity Bool),
11− -- | GagGog
12− fooGag,
13− fooGog ::
14− NonEmpty
15− ( Indentity
16− Bool
17− ),
18− -- | Huh!
19− fooFoo,
20− barBar ::
21− Int
22− }
4+data Foo
5+ = Foo
6+ { -- | X
7+ fooX :: Int,
8+ -- | Y
9+ fooY :: Int,
10+ -- | BarBaz
11+ fooBar, fooBaz :: NonEmpty (Identity Bool),
12+ -- | GagGog
13+ fooGag,
14+ fooGog ::
15+ NonEmpty
16+ ( Indentity
17+ Bool
18+ ),
19+ -- | Huh!
20+ fooFoo,
21+ barBar ::
22+ Int
23+ }
2324 deriving (Eq, Show)
data/examples/declaration/data/simple-broken-out.hs+2−1
@@ -1,7 +1,8 @@
11module Main where
22
33-- | Here we go.
4−data Foo = Foo {unFoo :: Int}
4+data Foo
5+ = Foo {unFoo :: Int}
56 deriving (Eq)
67
78-- | And once again.
data/examples/declaration/data/unnamed-field-comment-0-out.hsdeleted−7
@@ -1,7 +0,0 @@
1−data Foo
2− = -- | Bar
3− Bar
4− Field1
5− -- ^ Field 1
6− Field2
7− -- ^ Field 2
data/examples/declaration/data/unnamed-field-comment-0.hsdeleted−5
@@ -1,5 +0,0 @@
1−data Foo
2− = -- | Bar
3− Bar
4− Field1 -- ^ Field 1
5− Field2 -- ^ Field 2
data/examples/declaration/data/unnamed-field-comment-1-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−data X
2− = B
3− !Int
4− -- ^ y
5− C
data/examples/declaration/data/unnamed-field-comment-1.hsdeleted−4
@@ -1,4 +0,0 @@
1−data X
2− = B
3− !Int -- ^ y
4− C
data/examples/declaration/data/with-comment-out.hsdeleted−4
@@ -1,4 +0,0 @@
1−data A
2− = B -- C
3− | -- D
4− E
data/examples/declaration/data/with-comment.hsdeleted−5
@@ -1,5 +0,0 @@
1−data A =
2− B -- C
3−
4− -- D
5− | E
data/examples/declaration/data/with-weird-haddock-out.hsdeleted−4
@@ -1,4 +0,0 @@
1−data PlusLevel' t
2− = -- | @n + ℓ@.
3− Plus Integer (LevelAtom' t)
4− deriving (Show, Data)
data/examples/declaration/data/with-weird-haddock.hsdeleted−2
@@ -1,2 +0,0 @@
1−data PlusLevel' t = Plus Integer (LevelAtom' t) -- ^ @n + ℓ@.
2− deriving (Show, Data)
data/examples/declaration/instance/data-family-instances-gadt-out.hs+2−4
@@ -3,11 +3,9 @@
33
44data instance Bar Int a where
55 SameBar ::
6− Bar
7− Int
6+ Bar Int
87 Int
98 CloseBar :: Bar Int Double
109 OtherBar ::
11− Bar
12− Int
10+ Bar Int
1311 a
data/examples/declaration/instance/data-family-instances-newtype-out.hs+4−3
@@ -1,6 +1,7 @@
11{-# LANGUAGE GADTSyntax #-}
22{-# LANGUAGE TypeFamilies #-}
33
4−newtype instance Foo [Double] = DoubleListFoo
5− { unDoubleListFoo :: Double
6− }
4+newtype instance Foo [Double]
5+ = DoubleListFoo
6+ { unDoubleListFoo :: Double
7+ }
data/examples/declaration/signature/standalone-kind-out.hsdeleted−13
@@ -1,13 +0,0 @@
1−{-# LANGUAGE StandaloneKindSignatures #-}
2−
3−type T ::
4− (k -> Type) ->
5− k ->
6− Type
7−data T m a = MkT (m a) (T Maybe (m a))
8−
9−type C1 :: Type -> Constraint
10−class C1 a
11−
12−type F :: Type -> Type
13−type family F
data/examples/declaration/signature/standalone-kind.hsdeleted−13
@@ -1,13 +0,0 @@
1−{-# LANGUAGE StandaloneKindSignatures #-}
2−
3−type T :: (k -> Type)
4− -> k
5− -> Type
6−
7−data T m a = MkT (m a) (T Maybe (m a))
8−
9−type C1 :: Type -> Constraint
10−class C1 a
11−
12−type F :: Type -> Type
13−type family F
data/examples/declaration/signature/type/infix-promoted-type-constructor-out.hs+1
@@ -1,2 +1,3 @@
11fun1 :: Def ('[Ref s (Stored Uint32), IBool] 'T.:-> IBool)
2+
23fun2 :: Def ('[Ref s (Stored Uint32), IBool] ':-> IBool)
data/examples/declaration/signature/type/multi-value-out.hs−5
@@ -2,11 +2,6 @@ foo, bar :: Int
22foo = 1
33bar = 2
44
5−a, b, c :: Int
6−a = 1
7−b = 2
8−c = 3
9−
105foo,
116 bar,
127 baz ::
data/examples/declaration/signature/type/multi-value.hs−5
@@ -2,11 +2,6 @@ foo, bar :: Int
22foo = 1
33bar = 2
44
5−a, b, c :: Int
6−a = 1
7−b = 2
8−c = 3
9−
105foo,
116 bar,
127 baz :: Int
data/examples/declaration/signature/type/unrelated-out.hsdeleted−4
@@ -1,4 +0,0 @@
1−clientFunc1 :: SomeType1
2−clientFunc2 :: SomeType2
3−clientFunc3 :: SomeType3
4−clientFunc1 :<|> clientFunc2 :<|> clientFunc3 = hoistClient foo bar baz
data/examples/declaration/signature/type/unrelated.hsdeleted−4
@@ -1,4 +0,0 @@
1−clientFunc1 :: SomeType1
2−clientFunc2 :: SomeType2
3−clientFunc3 :: SomeType3
4−clientFunc1 :<|> clientFunc2 :<|> clientFunc3 = hoistClient foo bar baz
data/examples/declaration/splice/grouped-splices-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−$(deriveJSON fieldLabelMod ''A)
2−$(deriveJSON fieldLabelMod ''B)
3−$(deriveJSON fieldLabelMod ''C)
data/examples/declaration/splice/grouped-splices.hsdeleted−3
@@ -1,3 +0,0 @@
1−$(deriveJSON fieldLabelMod ''A)
2−$(deriveJSON fieldLabelMod ''B)
3−$(deriveJSON fieldLabelMod ''C)
data/examples/declaration/splice/splice-decl.hs+1
@@ -15,3 +15,4 @@ foo bar
1515-- TemplateHaskell allows Q () at the top level
1616do
1717 pure []
18+
data/examples/declaration/type-families/closed-type-family/multi-line-out.hs+5−6
@@ -1,7 +1,7 @@
11type family
22 Id a =
3− result | result -> a
4− where
3+ result
4+ | result -> a where
55 Id a =
66 a
77
@@ -10,15 +10,14 @@ type family
1010 (a :: k)
1111 b
1212 c =
13− foo | foo -> k b
14− where
13+ foo
14+ | foo -> k b where
1515 G a b c =
1616 (a, b)
1717
1818type family
1919 F a ::
20− * -> *
21− where
20+ * -> * where
2221 F Int = Double
2322 F Bool =
2423 Char
data/examples/declaration/type-synonyms/with-weird-haddock-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−type Elims =
2− -- | eliminations ordered left-to-right.
3− [Elim]
data/examples/declaration/type-synonyms/with-weird-haddock.hsdeleted−1
@@ -1 +0,0 @@
1−type Elims = [Elim] -- ^ eliminations ordered left-to-right.
data/examples/declaration/type/visible-forall-out.hsdeleted−2
@@ -1,2 +0,0 @@
1−-- source: https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0081-forall-arrow.rst
2−data T :: forall k -> k -> Type
data/examples/declaration/type/visible-forall.hsdeleted−2
@@ -1,2 +0,0 @@
1−-- source: https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0081-forall-arrow.rst
2−data T :: forall k -> k -> Type
data/examples/declaration/value/function/arg-breakpoints-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−foo
2− bar =
3− body
data/examples/declaration/value/function/arg-breakpoints.hsdeleted−3
@@ -1,3 +0,0 @@
1−foo
2− bar =
3− body
data/examples/declaration/value/function/arrow/expression-applications-out.hsnew file+9
@@ -0,0 +1,9 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo x y = x -< y
4+
5+bar f x =
6+ f x -< -- Hello
7+ x -- World
8+
9+baz x y = x -<< y
data/examples/declaration/value/function/arrow/expression-applications.hsnew file+9
@@ -0,0 +1,9 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo x y = x -< y
4+
5+bar f x
6+ = f x -- Hello
7+ -< x -- World
8+
9+baz x y = x -<< y
data/examples/declaration/value/function/arrow/expression-forms-out.hsnew file+14
@@ -0,0 +1,14 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo f g x y = (| test (f -< x) (g -< y) |)
4+
5+bar f g x y =
6+ (|
7+ test
8+ ( f -<
9+ x
10+ )
11+ ( g -<
12+ y
13+ )
14+ |)
data/examples/declaration/value/function/arrow/expression-forms.hsnew file+11
@@ -0,0 +1,11 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo f g x y = (| test (f -< x) (g -< y) |)
4+
5+bar f g x y = (|
6+ test
7+ (f
8+ -< x)
9+ (g
10+ -< y)
11+ |)
data/examples/declaration/value/function/arrow/multiline-case-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−{-# LANGUAGE Arrows #-}
2−
3−f = proc x -> do
4− x <-
5− case x of X -> x
6− -<
7− y
8− a -< b
data/examples/declaration/value/function/arrow/multiline-case.hsdeleted−7
@@ -1,7 +0,0 @@
1−{-# LANGUAGE Arrows #-}
2−
3−f = proc x -> do
4− x
5− <- case x of X -> x
6− -< y
7− a -< b
data/examples/declaration/value/function/arrow/proc-applications-out.hs+5−6
@@ -9,11 +9,10 @@ bar f x =
99 w
1010 )
1111 ->
12− f -- The value
13− -<
14− ( x, -- Foo
15− w, -- Bar
16− z -- Baz
17− )
12+ f -< -- The value
13+ ( x, -- Foo
14+ w, -- Bar
15+ z -- Baz
16+ )
1817
1918baz x = proc a -> a -<< x
data/examples/declaration/value/function/arrow/proc-do-complex-out.hs+14−18
@@ -19,11 +19,10 @@ foo
1919 )
2020 ( b,
2121 d
22+ ) -<
23+ ( b + 1, -- Funnel into arrow
24+ d * b
2225 )
23− -<
24− ( b + 1, -- Funnel into arrow
25− d * b
26− )
2726 if x `mod` y == 0 -- Basic condition
2827 then case e of -- Only left case is relevant
2928 Left
@@ -33,20 +32,18 @@ foo
3332 let v =
3433 u -- Actually never used
3534 ^ 2
36− in ( returnA
37− -<
38− -- Just do the calculation
39− (x + y * z)
35+ in ( returnA -<
36+ -- Just do the calculation
37+ (x + y * z)
4038 )
4139 else do
4240 let u = x -- Let bindings bind expressions, not commands
43− -- Could pattern match directly on x
41+ -- Could pattern match directly on x
4442 i <- case u of
4543 0 -> (g . h -< u)
4644 n ->
47− ( ( h . g
48− -<
49− y -- First actual use of y
45+ ( ( h . g -<
46+ y -- First actual use of y
5047 )
5148 )
5249 returnA -< ()
@@ -54,9 +51,8 @@ foo
5451 if i > 0
5552 then ma -< ()
5653 else returnA -< ()
57− returnA
58− -<
59− ( i
60− + x
61− * y -- Just do the calculation
62− )
54+ returnA -<
55+ ( i
56+ + x
57+ * y -- Just do the calculation
58+ )
data/examples/declaration/value/function/arrow/proc-do-simple1-out.hs+2−3
@@ -13,6 +13,5 @@ barbaz f g = proc (a, b) -> do
1313
1414bazbar f = proc a -> do
1515 a <-
16− f
17− -<
18− a
16+ f -<
17+ a
data/examples/declaration/value/function/arrow/proc-do-simple2-out.hs+7−9
@@ -11,12 +11,10 @@ bazbaz f g h = proc (a, b, c) -> do
1111 z <-
1212 h
1313 x
14− y
15− -<
16− ( a,
17− b,
18− c
19− )
20− returnA
21− -<
22− (x, y, z)
14+ y -<
15+ ( a,
16+ b,
17+ c
18+ )
19+ returnA -<
20+ (x, y, z)
data/examples/declaration/value/function/arrow/proc-forms1-out.hs+6−8
@@ -7,15 +7,13 @@ foo1 f g h x =
77 (|
88 test
99 ( h f
10− . h g
11− -<
12− y x
13− . y z
10+ . h g -<
11+ y x
12+ . y z
1413 )
1514 ( h g
16− . h f
17− -<
18− y z
19− . y x
15+ . h f -<
16+ y z
17+ . y x
2018 )
2119 |)
data/examples/declaration/value/function/arrow/proc-forms2-out.hs+6−10
@@ -4,19 +4,15 @@ bar0 f g h x =
44 proc (y, z) ->
55 (| test (h f . (h g) -< (y x) . y z) ((h g) . h f -< y z . (y x)) |)
66
7−bar1 f g x y = proc _ -> (f -< x) &&& (g -< y)
7+bar1 f g x y = proc _ -> f -< x &&& g -< y
88
99bar2 f g h x =
1010 proc (y, z) ->
11− (h f . (h g) -< (y x) . y z) ||| ((h g) . h f -< y z . (y x))
11+ h f . (h g) -< (y x) . y z ||| (h g) . h f -< y z . (y x)
1212
1313bar3 f g h x =
1414 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− )
15+ (h f . h g) -<
16+ (y x) . y z
17+ ||| (h g . h f) -<
18+ y z . (y x)
data/examples/declaration/value/function/arrow/proc-forms2.hs+6−6
@@ -4,16 +4,16 @@ bar0 f g h x =
44 proc (y, z) ->
55 (| test (h f.(h g) -< (y x).y z)((h g) . h f-<y z . (y x)) |)
66
7−bar1 f g x y = proc _ -> (f -< x)&&&(g -< y)
7+bar1 f g x y = proc _ -> f -< x&&&g -< y
88
99bar2 f g h x =
1010 proc (y, z) ->
11− (h f.(h g) -< (y x).y z) ||| ((h g) . h f-<y z . (y x))
11+ h f.(h g) -< (y x).y z ||| (h g) . h f-<y z . (y x)
1212
1313bar3 f g h x =
1414 proc (y, z) ->
15− ((h f.h g)
16− -< (y x).y z)
15+ (h f.h g)
16+ -< (y x).y z
1717 |||
18− ((h g . h f)
19− -<y z . (y x))
18+ (h g . h f)
19+ -<y z . (y x)
data/examples/declaration/value/function/arrow/proc-ifs-out.hs+4−6
@@ -6,10 +6,8 @@ bar f g = proc a ->
66 if f a
77 then
88 f
9− . g
10− -<
11− a
9+ . g -<
10+ a
1211 else
13− g
14− -<
15− b
12+ g -<
13+ b
data/examples/declaration/value/function/arrow/proc-parentheses-out.hs+4−5
@@ -6,14 +6,13 @@ bar f g = proc a ->
66 ( ( (f)
77 ( g
88 )
9− )
10− -<
11− ( ( ( ( ( ( g
12− a
13− )
9+ ) -<
10+ ( ( ( ( ( ( g
11+ a
1412 )
1513 )
1614 )
1715 )
1816 )
17+ )
1918 )
data/examples/declaration/value/function/arrow/recursive-procs-out.hs+10−14
@@ -3,21 +3,17 @@
33foo f g = proc (x, y) -> do
44 rec a <- f y -< x
55 b <-
6− g x
7− -<
8− y
9− bar
10− -<
11− ( a,
12− b
13− )
6+ g x -<
7+ y
8+ bar -<
9+ ( a,
10+ b
11+ )
1412 rec p <-
1513 f
16− p
17− -<
18− a
14+ p -<
15+ a
1916 rec q <-
2017 g
21− q
22− -<
23− b
18+ q -<
19+ b
data/examples/declaration/value/function/awkward-comment-0-out.hsdeleted−6
@@ -1,6 +0,0 @@
1−mergeErrorReply :: ParseError -> Reply s u a -> Reply s u a
2−mergeErrorReply err1 reply -- XXX where to put it?
3− =
4− case reply of
5− Ok x state err2 -> Ok x state (mergeError err1 err2)
6− Error err2 -> Error (mergeError err1 err2)
data/examples/declaration/value/function/awkward-comment-0.hsdeleted−5
@@ -1,5 +0,0 @@
1−mergeErrorReply :: ParseError -> Reply s u a -> Reply s u a
2−mergeErrorReply err1 reply -- XXX where to put it?
3− = case reply of
4− Ok x state err2 -> Ok x state (mergeError err1 err2)
5− Error err2 -> Error (mergeError err1 err2)
data/examples/declaration/value/function/awkward-comment-1-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−doForeign :: Vars -> [Name] -> [Term] -> Idris LExp
2−doForeign x = x
3− where
4− splitArg tm | (_, [_, _, l, r]) <- unApply tm -- pair, two implicits
5− =
6− do
7− let l' = toFDesc l
8− r' <- irTerm (sMN 0 "__foreignCall") vs env r
9− return (l', r')
data/examples/declaration/value/function/awkward-comment-1.hsdeleted−7
@@ -1,7 +0,0 @@
1−doForeign :: Vars -> [Name] -> [Term] -> Idris LExp
2−doForeign x = x
3− where
4− splitArg tm | (_, [_,_,l,r]) <- unApply tm -- pair, two implicits
5− = do let l' = toFDesc l
6− r' <- irTerm (sMN 0 "__foreignCall") vs env r
7− return (l', r')
data/examples/declaration/value/function/blank-lines-let-out.hsdeleted−6
@@ -1,6 +0,0 @@
1−foo =
2− let x = 10
3−
4− y = 11
5− z = 12
6− in x + y + z
data/examples/declaration/value/function/blank-lines-let.hsdeleted−9
@@ -1,9 +0,0 @@
1−foo =
2− let
3−
4− x = 10
5−
6− y = 11
7− z = 12
8−
9− in x + y + z
data/examples/declaration/value/function/blank-lines-where-out.hsdeleted−6
@@ -1,6 +0,0 @@
1−foo = x + y + z
2− where
3− x = 10
4−
5− y = 11
6− z = 12
data/examples/declaration/value/function/blank-lines-where.hsdeleted−7
@@ -1,7 +0,0 @@
1−foo = x + y + z
2− where
3−
4− x = 10
5−
6− y = 11
7− z = 12
data/examples/declaration/value/function/do/blocks-out.hs−1
@@ -15,5 +15,4 @@ readInClause = do
1515 <|> do
1616 optional g_Semi
1717 void allspacing
18−
1918 return things
data/examples/declaration/value/function/do/comment-alignment-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−main = do
2− case blah of
3− Nothing -> return ()
4− Just xs -> do
5− forM_ xs foo
6− bar
7− -- and here it goes
8− unless bobla $
9− quux
data/examples/declaration/value/function/do/comment-alignment.hsdeleted−9
@@ -1,9 +0,0 @@
1−main = do
2− case blah of
3− Nothing -> return ()
4− Just xs -> do
5− forM_ xs foo
6− bar
7− -- and here it goes
8− unless bobla $
9− quux
data/examples/declaration/value/function/do/comment-spacing-out.hsdeleted−7
@@ -1,7 +0,0 @@
1−foo = do
2− bar
3− -- foo
4− baz
5−
6− -- foo
7− quux
data/examples/declaration/value/function/do/comment-spacing.hsdeleted−7
@@ -1,7 +0,0 @@
1−foo = do
2− bar
3− -- foo
4− baz
5−
6− -- foo
7− quux
data/examples/declaration/value/function/do/recursive-do-rec-out.hs−5
@@ -2,18 +2,13 @@
22
33foo = do
44 rec a <- b + 5
5−
65 let d = c
7−
86 b <- a * 5
9−
107 something
11−
128 c <- a + b
139 print c
1410 rec something $ do
1511 x <- a
1612 print x
17−
1813 y <- c
1914 print y
data/examples/declaration/value/function/if-with-comment-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−foo =
2− if undefined
3− then -- then comment
4− undefined
5− else -- else comment
6−
7− do
8− undefined
data/examples/declaration/value/function/if-with-comment.hsdeleted−8
@@ -1,8 +0,0 @@
1−foo =
2− if undefined
3− -- then comment
4− then undefined
5− -- else comment
6− else
7− do
8− undefined
data/examples/declaration/value/function/implicit-params-out.hs−1
@@ -1,7 +1,6 @@
11{-# LANGUAGE ImplicitParams #-}
22
33sortBy :: (a -> a -> Bool) -> [a] -> [a]
4−sortBy = undefined
54
65sort :: (?cmp :: a -> a -> Bool) => [a] -> [a]
76sort = sortBy ?cmp
data/examples/declaration/value/function/implicit-params.hs−2
@@ -1,8 +1,6 @@
11{-# LANGUAGE ImplicitParams #-}
22sortBy :: (a -> a -> Bool) -> [a] -> [a]
33
4−sortBy = undefined
5−
64sort :: (?cmp :: a -> a -> Bool) => [a] -> [a]
75sort = sortBy ?cmp
86
data/examples/declaration/value/function/infix/dollar-chains-out.hs+3−3
@@ -13,9 +13,9 @@ foo =
1313 throwIO (OrmoluCppEnabled path)
1414
1515foo =
16− bar $
17− baz $
18− quux
16+ bar
17+ $ baz
18+ $ quux
1919
2020x =
2121 case l of { A -> B } $
data/examples/declaration/value/function/infix/hanging-out.hs+3−4
@@ -17,7 +17,6 @@ update =
1717 `catch` \case
1818 a -> a
1919
20−foo =
21− bar
22− ++ case foo of
23− a -> a
20+foo = bar
21+ ++ case foo of
22+ a -> a
data/examples/declaration/value/function/infix/lenses-out.hs+7−8
@@ -1,12 +1,11 @@
11lenses =
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− # []
2+ Just $ M.fromList $
3+ "type" .= ("user.connection" :: Text)
4+ # "connection" .= uc
5+ # "user" .= case name of
6+ Just n -> Just $ object ["name" .= n]
7+ Nothing -> Nothing
8+ # []
109
1110foo =
1211 a
data/examples/declaration/value/function/let-single-line-out.hs+1
@@ -5,6 +5,7 @@ foo x = let x = z where { z = 2 }; a = 3 in x
55foo x = let g :: Int -> Int; g = id in ()
66
77let a = b; c = do { foo; bar }; d = baz in b
8+
89let a = case True of { True -> foo; False -> bar }; b = foo a in b
910
1011foo x = let ?g = id; ?f = g in x
data/examples/declaration/value/function/list-notation-0-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−foo =
2− testCase "Foo" testFoo :
3− testCase "Bar" testBar :
4− testCase "Baz" testBaz :
5− []
data/examples/declaration/value/function/list-notation-0.hsdeleted−5
@@ -1,5 +0,0 @@
1−foo =
2− testCase "Foo" testFoo :
3− testCase "Bar" testBar :
4− testCase "Baz" testBaz :
5− []
data/examples/declaration/value/function/list-notation-1-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−instance A.ToJSON UpdateTable where
2− toJSON a =
3− A.object $
4− "TableName" .= updateTableName a :
5− "ProvisionedThroughput" .= updateProvisionedThroughput a :
6− case updateGlobalSecondaryIndexUpdates a of
7− [] -> []
8− l -> ["GlobalSecondaryIndexUpdates" .= l]
data/examples/declaration/value/function/list-notation-1.hsdeleted−7
@@ -1,7 +0,0 @@
1−instance A.ToJSON UpdateTable where
2− toJSON a = A.object
3− $ "TableName" .= updateTableName a
4− : "ProvisionedThroughput" .= updateProvisionedThroughput a
5− : case updateGlobalSecondaryIndexUpdates a of
6− [] -> []
7− l -> [ "GlobalSecondaryIndexUpdates" .= l ]
data/examples/declaration/value/function/list-notation-2-out.hsdeleted−6
@@ -1,6 +0,0 @@
1−-- A list of the element and all its parents up to the root node.
2−getPath tree t =
3− t :
4− case Map.lookup (getId t) tree of
5− Nothing -> []
6− Just parent -> getPath tree parent
data/examples/declaration/value/function/list-notation-2.hsdeleted−5
@@ -1,5 +0,0 @@
1−-- A list of the element and all its parents up to the root node.
2−getPath tree t = t :
3− case Map.lookup (getId t) tree of
4− Nothing -> []
5− Just parent -> getPath tree parent
data/examples/declaration/value/function/list-notation-3-out.hsdeleted−12
@@ -1,12 +0,0 @@
1−foo =
2− reportSDoc "tc.cc" 30 $
3− sep $ do
4− (prettyTCM q <+> " before compilation") : do
5− map (prettyTCM . map unArg . clPats) cls
6−
7−foo =
8− reportSDoc "tc.cc" 30 $
9− sep $ do
10− (prettyTCM q <+> " before compilation") :
11− do
12− map (prettyTCM . map unArg . clPats) cls
data/examples/declaration/value/function/list-notation-3.hsdeleted−10
@@ -1,10 +0,0 @@
1−foo =
2− reportSDoc "tc.cc" 30 $ sep $ do
3− (prettyTCM q <+> " before compilation") : do
4− map (prettyTCM . map unArg . clPats) cls
5−
6−foo =
7− reportSDoc "tc.cc" 30 $ sep $ do
8− (prettyTCM q <+> " before compilation") :
9− do
10− map (prettyTCM . map unArg . clPats) cls
data/examples/declaration/value/function/multi-way-if-out.hs+2−4
@@ -3,14 +3,12 @@
33foo x = if | x == 5 -> 5
44
55bar x y =
6− if
7− | x > y -> x
6+ if | x > y -> x
87 | x < y ->
98 y
109 | otherwise -> x
1110
1211baz =
13− if
14− | p -> f
12+ if | p -> f
1513 | otherwise -> g
1614 x
data/examples/declaration/value/function/operator-comments-2-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−x =
2− y
3− ++ f g -- commentA
4− -- commentB
5− -- commentC
data/examples/declaration/value/function/operator-comments-2.hsdeleted−4
@@ -1,4 +0,0 @@
1−x =
2− y ++ -- commentA
3−-- commentB
4− f g -- commentC
data/examples/declaration/value/function/operators-1-out.hsdeleted−4
@@ -1,4 +0,0 @@
1−foo =
2− f
3− . g
4− =<< h . i
data/examples/declaration/value/function/operators-1.hsdeleted−3
@@ -1,3 +0,0 @@
1−foo = f
2− . g
3− =<< h . i
data/examples/declaration/value/function/operators-2-out.hsdeleted−4
@@ -1,4 +0,0 @@
1−foo n
2− | x || y && z || n ** x
3− || x && n =
4− 42
data/examples/declaration/value/function/operators-2.hsdeleted−4
@@ -1,4 +0,0 @@
1−foo n
2− | x || y && z || n ** x
3− || x && n =
4− 42
data/examples/declaration/value/function/operators-3-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−foo =
2− op <> n <+> colon <+> prettySe <+> text "="
3− <+> prettySe <> text sc
data/examples/declaration/value/function/operators-3.hsdeleted−3
@@ -1,3 +0,0 @@
1−foo =
2− op <> n <+> colon <+> prettySe <+> text "=" <+>
3− prettySe <> text sc
data/examples/declaration/value/function/operators-4-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−foo =
2− line <> bindingOf <+> text "=" <+> tPretty <+> colon
3− <+> align <> prettyPs
data/examples/declaration/value/function/operators-4.hsdeleted−3
@@ -1,3 +0,0 @@
1−foo =
2− line <> bindingOf <+> text "=" <+> tPretty <+> colon <+>
3− align <> prettyPs
data/examples/declaration/value/function/operators-5-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−foo =
2− map bar $
3− [ baz
4− ]
5− ++ quux
data/examples/declaration/value/function/operators-5.hsdeleted−4
@@ -1,4 +0,0 @@
1−foo =
2− map bar $
3− [ baz
4− ] ++ quux
data/examples/declaration/value/function/operators-6-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−type PermuteRef =
2− "a"
3− :> ( "b" :> "c" :> End
4− :<|> "c" :> "b" :> End
5− )
6− :<|> "b"
7− :> ( "a" :> "c" :> End
8− :<|> "c" :> "a" :> End
9− )
data/examples/declaration/value/function/operators-6.hsdeleted−7
@@ -1,7 +0,0 @@
1−type PermuteRef =
2− "a" :> ( "b" :> "c" :> End
3− :<|> "c" :> "b" :> End
4− )
5− :<|> "b" :> ( "a" :> "c" :> End
6− :<|> "c" :> "a" :> End
7− )
data/examples/declaration/value/function/operators-0-out.hs → data/examples/declaration/value/function/operators-out.hsrenamed

The content is the same.

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

The content is the same.

data/examples/declaration/value/function/pattern/famous-cardano-pattern-out.hs+8−8
@@ -1,8 +1,8 @@
1−( getNodeSettingsR
2− :<|> getNodeInfoR
3− :<|> getNextUpdateR
4− :<|> restartNodeR
5− )
6− :<|> ( getUtxoR
7− :<|> getConfirmedProposalsR
8− ) = client nodeV1Api
1+( getNodeSettingsR :<|>
2+ getNodeInfoR :<|>
3+ getNextUpdateR :<|>
4+ restartNodeR
5+ ) :<|>
6+ ( getUtxoR :<|>
7+ getConfirmedProposalsR
8+ ) = client nodeV1Api
data/examples/declaration/value/function/pattern/multiline-case-pattern-out.hs+2−2
@@ -10,6 +10,6 @@ f xs = case xs of
1010 ] -> a + b
1111
1212g xs = case xs of
13− ( a
14− : bs
13+ ( a :
14+ bs
1515 ) -> a + b
data/examples/declaration/value/function/pattern/view-pattern-out.hs+3
@@ -13,3 +13,6 @@ multiline
1313 bar
1414 baz
1515 ) = True
16+
17+-- https://github.com/tweag/ormolu/issues/343
18+foo = (f -> 4)
data/examples/declaration/value/function/pattern/view-pattern.hs+3
@@ -10,3 +10,6 @@ g ((f, _), f -> 4) = True
1010multiline (t -> Foo
1111 bar
1212 baz) = True
13+
14+-- https://github.com/tweag/ormolu/issues/343
15+foo = (f -> 4)
data/examples/declaration/value/function/record/constructors-out.hs → data/examples/declaration/value/function/record-constructors-out.hsrenamed

The content is the same.

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

The content is the same.

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

The content is the same.

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

The content is the same.

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

The content is the same.

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

The content is the same.

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

The content is the same.

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

The content is the same.

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

The content is the same.

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

The content is the same.

data/examples/declaration/value/function/record/hanging-after-equal-con-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−foo =
2− Foo
3− { foo =
4− -- Blah blah
5− case x of
6− Blah -> 1
7− Blim -> 2
8− }
data/examples/declaration/value/function/record/hanging-after-equal-con.hsdeleted−7
@@ -1,7 +0,0 @@
1−foo = Foo
2− { foo =
3− -- Blah blah
4− case x of
5− Blah -> 1
6− Blim -> 2
7− }
data/examples/declaration/value/function/record/hanging-after-equal-update-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−foo =
2− foo
3− { foo =
4− -- Blah blah
5− case x of
6− Blah -> 1
7− Blim -> 2
8− }
data/examples/declaration/value/function/record/hanging-after-equal-update.hsdeleted−7
@@ -1,7 +0,0 @@
1−foo = foo
2− { foo =
3− -- Blah blah
4− case x of
5− Blah -> 1
6− Blim -> 2
7− }
data/examples/declaration/value/function/type-applications-and-splice-out.hsdeleted−4
@@ -1,4 +0,0 @@
1−{-# LANGUAGE TemplateHaskell #-}
2−{-# LANGUAGE TypeApplications #-}
3−
4−staticKey name = [|sing @ $(symFQN name)|]
data/examples/declaration/value/function/type-applications-and-splice.hsdeleted−4
@@ -1,4 +0,0 @@
1−{-# LANGUAGE TemplateHaskell #-}
2−{-# LANGUAGE TypeApplications #-}
3−
4−staticKey name = [| sing @ $(symFQN name) |]
data/examples/import/deduplication-bug-out.hsdeleted−6
@@ -1,6 +0,0 @@
1−import Foo1 (Bar1 (..), Baz1)
2−import Foo2 (Bar2 (..), Baz2)
3−import Foo3 (Bar3 (x1, x2, x3))
4−import Foo4 (Bar4 (x1, x2))
5−import Foo5 (Bar5 (x1))
6−import Foo6 (Bar6 (..))
data/examples/import/deduplication-bug.hsdeleted−6
@@ -1,6 +0,0 @@
1−import Foo1 (Bar1, Baz1, Bar1(..))
2−import Foo2 (Bar2(..), Baz2, Bar2)
3−import Foo3 (Bar3(x1,x3), Bar3(x1, x2))
4−import Foo4 (Bar4(x1), Bar4(x2))
5−import Foo5 (Bar5, Bar5(x1))
6−import Foo6 (Bar6(x1), Bar6(..))
data/examples/import/explicit-imports-out.hs+4−4
@@ -1,12 +1,12 @@
11import qualified MegaModule as M
2− ( Either,
2+ ( (<<<),
3+ (>>>),
4+ Either,
35 Maybe (Just, Nothing),
46 MaybeT (..),
5− Monad (return, (>>), (>>=)),
7+ Monad ((>>), (>>=), return),
68 MonadBaseControl,
79 join,
810 liftIO,
911 void,
10− (<<<),
11− (>>>),
1212 )
data/examples/import/explicit-imports-with-comments-out.hs+2−3
@@ -1,7 +1,6 @@
11import qualified MegaModule as M
22 ( -- (1)
3− -- (2)
4− Either, -- (3)
5− (<<<),
3+ (<<<), -- (2)
64 (>>>),
5+ Either, -- (3)
76 )
data/examples/import/merging-0-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−import Foo
2−import Foo (bar, foo)
3−import Foo as F
data/examples/import/merging-0.hsdeleted−4
@@ -1,4 +0,0 @@
1−import Foo
2−import Foo (foo)
3−import Foo (bar)
4−import Foo as F
data/examples/import/merging-1-out.hsdeleted−2
@@ -1,2 +0,0 @@
1−import "bar" Foo (bar)
2−import "foo" Foo (baz, foo)
data/examples/import/merging-1.hsdeleted−3
@@ -1,3 +0,0 @@
1−import "foo" Foo (foo)
2−import "bar" Foo (bar)
3−import "foo" Foo (baz)
data/examples/import/merging-2-out.hsdeleted−2
@@ -1,2 +0,0 @@
1−import Foo hiding (bar4, foo2)
2−import qualified Foo (bar3, foo1)
data/examples/import/merging-2.hsdeleted−4
@@ -1,4 +0,0 @@
1−import qualified Foo (foo1)
2−import Foo hiding (foo2)
3−import qualified Foo (bar3)
4−import Foo hiding (bar4)
data/examples/import/misc-out.hs+6
@@ -1,5 +1,11 @@
11import A hiding
22 ( foobarbazqux,
3+ foobarbazqux,
4+ foobarbazqux,
5+ foobarbazqux,
6+ foobarbazqux,
7+ foobarbazqux,
8+ foobarbazqux,
39 )
410import {-# SOURCE #-} safe qualified Module as M hiding (a, b, c, d, e, f)
511import Name hiding ()
data/examples/import/nested-explicit-imports-out.hs+6−6
@@ -1,10 +1,10 @@
11import qualified MegaModule as M
2− ( Either,
2+ ( (<<<),
3+ (>>>),
4+ Either,
35 Monad
4− ( return,
5− (>>),
6− (>>=)
6+ ( (>>),
7+ (>>=),
8+ return
79 ),
8− (<<<),
9− (>>>),
1010 )
data/examples/import/qualified-post-out.hsdeleted−5
@@ -1,5 +0,0 @@
1−{-# LANGUAGE ImportQualifiedPost #-}
2−
3−import Data.Text qualified (a, b, c)
4−import Data.Text qualified hiding (a, b, c)
5−import Data.Text qualified as T
data/examples/import/qualified-post.hsdeleted−5
@@ -1,5 +0,0 @@
1−{-# LANGUAGE ImportQualifiedPost #-}
2−
3−import qualified Data.Text as T
4−import qualified Data.Text (a, c, b)
5−import Data.Text qualified hiding (c, b, a)
data/examples/import/qualified-prelude-out.hs+1−1
@@ -1,4 +1,4 @@
11module P where
22
3−import Prelude hiding (id, (.))
3+import Prelude hiding ((.), id)
44import qualified Prelude
data/examples/import/simple-out.hs+3−2
@@ -1,5 +1,6 @@
11import Data.Text
2+import Data.Text
3+import qualified Data.Text as T
4+import qualified Data.Text (a, b, c)
25import Data.Text (a, b, c)
36import Data.Text hiding (a, b, c)
4−import qualified Data.Text (a, b, c)
5−import qualified Data.Text as T
data/examples/import/simple.hs−2
@@ -4,5 +4,3 @@ import qualified Data.Text as T
44import qualified Data.Text (a, c, b)
55import Data.Text (a, b, c)
66import Data.Text hiding (c, b, a)
7−import Data.Text (a, b, c, b, a)
8−import Data.Text hiding (c, b, a, b, c)
data/examples/import/sorted-export-list-out.hsdeleted−1
@@ -1 +0,0 @@
1−import Linear.Vector (Additive (..), (*^), (^*))
data/examples/import/sorted-export-list.hsdeleted−1
@@ -1 +0,0 @@
1−import Linear.Vector (Additive (..), (*^), (^*))
data/examples/module-header/double-dot-with-names-out.hs+6−1
@@ -1,6 +1,11 @@
11{-# LANGUAGE PatternSynonyms #-}
22
3−module ExportSyntax (A (.., NoA), Q (F, ..), G (T, .., U)) where
3+module ExportSyntax
4+ ( A (.., NoA),
5+ Q (F, ..),
6+ G (T, .., U),
7+ )
8+where
49
510data A = A | B
611
data/examples/module-header/multiline2.hs+2−2
@@ -1,2 +1,2 @@
1−module Foo (
2− foo, bar, baz) where
1+module Foo
2+ (foo, bar, baz) where
data/examples/module-header/preceding-comment-with-haddock-out.hs+4−1
@@ -3,6 +3,9 @@
33-}
44
55-- | This is the module's Haddock.
6−module Main (main) where
6+module Main
7+ ( main,
8+ )
9+where
710
811main = return ()
data/examples/module-header/singleline-empty-out.hs+4−1
@@ -1,2 +1,5 @@
11-- | This demonstrates a BUG.
2−module Foo () where
2+module Foo
3+ (
4+ )
5+where
data/examples/module-header/stack-header-0-out.hs−1
@@ -3,5 +3,4 @@
33{-# LANGUAGE OverloadedStrings #-}
44
55main = return ()
6−
76-- stack runhaskell
data/examples/module-header/stack-header-1-out.hs−1
@@ -4,5 +4,4 @@
44{-# LANGUAGE OverloadedStrings #-}
55
66main = return ()
7−
87-- stack runhaskell
data/examples/module-header/warning-pragma-multiline-out.hs+4−1
@@ -1,6 +1,9 @@
11module Test
22 {-# DEPRECATED "This module is unstable" #-}
3− (foo, bar, baz)
3+ ( foo,
4+ bar,
5+ baz,
6+ )
47where
58
69import Blah
data/examples/module-header/warning-pragma-out.hs+1−3
@@ -1,5 +1,3 @@
11module Test
2− {-# WARNING
3− "This module is very internal"
4− #-}
2+ {-# WARNING "This module is very internal" #-}
53where
data/examples/other/argument-comment-out.hs+1
@@ -9,6 +9,7 @@ foo ::
99 -- | Foo
1010 Int ->
1111 Int
12+
1213foo ::
1314 Foo a =>
1415 -- | Foo
data/examples/other/comment-glued-together-out.hsdeleted−7
@@ -1,7 +0,0 @@
1−module Main (main) where
2−
3−-- | Foo.
4−
5−-- Bar
6−main :: IO ()
7−main = return ()
data/examples/other/comment-glued-together.hsdeleted−6
@@ -1,6 +0,0 @@
1−module Main (main) where
2−
3−{- | Foo. -}
4−-- Bar
5−main :: IO ()
6−main = return ()
data/examples/other/comment-trailing-space-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−data T
2− = {-
3−
4− some multi-line comment
5−
6− with empty lines
7−
8− -}
9− A
data/examples/other/comment-trailing-space.hsdeleted−9
@@ -1,9 +0,0 @@
1−data T
2− = {-
3−
4− some multi-line comment
5−
6− with empty lines
7−
8− -}
9− A
data/examples/other/comment-two-blocks-out.hs+2−2
@@ -2,7 +2,7 @@ newNames :: [(String, String)]
22newNames =
33 let (*) = flip (,)
44 in [ "Control" * "Monad"
5− -- Foo
5+ -- Foo
66
7− -- Bar
7+ -- Bar
88 ]
data/examples/other/cpp/continuation-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−foo :: Int
2−foo = 5
3−
4−#define message_for(a, b) \
5− printf(#a " and " #b ": We love you!\n")
6−
7−bar :: Int
8−bar = 6
data/examples/other/cpp/continuation.hsdeleted−8
@@ -1,8 +0,0 @@
1−foo :: Int
2−foo = 5
3−
4−#define message_for(a, b) \
5− printf(#a " and " #b ": We love you!\n")
6−
7−bar :: Int
8−bar = 6
data/examples/other/cpp/lonely-hash-out.hsdeleted−14
@@ -1,14 +0,0 @@
1−module Main (main) where
2−
3−import Data.Void
4−import Test.Hspec
5−import Test.Hspec.Megaparsec
6−import Text.Megaparsec
7−import Text.Megaparsec.Char
8−
9−# if !MIN_VERSION_base(4,13,0)
10−import Data.Semigroup ((<>))
11−# endif
12−
13−main :: IO ()
14−main = return ()
data/examples/other/cpp/lonely-hash.hsdeleted−14
@@ -1,14 +0,0 @@
1−module Main (main) where
2−
3−import Data.Void
4−import Test.Hspec
5−import Test.Hspec.Megaparsec
6−import Text.Megaparsec
7−import Text.Megaparsec.Char
8−
9−# if !MIN_VERSION_base(4,13,0)
10−import Data.Semigroup ((<>))
11−# endif
12−
13−main :: IO ()
14−main = return ()
data/examples/other/cpp/separation-0a-out.hsdeleted−7
@@ -1,7 +0,0 @@
1−instance Stream s => Monad (ParsecT e s m) where
2− return = pure
3− (>>=) = pBind
4−
5−#if !(MIN_VERSION_base(4,13,0))
6− fail = Fail.fail
7−#endif
data/examples/other/cpp/separation-0a.hsdeleted−6
@@ -1,6 +0,0 @@
1−instance Stream s => Monad (ParsecT e s m) where
2− return = pure
3− (>>=) = pBind
4−#if !(MIN_VERSION_base(4,13,0))
5− fail = Fail.fail
6−#endif
data/examples/other/cpp/separation-0b-out.hsdeleted−10
@@ -1,10 +0,0 @@
1−instance Stream s => Monad (ParsecT e s m) where
2− return = pure
3− (>>=) = pBind
4−
5−#if !(MIN_VERSION_base(4,13,0))
6− fail = Fail.fail
7−#endif
8−
9−foo :: Int
10−foo = undefined
data/examples/other/cpp/separation-0b.hsdeleted−9
@@ -1,9 +0,0 @@
1−instance Stream s => Monad (ParsecT e s m) where
2− return = pure
3− (>>=) = pBind
4−#if !(MIN_VERSION_base(4,13,0))
5− fail = Fail.fail
6−#endif
7−
8−foo :: Int
9−foo = undefined
data/examples/other/cpp/separation-1a-out.hsdeleted−12
@@ -1,12 +0,0 @@
1−decompressingPipe ::
2− (PrimMonad m, MonadThrow m, MonadResource m) =>
3− CompressionMethod ->
4− ConduitT ByteString ByteString m ()
5−decompressingPipe Store = C.awaitForever C.yield
6−decompressingPipe Deflate = Z.decompress $ Z.WindowBits (-15)
7−
8−#ifdef ENABLE_BZIP2
9−decompressingPipe BZip2 = BZ.bunzip2
10−#else
11−decompressingPipe BZip2 = throwM BZip2Unsupported
12−#endif
data/examples/other/cpp/separation-1a.hsdeleted−11
@@ -1,11 +0,0 @@
1−decompressingPipe
2− :: (PrimMonad m, MonadThrow m, MonadResource m)
3− => CompressionMethod
4− -> ConduitT ByteString ByteString m ()
5−decompressingPipe Store = C.awaitForever C.yield
6−decompressingPipe Deflate = Z.decompress $ Z.WindowBits (-15)
7−#ifdef ENABLE_BZIP2
8−decompressingPipe BZip2 = BZ.bunzip2
9−#else
10−decompressingPipe BZip2 = throwM BZip2Unsupported
11−#endif
data/examples/other/cpp/separation-1b-out.hsdeleted−15
@@ -1,15 +0,0 @@
1−decompressingPipe ::
2− (PrimMonad m, MonadThrow m, MonadResource m) =>
3− CompressionMethod ->
4− ConduitT ByteString ByteString m ()
5−decompressingPipe Store = C.awaitForever C.yield
6−decompressingPipe Deflate = Z.decompress $ Z.WindowBits (-15)
7−
8−#ifdef ENABLE_BZIP2
9−decompressingPipe BZip2 = BZ.bunzip2
10−#else
11−decompressingPipe BZip2 = throwM BZip2Unsupported
12−#endif
13−
14−foo :: Int
15−foo = undefined
data/examples/other/cpp/separation-1b.hsdeleted−14
@@ -1,14 +0,0 @@
1−decompressingPipe
2− :: (PrimMonad m, MonadThrow m, MonadResource m)
3− => CompressionMethod
4− -> ConduitT ByteString ByteString m ()
5−decompressingPipe Store = C.awaitForever C.yield
6−decompressingPipe Deflate = Z.decompress $ Z.WindowBits (-15)
7−#ifdef ENABLE_BZIP2
8−decompressingPipe BZip2 = BZ.bunzip2
9−#else
10−decompressingPipe BZip2 = throwM BZip2Unsupported
11−#endif
12−
13−foo :: Int
14−foo = undefined
data/examples/other/cpp/separation-2a-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−ffff, ffffffff :: Natural
2−
3−#ifdef HASKELL_ZIP_DEV_MODE
4−ffff = 200
5−ffffffff = 5000
6−#else
7−ffff = 0xffff
8−ffffffff = 0xffffffff
9−#endif
data/examples/other/cpp/separation-2a.hsdeleted−8
@@ -1,8 +0,0 @@
1−ffff, ffffffff :: Natural
2−#ifdef HASKELL_ZIP_DEV_MODE
3−ffff = 200
4−ffffffff = 5000
5−#else
6−ffff = 0xffff
7−ffffffff = 0xffffffff
8−#endif
data/examples/other/cpp/separation-2b-out.hsdeleted−11
@@ -1,11 +0,0 @@
1−ffff, ffffffff :: Natural
2−#ifdef HASKELL_ZIP_DEV_MODE
3−ffff = 200
4−ffffffff = 5000
5−#else
6−ffff = 0xffff
7−ffffffff = 0xffffffff
8−#endif
9−
10−foo :: Int
11−foo = undefined
data/examples/other/cpp/separation-2b.hsdeleted−11
@@ -1,11 +0,0 @@
1−ffff, ffffffff :: Natural
2−#ifdef HASKELL_ZIP_DEV_MODE
3−ffff = 200
4−ffffffff = 5000
5−#else
6−ffff = 0xffff
7−ffffffff = 0xffffffff
8−#endif
9−
10−foo :: Int
11−foo = undefined
data/examples/other/cpp/shifted-out.hsdeleted−21
@@ -1,21 +0,0 @@
1−sinkData h compression = do
2− (uncompressedSize, crc32, compressedSize) <-
3− case compression of
4− Store ->
5− withCompression
6− dataSink
7− Deflate ->
8− withCompression $
9− Z.compress 9 (Z.WindowBits (-15)) .| dataSink
10−#ifdef ENABLE_BZIP2
11− BZip2 -> withCompression $
12− BZ.bzip2 .| dataSink
13−#else
14− BZip2 -> throwM BZip2Unsupported
15−#endif
16− return
17− DataDescriptor
18− { ddCRC32 = fromIntegral crc32,
19− ddCompressedSize = compressedSize,
20− ddUncompressedSize = uncompressedSize
21− }
data/examples/other/cpp/shifted.hsdeleted−17
@@ -1,17 +0,0 @@
1−sinkData h compression = do
2− (uncompressedSize, crc32, compressedSize) <-
3− case compression of
4− Store -> withCompression
5− dataSink
6− Deflate -> withCompression $
7− Z.compress 9 (Z.WindowBits (-15)) .| dataSink
8−#ifdef ENABLE_BZIP2
9− BZip2 -> withCompression $
10− BZ.bzip2 .| dataSink
11−#else
12− BZip2 -> throwM BZip2Unsupported
13−#endif
14− return DataDescriptor
15− { ddCRC32 = fromIntegral crc32
16− , ddCompressedSize = compressedSize
17− , ddUncompressedSize = uncompressedSize }
data/examples/other/cpp/simple-import-out.hsdeleted−14
@@ -1,14 +0,0 @@
1−module Main (main) where
2−
3−import Data.Void
4−import Test.Hspec
5−import Test.Hspec.Megaparsec
6−import Text.Megaparsec
7−import Text.Megaparsec.Char
8−
9−#if !MIN_VERSION_base(4,13,0)
10−import Data.Semigroup ((<>))
11−#endif
12−
13−main :: IO ()
14−main = return ()
data/examples/other/cpp/simple-import.hsdeleted−14
@@ -1,14 +0,0 @@
1−module Main (main) where
2−
3−import Data.Void
4−import Test.Hspec
5−import Test.Hspec.Megaparsec
6−import Text.Megaparsec
7−import Text.Megaparsec.Char
8−
9−#if !MIN_VERSION_base(4,13,0)
10−import Data.Semigroup ((<>))
11−#endif
12−
13−main :: IO ()
14−main = return ()
data/examples/other/disabling/indented-fragment-out.hsdeleted−7
@@ -1,7 +0,0 @@
1−foo =
2− {- ORMOLU_DISABLE -}
3− testCase "Foo" testFoo :
4− testCase "Bar" testBar :
5− testCase "Baz" testBaz :
6− {- ORMOLU_ENABLE -}
7− []
data/examples/other/disabling/indented-fragment.hsdeleted−7
@@ -1,7 +0,0 @@
1−foo =
2− {- ORMOLU_DISABLE -}
3− testCase "Foo" testFoo :
4− testCase "Bar" testBar :
5− testCase "Baz" testBaz :
6− {- ORMOLU_ENABLE -}
7− []
data/examples/other/disabling/single-definition-out.hsdeleted−10
@@ -1,10 +0,0 @@
1−module Foo (foo, bar) where
2−
3−{- ORMOLU_DISABLE -}
4−foo :: Int -> Int
5−foo = (+5)
6−{- ORMOLU_ENABLE -}
7−
8−bar :: Bool -> Bool
9−bar True = True
10−bar False = True
data/examples/other/disabling/single-definition.hsdeleted−10
@@ -1,10 +0,0 @@
1−module Foo (foo,bar) where
2−
3−{- ORMOLU_DISABLE -}
4−foo :: Int -> Int
5−foo = (+5)
6−{- ORMOLU_ENABLE -}
7−
8−bar :: Bool -> Bool
9−bar True = True
10−bar False = True
data/examples/other/disabling/whole-file-out.hsdeleted−10
@@ -1,10 +0,0 @@
1−{- ORMOLU_DISABLE -}
2−
3−module Foo (foo,bar) where
4−
5−foo :: Int -> Int
6−foo = (+5)
7−
8−bar :: Bool -> Bool
9−bar True = True
10−bar False = True
data/examples/other/disabling/whole-file.hsdeleted−10
@@ -1,10 +0,0 @@
1−{- ORMOLU_DISABLE -}
2−
3−module Foo (foo,bar) where
4−
5−foo :: Int -> Int
6−foo = (+5)
7−
8−bar :: Bool -> Bool
9−bar True = True
10−bar False = True
data/examples/other/inline-comment-0-out.hsdeleted−3
@@ -1,3 +0,0 @@
1−x = ({-a-} b, c)
2−
3−y = ({-a-} b)
data/examples/other/inline-comment-0.hsdeleted−3
@@ -1,3 +0,0 @@
1−x = ({-a-}b, c)
2−
3−y = ({-a-}b)
data/examples/other/inline-comment-1-out.hsdeleted−12
@@ -1,12 +0,0 @@
1−showPs env ((n, _, Let _ t v) : bs) =
2− " " ++ show n ++ " : "
3− ++ showEnv env ({- normalise ctxt env -} t)
4− ++ " = "
5− ++ showEnv env ({- normalise ctxt env -} v)
6− ++ "\n"
7− ++ showPs env bs
8−showPs env ((n, _, b) : bs) =
9− " " ++ show n ++ " : "
10− ++ showEnv env ({- normalise ctxt env -} (binderTy b))
11− ++ "\n"
12− ++ showPs env bs
data/examples/other/inline-comment-1.hsdeleted−9
@@ -1,9 +0,0 @@
1−showPs env ((n, _, Let _ t v):bs)
2− = " " ++ show n ++ " : " ++
3− showEnv env ({- normalise ctxt env -} t) ++ " = " ++
4− showEnv env ({- normalise ctxt env -} v) ++
5− "\n" ++ showPs env bs
6−showPs env ((n, _, b):bs)
7− = " " ++ show n ++ " : " ++
8− showEnv env ({- normalise ctxt env -} (binderTy b)) ++
9− "\n" ++ showPs env bs
data/examples/other/multiline-forall-out.hs+2−1
@@ -12,7 +12,8 @@ data D
1212 )
1313 (x :: *)
1414 (y :: *).
15− D (f x y)
15+ D
16+ (f x y)
1617
1718data G where
1819 G ::
data/examples/other/multiple-blank-line-comment-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−module A where
2−
3−a =
4− b
5− [ f
6− {-,
7−
8− -}
9− ]
data/examples/other/multiple-blank-line-comment.hsdeleted−10
@@ -1,10 +0,0 @@
1−module A where
2−
3−a =
4− b
5− [ f
6− {-,
7−
8−
9− -}
10− ]
data/examples/other/pragma-comments-after-out.hsdeleted−4
@@ -1,4 +0,0 @@
1−{-# LANGUAGE AllowAmbiguousTypes #-}
2−{-# LANGUAGE ConstraintKinds #-}
3−-- TODO: Fix and delete this pragma
4−{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
data/examples/other/pragma-comments-after.hsdeleted−3
@@ -1,3 +0,0 @@
1−{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} -- TODO: Fix and delete this pragma
2−{-# LANGUAGE AllowAmbiguousTypes #-}
3−{-# LANGUAGE ConstraintKinds #-}
data/examples/other/pragma-comments-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−-- TODO This extension is probably too dangerous, remove it.
3−{-# LANGUAGE RecordWildCards #-}
4−-- Avoid warning produced by TH.
5−{-# OPTIONS_GHC -fno-warn-overlapping-patterns #-}
6−
7−-- | Header comment.
8−module Foo () where
data/examples/other/pragma-comments.hsdeleted−11
@@ -1,11 +0,0 @@
1−-- | Header comment.
2−
3−{-# LANGUAGE OverloadedStrings #-}
4−
5−-- Avoid warning produced by TH.
6−{-# OPTIONS_GHC -fno-warn-overlapping-patterns #-}
7−
8−-- TODO This extension is probably too dangerous, remove it.
9−{-# LANGUAGE RecordWildCards #-}
10−
11−module Foo () where
data/examples/other/pragma-out.hs+4−1
@@ -9,4 +9,7 @@
99{-# OPTIONS_HADDOCK prune, show-extensions #-}
1010
1111-- | Header comment.
12−module Foo () where
12+module Foo
13+ (
14+ )
15+where
data/examples/other/pragma-sorting-out.hs+2−1
@@ -1,9 +1,10 @@
11{-# LANGUAGE NondecreasingIndentation #-}
22{-# LANGUAGE ScopedTypeVariables #-}
33{-# LANGUAGE TypeFamilies #-}
4+{-# LANGUAGE NoMonoLocalBinds #-}
5+
46-- This gap is necessary for stylish Haskell not to re-arrange
57-- NoMonoLocalBinds before TypeFamilies
6−{-# LANGUAGE NoMonoLocalBinds #-}
78
89module Foo
910 ( bar,
default.nix+51−108
@@ -1,9 +1,7 @@
1−{ pkgs ? (import ./nix/nixpkgs { inherit system; })
2−, system ? builtins.currentSystem
3−, ormoluCompiler ? "ghc884" # the shell doesn't work with ghc8101 yet
4−}:
1+{ pkgs ? (import ./nix/nixpkgs) }:
52
63let
4+ ormoluCompiler = "ghc865";
75 source = pkgs.lib.sourceByRegex ./. [
86 "^.*\.md$"
97 "^app.*$"
@@ -16,71 +14,57 @@ let
1614 overrides = ormoluOverlay;
1715 };
1816 ormoluOverlay = self: super: {
19− "ormolu" = super.callCabal2nixWithOptions "ormolu" source "-fdev" { };
17+ "ormolu" = pkgs.haskell.lib.enableCabalFlag
18+ (super.callCabal2nix "ormolu" source { }) "dev";
19+ # Nixpkgs provides ghc-lib-parser-8.8.0.20190424, but we want
20+ # ghc-lib-parser-8.8.1. We disable Haddock generation because it's way
21+ # too slow.
22+ "ghc-lib-parser" = pkgs.haskell.lib.dontHaddock
23+ (super.callHackage "ghc-lib-parser" "8.8.1" { });
2024 };
2125 ormolize = import ./nix/ormolize {
2226 inherit pkgs;
2327 inherit haskellPackages;
2428 };
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"]);
29+ # NOTE We have to exclude some directories for some packages because
30+ # Ormolu needs files to be parsable by Haddock which is not always the
31+ # case. For example some tests and examples do not parse.
32+ excludedHackageDirs = {
33+ "aws" = ["Examples"];
34+ "distributed-process" = ["benchmarks"];
35+ "esqueleto" = ["test"];
36+ "fay" = ["examples"];
37+ "postgrest" = ["test"];
38+ };
4139 ormolizedPackages = doCheck:
4240 pkgs.lib.mapAttrs (name: p: ormolize {
4341 package = p;
4442 inherit doCheck;
45− expectedFailures =
46− if pkgs.lib.lists.any (x: x == name) expectedFailures
47− then ./expected-failures + "/${name}.txt"
48− else null;
43+ excludedDirs =
44+ if builtins.hasAttr name excludedHackageDirs
45+ then excludedHackageDirs.${name}
46+ else [];
4947 }) haskellPackages;
5048in {
5149 ormolu = haskellPackages.ormolu;
52− # We put the derivations in another attribute set to avoid building them
53− # when nix-build is run.
54− dev = {
55− ormoluShell =
56− haskellPackages.shellFor {
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 = [
68− haskellPackages.cabal-install
69− haskellPackages.ormolu
70− ];
71− };
50+ ormoluShell = haskellPackages.shellFor {
51+ packages = ps: [
52+ ps.ormolu
53+ ];
54+ buildInputs = [
55+ haskellPackages.cabal-install
56+ haskellPackages.ghcid
57+ ];
7258 };
7359 inherit ormoluOverlay ormoluCompiler;
7460 hackage = ormolizedPackages false;
7561 hackageTests = with pkgs.lib; pkgs.recurseIntoAttrs (
7662 let ps = [
77− "Agda"
7863 "QuickCheck"
7964 "ShellCheck"
8065 "aeson"
8166 "attoparsec"
8267 "aws"
83− "brick"
8468 "capability"
8569 "cassava"
8670 "conduit"
@@ -92,78 +76,37 @@ in {
9276 "hakyll"
9377 "haxl"
9478 "hedgehog"
95− "hledger"
9679 "hlint"
97− "http-client"
98− "idris"
99− "intero"
100− "leksah"
101− "lens"
10280 "megaparsec"
103− "optics"
10481 "ormolu"
105− "pandoc"
106− "parsec3"
107− "pipes"
82+ "optics"
10883 "postgrest"
109− "purescript"
11084 "servant"
11185 "servant-server"
112− "stack"
11386 "tensorflow"
11487 "text_1_2_4_0"
11588 "tls"
11689 "yesod-core"
90+
91+ # Comment idempotence issue
92+
93+ # "Agda"
94+ # "brick"
95+ # "hledger"
96+ # "http-client"
97+ # "idris"
98+ # "intero"
99+ # "leksah"
100+ # "pandoc"
101+ # "pipes"
102+ # "stack"
103+
104+ # Missing language extension
105+
106+ # "lens" #fixed in master
107+ # "purescript"
108+
117109 ];
118110 in listToAttrs (map (p: nameValuePair p (ormolizedPackages true).${p}) ps)
119111 );
120− regionTests = pkgs.stdenv.mkDerivation {
121− name = "ormolu-region-tests";
122− src = ./region-tests;
123− buildInputs = [
124− haskellPackages.ormolu
125− pkgs.diffutils
126− ];
127− doCheck = true;
128− buildPhase = ''
129− cp src.hs result-all-implicit.hs
130− ormolu --check-idempotence --mode inplace result-all-implicit.hs
131− cp src.hs result-all-explicit.hs
132− ormolu --check-idempotence --mode inplace --start-line 1 --end-line 18 result-all-explicit.hs
133− cp src.hs result-only-start.hs
134− ormolu --check-idempotence --mode inplace --start-line 1 result-only-start.hs
135− cp src.hs result-only-end.hs
136− ormolu --check-idempotence --mode inplace --end-line 18 result-only-end.hs
137− cp src.hs result-6-7.hs
138− ormolu --check-idempotence --mode inplace --start-line 6 --end-line 7 result-6-7.hs
139− cp src.hs result-6-8.hs
140− ormolu --check-idempotence --mode inplace --start-line 6 --end-line 8 result-6-8.hs
141− cp src.hs result-9-12.hs
142− ormolu --check-idempotence --mode inplace --start-line 9 --end-line 12 result-9-12.hs
143− cp src.hs result-17-18.hs
144− ormolu --check-idempotence --mode inplace --start-line 17 --end-line 18 result-17-18.hs
145− '';
146− checkPhase = ''
147− echo result-all-implicit.hs
148− diff --color=always expected-result-all.hs result-all-implicit.hs
149− echo result-all-explicit.hs
150− diff --color=always expected-result-all.hs result-all-explicit.hs
151− echo result-only-start.hs
152− diff --color=always expected-result-all.hs result-only-start.hs
153− echo result-only-end.hs
154− diff --color=always expected-result-all.hs result-only-end.hs
155− echo result-6-7.hs
156− diff --color=always expected-result-6-7.hs result-6-7.hs
157− echo result-6-8.hs
158− diff --color=always expected-result-6-8.hs result-6-8.hs
159− echo result-9-12.hs
160− diff --color=always expected-result-9-12.hs result-9-12.hs
161− echo result-17-18.hs
162− diff --color=always expected-result-17-18.hs result-17-18.hs
163− '';
164− installPhase = ''
165− mkdir "$out"
166− find . -name '*.hs' -exec cp --parents {} $out \;
167− '';
168− };
169112}
expected-failures/Agda.txtdeleted−11
@@ -1,11 +0,0 @@
1−Formatting is not idempotent:
2− dist/build/Agda/Syntax/Parser/Lexer.hs<rendered>:1602:17
3− before: " = (check_ac"
4− after: " =\n "
5−Please, consider reporting the bug.
6−
7−Formatting is not idempotent:
8− src/full/Agda/Syntax/Translation/InternalToAbstract.hs<rendered>:769:4
9− before: " nes\n\n "
10− after: " nes\n\n -- Andreas"
11−Please, consider reporting the bug.
expected-failures/aws.txtdeleted−9
@@ -1,9 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− Examples/PutBucketNearLine.hs:5:1-6
3− parse error on input `import'
4−
5−The GHC parser (in Haddock mode) failed:
6− Examples/Sqs.hs:(88,3)-(90,4)
7− parse error on input `{- | Let's make sure the queue was actually deleted and that the same number of queues exist at when
8− | the program ends as when it started.
9− -}'
expected-failures/distributed-process.txtdeleted−7
@@ -1,7 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− benchmarks/Channels.hs:2:1-6
3− parse error on input `import'
4−
5−The GHC parser (in Haddock mode) failed:
6− benchmarks/Spawns.hs:5:1-6
7− parse error on input `import'
expected-failures/esqueleto.txtdeleted−7
@@ -1,7 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− src/Database/Esqueleto/Internal/Internal.hs:379:1
3− lexical error in string/character literal at character 's'
4−
5−The GHC parser (in Haddock mode) failed:
6− test/PostgreSQL/Test.hs:562:9-41
7− parse error on input `-- | Check the result is not null'
expected-failures/fay.txtdeleted−18
@@ -1,18 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− examples/Separated.hs:12:1-6
3− parse error on input `module'
4−
5−The GHC parser (in Haddock mode) failed:
6− examples/calc.hs:(4,1)-(6,2)
7− parse error on input `-- $ fay -p --html-wrapper --html-js-lib jquery.min.js examples/calc.hs
8−-- You also need to download jquery.min.js.
9−--'
10−
11−The GHC parser (in Haddock mode) failed:
12− examples/canvaswater.hs:(6,1)-(7,17)
13− parse error on input `-- | A demonstration of Fay using the canvas element to display a
14−-- simple effect.'
15−
16−The GHC parser (in Haddock mode) failed:
17− examples/data.hs:9:1-6
18− parse error on input `module'
expected-failures/hlint.txtdeleted−11
@@ -1,11 +0,0 @@
1−Formatting is not idempotent:
2− src/Extension.hs<rendered>:19:22
3− before: "DoRec , -} Recursive"
4− after: "DoRec , -}\n "
5−Please, consider reporting the bug.
6−
7−Formatting is not idempotent:
8− src/Hint/Bracket.hs<rendered>:249:50
9− before: "\" x y [r]) {ideaSpan"
10− after: "\" x y [r])\n "
11−Please, consider reporting the bug.
expected-failures/idris.txtdeleted−7
@@ -1,7 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− src/Idris/Parser.hs:1052:1
3− parse error on input `@'
4−
5−The GHC parser (in Haddock mode) failed:
6− src/Idris/Parser/Expr.hs:75:1
7− parse error on input `@'
expected-failures/intero.txtdeleted−5
@@ -1,5 +0,0 @@
1−Formatting is not idempotent:
2− src/InteractiveUI.hs<rendered>:3748:33
3− before: "text \"Try\" <+> doWha"
4− after: "text \"Try\"\n "
5−Please, consider reporting the bug.
expected-failures/leksah.txtdeleted−5
@@ -1,5 +0,0 @@
1−Formatting is not idempotent:
2− src/IDE/Pane/Modules.hs<rendered>:1184:7
3− before: "cr\n -- show"
4− after: "cr\n in -- show"
5−Please, consider reporting the bug.
expected-failures/lens.txtdeleted−3
@@ -1,3 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− src/Control/Exception/Lens.hs:180:13-37
3− parse error on input `AllocationLimitExceeded__'
expected-failures/pandoc.txtdeleted−9
@@ -1,9 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− benchmark/weigh-pandoc.hs:14:1-6
3− parse error on input `import'
4−
5−Formatting is not idempotent:
6− src/Text/Pandoc/Readers/Vimwiki.hs<rendered>:613:19
7− before: ".softbreak <$ endlin"
8− after: ".softbreak\n <$ en"
9−Please, consider reporting the bug.
expected-failures/pipes.txtdeleted−3
@@ -1,3 +0,0 @@
1−AST of input and AST of formatted code differ.
2− at src/Pipes/Core.hs:(128,1)-(151,2)
3−Please, consider reporting the bug.
expected-failures/postgrest.txtdeleted−5
@@ -1,5 +0,0 @@
1−Formatting is not idempotent:
2− src/PostgREST/DbRequestBuilder.hs<rendered>:149:24
3− before: " || -- clients"
4− after: " || ( origin ="
5−Please, consider reporting the bug.
expected-failures/purescript.txtdeleted−18
@@ -1,18 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− src/Language/PureScript/AST/Declarations.hs:479:1-17
3− Invalid type signature: pattern ValueDecl :: ...
4−Perhaps you meant to use PatternSynonyms?
5−
6−The GHC parser (in Haddock mode) failed:
7− src/Language/PureScript/AST/SourcePos.hs:99:1-22
8− Invalid type signature: pattern NullSourceSpan :: ...
9−Perhaps you meant to use PatternSynonyms?
10−
11−The GHC parser (in Haddock mode) failed:
12− src/Language/PureScript/Constants.hs:42:1-15
13− Invalid type signature: pattern Discard :: ...
14−Perhaps you meant to use PatternSynonyms?
15−
16−The GHC parser (in Haddock mode) failed:
17− src/Language/PureScript/Crash.hs:16:1-6
18− parse error on input `import'
expected-failures/tensorflow.txtdeleted−7
@@ -1,7 +0,0 @@
1−The GHC parser (in Haddock mode) failed:
2− tensorflow-mnist/app/Main.hs:50:13-14
3− parse error on input `->'
4−
5−The GHC parser (in Haddock mode) failed:
6− tensorflow-ops/tests/RegressionTest.hs:3:1-6
7− parse error on input `import'
format.sh+3−6
@@ -1,5 +1,5 @@
11#!/usr/bin/env nix-shell
2−#!nix-shell default.nix -A dev.withOrmolu -i bash --pure
2+#!nix-shell -p "(import ./default.nix {}).ormolu" -i bash --pure
33#
44# Format Ormolu using current version of Ormolu.
55
@@ -7,8 +7,5 @@ set -e
77
88export LANG="C.UTF-8"
99
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")
10+ormolu --mode inplace $(find src -type f \( -name "*.hs" -o -name "*.hs-boot" \))
11+ormolu --mode inplace $(find tests -type f -name "*.hs")
nix/nixpkgs/default.nix+3−7
@@ -1,13 +1,9 @@
1−{ system ? builtins.currentSystem }:
21let
3− rev = "32b46dd897ab2143a609988a04d87452f0bbef59";
4− sha256 = "1gzfrpjnr1bz9zljsyg3a4zrhk8r927sz761mrgcg56dwinkhpjk";
2+ rev = "19.09";
3+ sha256 = "0mhqhq21y5vrr1f30qd2bvydv4bbbslvyzclhw0kdxmkgg3z4c92";
54 nixpkgs = builtins.fetchTarball {
65 url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
76 inherit sha256;
87 };
9− pkgs = import nixpkgs {
10− inherit system;
11− config.allowUnfree = true;
12− };
8+ pkgs = import nixpkgs { config.allowUnfree = true; };
139in pkgs
nix/ormolize/default.nix+13−29
@@ -2,48 +2,32 @@
22, haskellPackages
33}:
44{ package
5−, expectedFailures ? null
65, doCheck ? false
6+, excludedDirs ? []
77}:
88 pkgs.stdenv.mkDerivation rec {
99 name = package.name + "-ormolized";
1010 src = package.src;
1111 buildInputs = [
1212 haskellPackages.cpphs
13− haskellPackages.ormolu
14− pkgs.diffutils
13+ (if doCheck
14+ then haskellPackages.ormolu
15+ else pkgs.haskell.lib.dontCheck haskellPackages.ormolu)
1516 pkgs.glibcLocales
1617 ];
1718 LANG = "en_US.UTF-8";
19+ excludedDirsRendered =
20+ if excludedDirs == []
21+ then ""
22+ else pkgs.lib.concatMapStringsSep " " (x: "-not -path './" + x + "/*'") excludedDirs;
1823 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
24+ find . -name '*.hs' ${excludedDirsRendered} -exec bash ${./ormolize.sh} {} \; 2> log.txt
25+ cat log.txt
3626 '';
3727 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− '';
28+ checkPhase = ''
29+ if [[ -s log.txt ]]; then exit 1; fi
30+ '';
4731 installPhase = ''
4832 mkdir "$out"
4933 find . -name '*.hs-original' -exec cp --parents {} $out \;
nix/ormolize/ormolize.shnew file+17
@@ -0,0 +1,17 @@
1+set -euo pipefail
2+
3+# drop includes
4+sed -i '/^#include/d' "$1"
5+
6+# deal with CPP in a fairly straightforward way
7+cpphs "$1" --noline > "$1-nocpp" 2> /dev/null
8+
9+# annoyingly, cpphs cannot modify files in place
10+mv "$1-nocpp" "$1"
11+
12+# preserve the original
13+cp "$1" "$1-original"
14+
15+# run ormolu
16+ormolu --tolerate-cpp --check-idempotency --mode inplace "$1" ||
17+ ormolu --tolerate-cpp --unsafe --mode inplace "$1"
ormolu.cabal+157−174
@@ -1,184 +1,167 @@
1−cabal-version: 1.18
2−name: ormolu
3−version: 0.1.2.0
4−license: BSD3
5−license-file: LICENSE.md
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
9−bug-reports: https://github.com/tweag/ormolu/issues
10−synopsis: A formatter for Haskell source code
11−description: A formatter for Haskell source code.
12−category: Development, Formatting
13−build-type: Simple
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:
53− CONTRIBUTING.md
54− CHANGELOG.md
55− DESIGN.md
56− README.md
1+name: ormolu
2+version: 0.0.3.0
3+cabal-version: 1.18
4+tested-with: GHC==8.6.5
5+license: BSD3
6+license-file: LICENSE.md
7+maintainer: Mark Karpov <mark.karpov@tweag.io>
8+homepage: https://github.com/tweag/ormolu
9+bug-reports: https://github.com/tweag/ormolu/issues
10+category: Development, Formatting
11+synopsis: A formatter for Haskell source code
12+build-type: Simple
13+description: A formatter for Haskell source code.
14+extra-doc-files: CONTRIBUTING.md
15+ , CHANGELOG.md
16+ , DESIGN.md
17+ , README.md
18+data-files: data/examples/declaration/annotation/*.hs
19+ , data/examples/declaration/class/*.hs
20+ , data/examples/declaration/data/*.hs
21+ , data/examples/declaration/data/gadt/*.hs
22+ , data/examples/declaration/default/*.hs
23+ , data/examples/declaration/deriving/*.hs
24+ , data/examples/declaration/foreign/*.hs
25+ , data/examples/declaration/instance/*.hs
26+ , data/examples/declaration/rewrite-rule/*.hs
27+ , data/examples/declaration/role-annotation/*.hs
28+ , data/examples/declaration/signature/complete/*.hs
29+ , data/examples/declaration/signature/fixity/*.hs
30+ , data/examples/declaration/signature/inline/*.hs
31+ , data/examples/declaration/signature/minimal/*.hs
32+ , data/examples/declaration/signature/pattern/*.hs
33+ , data/examples/declaration/signature/set-cost-centre/*.hs
34+ , data/examples/declaration/signature/specialize/*.hs
35+ , data/examples/declaration/signature/type/*.hs
36+ , data/examples/declaration/splice/*.hs
37+ , data/examples/declaration/type-families/closed-type-family/*.hs
38+ , data/examples/declaration/type-families/data-family/*.hs
39+ , data/examples/declaration/type-families/type-family/*.hs
40+ , data/examples/declaration/type-synonyms/*.hs
41+ , data/examples/declaration/type/*.hs
42+ , data/examples/declaration/value/function/*.hs
43+ , data/examples/declaration/value/function/arrow/*.hs
44+ , data/examples/declaration/value/function/comprehension/*.hs
45+ , data/examples/declaration/value/function/do/*.hs
46+ , data/examples/declaration/value/function/infix/*.hs
47+ , data/examples/declaration/value/function/pattern/*.hs
48+ , data/examples/declaration/value/other/*.hs
49+ , data/examples/declaration/value/pattern-synonyms/*.hs
50+ , data/examples/declaration/warning/*.hs
51+ , data/examples/import/*.hs
52+ , data/examples/module-header/*.hs
53+ , data/examples/other/*.hs
5754
5855source-repository head
59− type: git
60− location: https://github.com/tweag/ormolu.git
56+ type: git
57+ location: https://github.com/tweag/ormolu.git
6158
6259flag dev
63− description: Turn on development settings.
64− default: False
65− manual: True
60+ description: Turn on development settings.
61+ manual: True
62+ default: False
6663
6764library
68− exposed-modules:
69− Ormolu
70− Ormolu.Config
71− Ormolu.Diff
72− Ormolu.Exception
73− Ormolu.Imports
74− Ormolu.Parser
75− Ormolu.Parser.Anns
76− Ormolu.Parser.CommentStream
77− Ormolu.Parser.Pragma
78− Ormolu.Parser.Result
79− Ormolu.Parser.Shebang
80− Ormolu.Printer
81− Ormolu.Printer.Combinators
82− Ormolu.Printer.Comments
83− Ormolu.Printer.Internal
84− Ormolu.Printer.Meat.Common
85− Ormolu.Printer.Meat.Declaration
86− Ormolu.Printer.Meat.Declaration.Annotation
87− Ormolu.Printer.Meat.Declaration.Class
88− Ormolu.Printer.Meat.Declaration.Data
89− Ormolu.Printer.Meat.Declaration.Default
90− Ormolu.Printer.Meat.Declaration.Foreign
91− Ormolu.Printer.Meat.Declaration.Instance
92− Ormolu.Printer.Meat.Declaration.RoleAnnotation
93− Ormolu.Printer.Meat.Declaration.Rule
94− Ormolu.Printer.Meat.Declaration.Signature
95− Ormolu.Printer.Meat.Declaration.Splice
96− Ormolu.Printer.Meat.Declaration.Type
97− Ormolu.Printer.Meat.Declaration.TypeFamily
98− Ormolu.Printer.Meat.Declaration.Value
99− Ormolu.Printer.Meat.Declaration.Warning
100− Ormolu.Printer.Meat.ImportExport
101− Ormolu.Printer.Meat.Module
102− Ormolu.Printer.Meat.Pragma
103− Ormolu.Printer.Meat.Type
104− Ormolu.Printer.Operators
105− Ormolu.Printer.SpanStream
106− Ormolu.Processing.Common
107− Ormolu.Processing.Cpp
108− Ormolu.Processing.Postprocess
109− Ormolu.Processing.Preprocess
110− Ormolu.Utils
111−
112− hs-source-dirs: src
113− other-modules:
114− GHC
115− GHC.DynFlags
116−
117− default-language: Haskell2010
118− build-depends:
119− base >=4.12 && <5.0,
120− bytestring >=0.2 && <0.11,
121− containers >=0.5 && <0.7,
122− dlist >=0.8 && <2.0,
123− exceptions >=0.6 && <0.11,
124− ghc-lib-parser >=8.10 && <8.11,
125− mtl >=2.0 && <3.0,
126− syb >=0.7 && <0.8,
127− text >=0.2 && <1.3
128−
129− if flag(dev)
130− ghc-options:
131− -Wall -Werror -Wcompat -Wincomplete-record-updates
132− -Wincomplete-uni-patterns -Wnoncanonical-monad-instances
133− -Wno-missing-home-modules
134−
135− else
136− ghc-options: -O2 -Wall
137−
138−executable ormolu
139− main-is: Main.hs
140− hs-source-dirs: app
141− other-modules: Paths_ormolu
142− default-language: Haskell2010
143− build-depends:
144− base >=4.12 && <5.0,
145− ghc-lib-parser >=8.10 && <8.11,
146− gitrev >=1.3 && <1.4,
147− optparse-applicative >=0.14 && <0.17,
148− ormolu -any,
149− text >=0.2 && <1.3
150−
151− if flag(dev)
152− ghc-options:
153− -Wall -Werror -Wcompat -Wincomplete-record-updates
154− -Wincomplete-uni-patterns -Wnoncanonical-monad-instances
155− -optP-Wno-nonportable-include-path
156−
157− else
158− ghc-options: -O2 -Wall -rtsopts
65+ hs-source-dirs: src
66+ build-depends: base >= 4.12 && < 5.0
67+ , bytestring >= 0.2 && < 0.11
68+ , containers >= 0.5 && < 0.7
69+ , dlist >= 0.8 && < 0.9
70+ , exceptions >= 0.6 && < 0.11
71+ , ghc-lib-parser >= 8.8.1 && < 8.8.2
72+ , mtl >= 2.0 && < 3.0
73+ , syb >= 0.7 && < 0.8
74+ , text >= 0.2 && < 1.3
75+ exposed-modules: Ormolu
76+ , Ormolu.Config
77+ , Ormolu.Diff
78+ , Ormolu.Exception
79+ , Ormolu.Imports
80+ , Ormolu.Parser
81+ , Ormolu.Parser.Anns
82+ , Ormolu.Parser.CommentStream
83+ , Ormolu.Parser.Pragma
84+ , Ormolu.Parser.Result
85+ , Ormolu.Printer
86+ , Ormolu.Printer.Combinators
87+ , Ormolu.Printer.Comments
88+ , Ormolu.Printer.Internal
89+ , Ormolu.Printer.Meat.Common
90+ , Ormolu.Printer.Meat.Declaration
91+ , Ormolu.Printer.Meat.Declaration.Annotation
92+ , Ormolu.Printer.Meat.Declaration.Class
93+ , Ormolu.Printer.Meat.Declaration.Data
94+ , Ormolu.Printer.Meat.Declaration.Default
95+ , Ormolu.Printer.Meat.Declaration.Foreign
96+ , Ormolu.Printer.Meat.Declaration.Instance
97+ , Ormolu.Printer.Meat.Declaration.RoleAnnotation
98+ , Ormolu.Printer.Meat.Declaration.Rule
99+ , Ormolu.Printer.Meat.Declaration.Signature
100+ , Ormolu.Printer.Meat.Declaration.Splice
101+ , Ormolu.Printer.Meat.Declaration.Type
102+ , Ormolu.Printer.Meat.Declaration.TypeFamily
103+ , Ormolu.Printer.Meat.Declaration.Value
104+ , Ormolu.Printer.Meat.Declaration.Warning
105+ , Ormolu.Printer.Meat.ImportExport
106+ , Ormolu.Printer.Meat.Module
107+ , Ormolu.Printer.Meat.Pragma
108+ , Ormolu.Printer.Meat.Type
109+ , Ormolu.Printer.Operators
110+ , Ormolu.Printer.SpanStream
111+ , Ormolu.Utils
112+ other-modules: GHC
113+ , GHC.DynFlags
114+ if flag(dev)
115+ ghc-options: -Wall -Werror -Wcompat
116+ -Wincomplete-record-updates
117+ -Wincomplete-uni-patterns
118+ -Wnoncanonical-monad-instances
119+ -Wnoncanonical-monadfail-instances
120+ -- https://github.com/haskell/haddock/issues/1116
121+ -Wno-missing-home-modules
122+ else
123+ ghc-options: -O2 -Wall
124+ default-language: Haskell2010
159125
160126test-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
127+ main-is: Spec.hs
128+ hs-source-dirs: tests
129+ type: exitcode-stdio-1.0
130+ build-depends: base >= 4.12 && < 5.0
131+ , containers >= 0.5 && < 0.7
132+ , filepath >= 1.2 && < 1.5
133+ , hspec >= 2.0 && < 3.0
134+ , ormolu
135+ , path >= 0.6 && < 0.7
136+ , path-io >= 1.4.2 && < 2.0
137+ , text >= 0.2 && < 1.3
138+ build-tools: hspec-discover >= 2.0 && < 3.0
139+ other-modules:
140+ Ormolu.Parser.PragmaSpec
141+ , Ormolu.PrinterSpec
168142
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
143+ if flag(dev)
144+ ghc-options: -Wall -Werror
145+ else
146+ ghc-options: -O2 -Wall
147+ default-language: Haskell2010
179148
180− if flag(dev)
181− ghc-options: -Wall -Werror
182−
183− else
184− ghc-options: -O2 -Wall
149+executable ormolu
150+ main-is: Main.hs
151+ hs-source-dirs: app
152+ build-depends: base >= 4.12 && < 5.0
153+ , ghc-lib-parser >= 8.8.1 && < 8.8.2
154+ , gitrev >= 1.3 && < 1.4
155+ , optparse-applicative >= 0.14 && < 0.15
156+ , ormolu
157+ , text >= 0.2 && < 1.3
158+ other-modules: Paths_ormolu
159+ if flag(dev)
160+ ghc-options: -Wall -Werror -Wcompat
161+ -Wincomplete-record-updates
162+ -Wincomplete-uni-patterns
163+ -Wnoncanonical-monad-instances
164+ -Wnoncanonical-monadfail-instances
165+ else
166+ ghc-options: -O2 -Wall
167+ default-language: Haskell2010
region-tests/expected-result-17-18.hsdeleted−17
@@ -1,17 +0,0 @@
1−{-# LANGUAGE LambdaCase #-}
2−
3−module Foo (
4− foo, bar, baz) where
5−
6−foo :: Int
7−foo = 5
8−
9−bar :: Int -> Int
10−bar = \case
11− 0 -> foo
12− x -> x - foo
13−
14−baz :: Int -> Int
15−baz = gege
16− where
17− gege = 1 + 2
region-tests/expected-result-6-7.hsdeleted−17
@@ -1,17 +0,0 @@
1−{-# LANGUAGE LambdaCase #-}
2−
3−module Foo (
4− foo, bar, baz) where
5−
6−foo :: Int
7−foo = 5
8−
9−bar :: Int -> Int
10−bar = \case
11− 0 -> foo
12− x -> x - foo
13−
14−baz :: Int -> Int
15−baz = gege
16− where
17− gege = 1 + 2
region-tests/expected-result-6-8.hsdeleted−16
@@ -1,16 +0,0 @@
1−{-# LANGUAGE LambdaCase #-}
2−
3−module Foo (
4− foo, bar, baz) where
5−
6−foo :: Int
7−foo = 5
8−bar :: Int -> Int
9−bar = \case
10− 0 -> foo
11− x -> x - foo
12−
13−baz :: Int -> Int
14−baz = gege
15− where
16− gege = 1 + 2
region-tests/expected-result-9-12.hsdeleted−17
@@ -1,17 +0,0 @@
1−{-# LANGUAGE LambdaCase #-}
2−
3−module Foo (
4− foo, bar, baz) where
5−
6−foo :: Int
7−foo = 5
8−
9−bar :: Int -> Int
10−bar = \case
11− 0 -> foo
12− x -> x - foo
13−
14−baz :: Int -> Int
15−baz = gege
16− where
17− gege = 1 + 2
region-tests/expected-result-all.hsdeleted−21
@@ -1,21 +0,0 @@
1−{-# LANGUAGE LambdaCase #-}
2−
3−module Foo
4− ( foo,
5− bar,
6− baz,
7− )
8−where
9−
10−foo :: Int
11−foo = 5
12−
13−bar :: Int -> Int
14−bar = \case
15− 0 -> foo
16− x -> x - foo
17−
18−baz :: Int -> Int
19−baz = gege
20− where
21− gege = 1 + 2
region-tests/src.hsdeleted−17
@@ -1,17 +0,0 @@
1−{-# LANGUAGE LambdaCase #-}
2−
3−module Foo (
4− foo, bar, baz) where
5−
6−foo :: Int
7−foo = 5
8−
9−bar :: Int -> Int
10−bar = \case
11− 0 -> foo
12− x -> x - foo
13−
14−baz :: Int -> Int
15−baz = gege
16− where
17− gege = 1 + 2
shell.nix+2−4
@@ -1,5 +1,3 @@
1−{ pkgs ? (import ./nix/nixpkgs { inherit system; })
2−, system ? builtins.currentSystem
3−}:
1+{ pkgs ? (import ./nix/nixpkgs) }:
42
5−(import ./default.nix { inherit pkgs; }).dev.ormoluShell
3+(import ./default.nix { inherit pkgs; }).ormoluShell
src/GHC.hs+13−2
@@ -1,12 +1,23 @@
11module GHC
22 ( module X,
3+ ParsedSource,
34 )
45where
56
67import ApiAnnotation as X
78import BasicTypes as X
8−import GHC.Hs as X
9−import GHC.Hs.Instances as X ()
9+import HsBinds as X
10+import HsDecls as X
11+import HsDoc as X
12+import HsExpr as X
13+import HsExtension as X
14+import HsImpExp as X
15+import HsInstances as X ()
16+import HsLit as X
17+import HsPat as X
18+import HsSyn as X
1019import Module as X
1120import RdrName as X
1221import SrcLoc as X
22+
23+type ParsedSource = Located (HsModule GhcPs)
src/GHC/DynFlags.hs+19−30
@@ -1,7 +1,5 @@
11{-# OPTIONS_GHC -Wno-missing-fields #-}
22
3−-- Modified from ghc-lib-api-ext.
4−
53module GHC.DynFlags
64 ( baseDynFlags,
75 )
@@ -10,40 +8,31 @@ where
108import Config
119import DynFlags
1210import Fingerprint
13−import GHC.Platform
14−import ToolSettings
11+import Platform
1512
13+-- | Taken from HLint.
1614fakeSettings :: Settings
1715fakeSettings =
1816 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− }
17+ { sTargetPlatform = platform,
18+ sPlatformConstants = platformConstants,
19+ sProjectVersion = cProjectVersion,
20+ sProgramName = "ghc",
21+ sOpt_P_fingerprint = fingerprint0,
22+ sPgm_F = ""
4323 }
24+ where
25+ platform =
26+ Platform
27+ { platformWordSize = 8,
28+ platformOS = OSUnknown,
29+ platformUnregisterised = True
30+ }
31+ platformConstants =
32+ PlatformConstants {pc_DYNAMIC_BY_DEFAULT = False, pc_WORD_SIZE = 8}
4433
45−fakeLlvmConfig :: LlvmConfig
46−fakeLlvmConfig = LlvmConfig [] []
34+fakeLlvmConfig :: (LlvmTargets, LlvmPasses)
35+fakeLlvmConfig = ([], [])
4736
4837baseDynFlags :: DynFlags
4938baseDynFlags = defaultDynFlags fakeSettings fakeLlvmConfig
src/Ormolu.hs+7−10
@@ -6,7 +6,6 @@ module Ormolu
66 ormoluFile,
77 ormoluStdin,
88 Config (..),
9− RegionIndices (..),
109 defaultConfig,
1110 DynOption (..),
1211 OrmoluException (..),
@@ -43,15 +42,13 @@ import qualified SrcLoc as GHC
4342ormolu ::
4443 MonadIO m =>
4544 -- | Ormolu configuration
46− Config RegionIndices ->
45+ Config ->
4746 -- | Location of source file
4847 FilePath ->
4948 -- | Input to format
5049 String ->
5150 m Text
52−ormolu cfgWithIndices path str = do
53− let totalLines = length (lines str)
54− cfg = regionIndicesToDeltas totalLines <$> cfgWithIndices
51+ormolu cfg path str = do
5552 (warnings, result0) <-
5653 parseModule' cfg OrmoluParsingFailed path str
5754 when (cfgDebug cfg) $ do
@@ -63,7 +60,7 @@ ormolu cfgWithIndices path str = do
6360 -- to parse the rendered code back, inside of GHC monad wrapper which will
6461 -- lead to error messages presenting the exceptions as GHC bugs.
6562 let !txt = printModule result0
66− when (not (cfgUnsafe cfg) || cfgCheckIdempotence cfg) $ do
63+ when (not (cfgUnsafe cfg) || cfgCheckIdempotency cfg) $ do
6764 let pathRendered = path ++ "<rendered>"
6865 -- Parse the result of pretty-printing again and make sure that AST
6966 -- is the same as AST of original snippet module span positions.
@@ -79,7 +76,7 @@ ormolu cfgWithIndices path str = do
7976 Different ss -> liftIO $ throwIO (OrmoluASTDiffers path ss)
8077 -- Try re-formatting the formatted result to check if we get exactly
8178 -- the same output.
82− when (cfgCheckIdempotence cfg) $
79+ when (cfgCheckIdempotency cfg) $
8380 let txt2 = printModule result1
8481 in case diffText txt txt2 pathRendered of
8582 Nothing -> return ()
@@ -96,7 +93,7 @@ ormolu cfgWithIndices path str = do
9693ormoluFile ::
9794 MonadIO m =>
9895 -- | Ormolu configuration
99− Config RegionIndices ->
96+ Config ->
10097 -- | Location of source file
10198 FilePath ->
10299 -- | Resulting rendition
@@ -111,7 +108,7 @@ ormoluFile cfg path =
111108ormoluStdin ::
112109 MonadIO m =>
113110 -- | Ormolu configuration
114− Config RegionIndices ->
111+ Config ->
115112 -- | Resulting rendition
116113 m Text
117114ormoluStdin cfg =
@@ -124,7 +121,7 @@ ormoluStdin cfg =
124121parseModule' ::
125122 MonadIO m =>
126123 -- | Ormolu configuration
127− Config RegionDeltas ->
124+ Config ->
128125 -- | How to obtain 'OrmoluException' to throw when parsing fails
129126 (GHC.SrcSpan -> String -> OrmoluException) ->
130127 -- | File name to use in errors
src/Ormolu/Config.hs+23−62
@@ -1,13 +1,7 @@
1−{-# LANGUAGE DeriveFunctor #-}
2−{-# LANGUAGE RecordWildCards #-}
3−
41-- | Configuration options used by the tool.
52module Ormolu.Config
63 ( Config (..),
7− RegionIndices (..),
8− RegionDeltas (..),
94 defaultConfig,
10− regionIndicesToDeltas,
115 DynOption (..),
126 dynOptionToLocatedStr,
137 )
@@ -16,72 +10,39 @@ where
1610import qualified SrcLoc as GHC
1711
1812-- | 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)
32−
33−-- | Region selection as the combination of start and end line numbers.
34−data RegionIndices = RegionIndices
35− { -- | Start line of the region to format
36− regionStartLine :: !(Maybe Int),
37− -- | End line of the region to format
38− regionEndLine :: !(Maybe Int)
39− }
40− deriving (Eq, Show)
41−
42−-- | Region selection as the length of the literal prefix and the literal
43−-- suffix.
44−data RegionDeltas = RegionDeltas
45− { -- | Prefix length in number of lines
46− regionPrefixLength :: !Int,
47− -- | Suffix length in number of lines
48− regionSuffixLength :: !Int
49− }
13+data Config
14+ = Config
15+ { -- | Dynamic options to pass to GHC parser
16+ cfgDynOptions :: ![DynOption],
17+ -- | Do formatting faster but without automatic detection of defects
18+ cfgUnsafe :: !Bool,
19+ -- | Output information useful for debugging
20+ cfgDebug :: !Bool,
21+ -- | Do not fail if CPP pragma is present (still doesn't handle CPP but
22+ -- useful for formatting of files that enable the extension without
23+ -- actually containing CPP macros)
24+ cfgTolerateCpp :: !Bool,
25+ -- | Checks if re-formatting the result is idempotent.
26+ cfgCheckIdempotency :: !Bool
27+ }
5028 deriving (Eq, Show)
5129
52−-- | Default @'Config' 'RegionIndices'@.
53−defaultConfig :: Config RegionIndices
30+-- | Default 'Config'.
31+defaultConfig :: Config
5432defaultConfig =
5533 Config
5634 { cfgDynOptions = [],
5735 cfgUnsafe = False,
5836 cfgDebug = False,
59− cfgCheckIdempotence = False,
60− cfgRegion =
61− RegionIndices
62− { regionStartLine = Nothing,
63− regionEndLine = Nothing
64− }
65− }
66−
67−-- | Convert 'RegionIndices' into 'RegionDeltas'.
68−regionIndicesToDeltas ::
69− -- | Total number of lines in the input
70− Int ->
71− -- | Region indices
72− RegionIndices ->
73− -- | Region deltas
74− RegionDeltas
75−regionIndicesToDeltas total RegionIndices {..} =
76− RegionDeltas
77− { regionPrefixLength = maybe 0 (subtract 1) regionStartLine,
78− regionSuffixLength = maybe 0 (total -) regionEndLine
37+ cfgTolerateCpp = False,
38+ cfgCheckIdempotency = False
7939 }
8040
8141-- | A wrapper for dynamic options.
82−newtype DynOption = DynOption
83− { unDynOption :: String
84− }
42+newtype DynOption
43+ = DynOption
44+ { unDynOption :: String
45+ }
8546 deriving (Eq, Ord, Show)
8647
8748-- | Convert 'DynOption' to @'GHC.Located' 'String'@.
src/Ormolu/Diff.hs+13−23
@@ -8,14 +8,14 @@ module Ormolu.Diff
88 )
99where
1010
11+import BasicTypes (SourceText)
1112import Data.ByteString (ByteString)
1213import Data.Generics
1314import Data.Text (Text)
1415import qualified Data.Text as T
1516import qualified FastString as GHC
1617import GHC
17−import Ormolu.Imports (normalizeImports)
18−import Ormolu.Parser.CommentStream
18+import Ormolu.Imports (sortImports)
1919import Ormolu.Parser.Result
2020import Ormolu.Utils
2121
@@ -39,16 +39,14 @@ diffParseResult :: ParseResult -> ParseResult -> Diff
3939diffParseResult
4040 ParseResult
4141 { prCommentStream = cstream0,
42− prParsedSource = hs0
42+ prParsedSource = ps0
4343 }
4444 ParseResult
4545 { prCommentStream = cstream1,
46− prParsedSource = hs1
46+ prParsedSource = ps1
4747 } =
4848 matchIgnoringSrcSpans cstream0 cstream1
49− <> matchIgnoringSrcSpans
50− hs0 {hsmodImports = normalizeImports (hsmodImports hs0)}
51− hs1 {hsmodImports = normalizeImports (hsmodImports hs1)}
49+ <> matchIgnoringSrcSpans ps0 ps1
5250
5351-- | Compare two values for equality disregarding differences in 'SrcSpan's
5452-- and the ordering of import lists.
@@ -70,10 +68,9 @@ matchIgnoringSrcSpans = genericQuery
7068 gzipWithQ
7169 ( genericQuery
7270 `extQ` srcSpanEq
73− `extQ` commentEq
71+ `extQ` hsModuleEq
7472 `extQ` sourceTextEq
7573 `extQ` hsDocStringEq
76− `extQ` importDeclQualifiedStyleEq
7774 `ext2Q` forLocated
7875 )
7976 x
@@ -81,23 +78,16 @@ matchIgnoringSrcSpans = genericQuery
8178 | otherwise = Different []
8279 srcSpanEq :: SrcSpan -> GenericQ Diff
8380 srcSpanEq _ _ = Same
84− commentEq :: Comment -> GenericQ Diff
85− commentEq (Comment _ x) d =
86− case cast d :: Maybe Comment of
81+ hsModuleEq :: HsModule GhcPs -> GenericQ Diff
82+ hsModuleEq hs0 hs1' =
83+ case cast hs1' :: Maybe (HsModule GhcPs) of
8784 Nothing -> Different []
88− Just (Comment _ y) ->
89− if x == y
90− then Same
91− else Different []
85+ Just hs1 ->
86+ matchIgnoringSrcSpans
87+ hs0 {hsmodImports = sortImports (hsmodImports hs0)}
88+ hs1 {hsmodImports = sortImports (hsmodImports hs1)}
9289 sourceTextEq :: SourceText -> GenericQ Diff
9390 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 []
10191 hsDocStringEq :: HsDocString -> GenericQ Diff
10292 hsDocStringEq str0 str1' =
10393 case cast str1' :: Maybe HsDocString of
src/Ormolu/Exception.hs+11−4
@@ -19,7 +19,9 @@ import System.IO
1919
2020-- | Ormolu exception representing all cases when Ormolu can fail.
2121data OrmoluException
22− = -- | Parsing of original source code failed
22+ = -- | Ormolu does not work with source files that use CPP
23+ OrmoluCppEnabled FilePath
24+ | -- | Parsing of original source code failed
2325 OrmoluParsingFailed GHC.SrcSpan String
2426 | -- | Parsing of formatted source code failed
2527 OrmoluOutputParsingFailed GHC.SrcSpan String
@@ -33,8 +35,13 @@ data OrmoluException
3335
3436instance Exception OrmoluException where
3537 displayException = \case
38+ OrmoluCppEnabled path ->
39+ unlines
40+ [ "CPP is not supported:",
41+ withIndent path
42+ ]
3643 OrmoluParsingFailed s e ->
37− showParsingErr "The GHC parser (in Haddock mode) failed:" s [e]
44+ showParsingErr "Parsing of source code failed:" s [e]
3845 OrmoluOutputParsingFailed s e ->
3946 showParsingErr "Parsing of formatted code failed:" s [e]
4047 ++ "Please, consider reporting the bug.\n"
@@ -74,8 +81,8 @@ withPrettyOrmoluExceptions m = m `catch` h
7481 hPutStrLn stderr (displayException e)
7582 exitWith . ExitFailure $
7683 case e of
77− -- Error code 1 is for 'error' or 'notImplemented'
78− -- 2 used to be for erroring out on CPP
84+ -- Error code 1 is for `error` or `notImplemented`
85+ OrmoluCppEnabled {} -> 2
7986 OrmoluParsingFailed {} -> 3
8087 OrmoluOutputParsingFailed {} -> 4
8188 OrmoluASTDiffers {} -> 5
src/Ormolu/Imports.hs+51−168
@@ -4,199 +4,82 @@
44
55-- | Manipulations on import lists.
66module Ormolu.Imports
7− ( normalizeImports,
7+ ( sortImports,
88 )
99where
1010
1111import Data.Bifunctor
12−import Data.Char (isAlphaNum)
1312import Data.Function (on)
14−import Data.List (foldl', nubBy, sortBy, sortOn)
15−import Data.Map.Strict (Map)
16−import qualified Data.Map.Strict as M
17−import FastString (FastString)
13+import Data.Generics (gcompare)
14+import Data.List (sortBy)
1815import GHC hiding (GhcPs, IE)
19−import GHC.Hs.Extension
20−import GHC.Hs.ImpExp (IE (..))
21−import Ormolu.Utils (notImplemented, showOutputable)
16+import HsExtension
17+import HsImpExp (IE (..))
18+import Ormolu.Utils (notImplemented)
2219
23−-- | Sort and normalize imports.
24−normalizeImports :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]
25−normalizeImports =
26− fmap snd
27− . M.toAscList
28− . M.fromListWith combineImports
29− . fmap (\x -> (importId x, g x))
20+-- | Sort imports by module name. This also sorts explicit import lists for
21+-- each declaration.
22+sortImports :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]
23+sortImports = sortBy compareIdecl . fmap (fmap sortImportLists)
3024 where
31− g (L l ImportDecl {..}) =
32− L
33− l
25+ sortImportLists :: ImportDecl GhcPs -> ImportDecl GhcPs
26+ sortImportLists = \case
27+ ImportDecl {..} ->
3428 ImportDecl
35− { ideclHiding = second (fmap normalizeLies) <$> ideclHiding,
29+ { ideclHiding = second (fmap sortLies) <$> ideclHiding,
3630 ..
3731 }
38− g _ = notImplemented "XImportDecl"
32+ XImportDecl {} -> notImplemented "XImportDecl"
3933
40−-- | Combine two import declarations. It should be assumed that 'ImportId's
41−-- are equal.
42−combineImports ::
43− LImportDecl GhcPs ->
44− LImportDecl GhcPs ->
45− LImportDecl GhcPs
46−combineImports (L lx ImportDecl {..}) (L _ y) =
47− L
48− lx
49− ImportDecl
50− { ideclHiding = case (ideclHiding, GHC.ideclHiding y) of
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− }
34+-- | Compare two @'LImportDecl' 'GhcPs'@ things.
35+compareIdecl :: LImportDecl GhcPs -> LImportDecl GhcPs -> Ordering
36+compareIdecl (L _ m0) (L _ m1) =
37+ case (isPrelude n0, isPrelude n1) of
38+ (False, False) -> n0 `compare` n1
39+ (True, False) -> GT
40+ (False, True) -> LT
41+ (True, True) -> m0 `gcompare` m1
9142 where
92− isPrelude = moduleNameString moduleName == "Prelude"
93− moduleName = unLoc ideclName
94−importId _ = notImplemented "XImportDecl"
43+ n0 = unLoc (ideclName m0)
44+ n1 = unLoc (ideclName m1)
45+ isPrelude = (== "Prelude") . moduleNameString
9546
96−-- | Normalize a collection of import\/export items.
97−normalizeLies :: [LIE GhcPs] -> [LIE GhcPs]
98−normalizeLies = sortOn (getIewn . unLoc) . M.elems . foldl' combine M.empty
99− where
100− combine ::
101− Map IEWrappedNameOrd (LIE GhcPs) ->
102− LIE GhcPs ->
103− Map IEWrappedNameOrd (LIE GhcPs)
104− combine m (L new_l new) =
105− let wname = getIewn new
106− normalizeWNames =
107− nubBy (\x y -> compareLIewn x y == EQ) . sortBy compareLIewn
108− alter = \case
109− Nothing -> Just . L new_l $
110− case new of
111− IEThingWith NoExtField n wildcard g flbl ->
112− IEThingWith NoExtField n wildcard (normalizeWNames g) flbl
113− other -> other
114− Just old ->
115− let f = \case
116− IEVar NoExtField n -> IEVar NoExtField n
117− IEThingAbs NoExtField _ -> new
118− IEThingAll NoExtField n -> IEThingAll NoExtField n
119− IEThingWith NoExtField n wildcard g flbl ->
120− case new of
121− IEVar NoExtField _ ->
122− error "Ormolu.Imports broken presupposition"
123− IEThingAbs NoExtField _ ->
124− IEThingWith NoExtField n wildcard g flbl
125− IEThingAll NoExtField n' ->
126− IEThingAll NoExtField n'
127− IEThingWith NoExtField n' wildcard' g' flbl' ->
128− let combinedWildcard =
129− case (wildcard, wildcard') of
130− (IEWildcard _, _) -> IEWildcard 0
131− (_, IEWildcard _) -> IEWildcard 0
132− _ -> NoIEWildcard
133− in IEThingWith
134− NoExtField
135− n'
136− combinedWildcard
137− (normalizeWNames (g <> g'))
138− flbl'
139− IEModuleContents NoExtField _ -> notImplemented "IEModuleContents"
140− IEGroup NoExtField _ _ -> notImplemented "IEGroup"
141− IEDoc NoExtField _ -> notImplemented "IEDoc"
142− IEDocNamed NoExtField _ -> notImplemented "IEDocNamed"
143− XIE x -> noExtCon x
144− IEModuleContents NoExtField _ -> notImplemented "IEModuleContents"
145− IEGroup NoExtField _ _ -> notImplemented "IEGroup"
146− IEDoc NoExtField _ -> notImplemented "IEDoc"
147− IEDocNamed NoExtField _ -> notImplemented "IEDocNamed"
148− XIE x -> noExtCon x
149− in Just (f <$> old)
150− in M.alter alter wname m
47+-- | Sort located import or export.
48+sortLies :: [LIE GhcPs] -> [LIE GhcPs]
49+sortLies = sortBy (compareIE `on` unLoc) . fmap (fmap sortThings)
15150
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)
51+-- | Sort imports\/exports inside of 'IEThingWith'.
52+sortThings :: IE GhcPs -> IE GhcPs
53+sortThings = \case
54+ IEThingWith NoExt x w xs fl ->
55+ IEThingWith NoExt x w (sortBy (compareIewn `on` unLoc) xs) fl
56+ other -> other
15657
157−instance Ord IEWrappedNameOrd where
158− compare (IEWrappedNameOrd x) (IEWrappedNameOrd y) = compareIewn x y
58+-- | Compare two located imports or exports.
59+compareIE :: IE GhcPs -> IE GhcPs -> Ordering
60+compareIE = compareIewn `on` getIewn
15961
16062-- | Project @'IEWrappedName' 'RdrName'@ from @'IE' 'GhcPs'@.
161−getIewn :: IE GhcPs -> IEWrappedNameOrd
63+getIewn :: IE GhcPs -> IEWrappedName RdrName
16264getIewn = \case
163− IEVar NoExtField x -> IEWrappedNameOrd (unLoc x)
164− IEThingAbs NoExtField x -> IEWrappedNameOrd (unLoc x)
165− IEThingAll NoExtField x -> IEWrappedNameOrd (unLoc x)
166− IEThingWith NoExtField x _ _ _ -> IEWrappedNameOrd (unLoc x)
167− IEModuleContents NoExtField _ -> notImplemented "IEModuleContents"
168− IEGroup NoExtField _ _ -> notImplemented "IEGroup"
169− IEDoc NoExtField _ -> notImplemented "IEDoc"
170− IEDocNamed NoExtField _ -> notImplemented "IEDocNamed"
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
65+ IEVar NoExt x -> unLoc x
66+ IEThingAbs NoExt x -> unLoc x
67+ IEThingAll NoExt x -> unLoc x
68+ IEThingWith NoExt x _ _ _ -> unLoc x
69+ IEModuleContents NoExt _ -> notImplemented "IEModuleContents"
70+ IEGroup NoExt _ _ -> notImplemented "IEGroup"
71+ IEDoc NoExt _ -> notImplemented "IEDoc"
72+ IEDocNamed NoExt _ -> notImplemented "IEDocNamed"
73+ XIE NoExt -> notImplemented "XIE"
17674
17775-- | Compare two @'IEWrapppedName' 'RdrName'@ things.
17876compareIewn :: IEWrappedName RdrName -> IEWrappedName RdrName -> Ordering
179−compareIewn (IEName x) (IEName y) = unLoc x `compareRdrName` unLoc y
77+compareIewn (IEName x) (IEName y) = unLoc x `compare` unLoc y
18078compareIewn (IEName _) (IEPattern _) = LT
18179compareIewn (IEName _) (IEType _) = LT
18280compareIewn (IEPattern _) (IEName _) = GT
183−compareIewn (IEPattern x) (IEPattern y) = unLoc x `compareRdrName` unLoc y
81+compareIewn (IEPattern x) (IEPattern y) = unLoc x `compare` unLoc y
18482compareIewn (IEPattern _) (IEType _) = LT
18583compareIewn (IEType _) (IEName _) = GT
18684compareIewn (IEType _) (IEPattern _) = GT
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
85+compareIewn (IEType x) (IEType y) = unLoc x `compare` unLoc y
src/Ormolu/Parser.hs+84−78
@@ -9,16 +9,14 @@ module Ormolu.Parser
99 )
1010where
1111
12−import Bag (bagToList)
1312import qualified CmdLineParser as GHC
1413import Control.Exception
14+import Control.Monad
1515import Control.Monad.IO.Class
16−import qualified Data.List as L
16+import Data.List ((\\), foldl', isPrefixOf)
1717import qualified Data.List.NonEmpty as NE
18−import Data.Ord (Down (Down))
19−import qualified Data.Text as T
18+import Data.Maybe (catMaybes)
2019import DynFlags as GHC
21−import ErrUtils (Severity (..), errMsgSeverity, errMsgSpan)
2220import qualified FastString as GHC
2321import GHC hiding (IE, UnicodeSyntax)
2422import GHC.DynFlags (baseDynFlags)
@@ -31,8 +29,7 @@ import Ormolu.Exception
3129import Ormolu.Parser.Anns
3230import Ormolu.Parser.CommentStream
3331import Ormolu.Parser.Result
34−import Ormolu.Processing.Preprocess (preprocess)
35−import Ormolu.Utils (incSpanLine, removeIndentation)
32+import qualified Outputable as GHC
3633import qualified Panic as GHC
3734import qualified Parser as GHC
3835import qualified StringBuffer as GHC
@@ -41,7 +38,7 @@ import qualified StringBuffer as GHC
4138parseModule ::
4239 MonadIO m =>
4340 -- | Ormolu configuration
44− Config RegionDeltas ->
41+ Config ->
4542 -- | File name (only for source location annotations)
4643 FilePath ->
4744 -- | Input for parser
@@ -50,10 +47,8 @@ parseModule ::
5047 ( [GHC.Warn],
5148 Either (SrcSpan, String) ParseResult
5249 )
53−parseModule Config {..} path rawInput = liftIO $ do
54− let (literalPrefix, indentedInput, literalSuffix, extraComments) =
55− preprocess path rawInput cfgRegion
56− (input, indent) = removeIndentation indentedInput
50+parseModule Config {..} path input' = liftIO $ do
51+ let (input, extraComments) = extractCommentsFromLines path input'
5752 -- It's important that 'setDefaultExts' is done before
5853 -- 'parsePragmasIntoDynFlags', because otherwise we might enable an
5954 -- extension that was explicitly disabled in the file.
@@ -63,7 +58,7 @@ parseModule Config {..} path rawInput = liftIO $ do
6358 (setDefaultExts baseDynFlags)
6459 extraOpts = dynOptionToLocatedStr <$> cfgDynOptions
6560 (warnings, dynFlags) <-
66− parsePragmasIntoDynFlags baseFlags extraOpts path rawInput >>= \case
61+ parsePragmasIntoDynFlags baseFlags extraOpts path input' >>= \case
6762 Right res -> pure res
6863 Left err ->
6964 let loc =
@@ -71,59 +66,29 @@ parseModule Config {..} path rawInput = liftIO $ do
7166 (mkSrcLoc (GHC.mkFastString path) 1 1)
7267 (mkSrcLoc (GHC.mkFastString path) 1 1)
7368 in throwIO (OrmoluParsingFailed loc err)
69+ when (GHC.xopt Cpp dynFlags && not cfgTolerateCpp) $
70+ throwIO (OrmoluCppEnabled path)
7471 let useRecordDot =
7572 "record-dot-preprocessor" == pgm_F dynFlags
7673 || any
7774 (("RecordDotPreprocessor" ==) . moduleNameString)
7875 (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)
8776 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− }
77+ GHC.PFailed _ ss m ->
78+ Left (ss, GHC.showSDoc dynFlags m)
79+ GHC.POk pstate pmod ->
80+ let (comments, exts, shebangs) = mkCommentStream extraComments pstate
81+ in Right
82+ ParseResult
83+ { prParsedSource = pmod,
84+ prAnns = mkAnns pstate,
85+ prCommentStream = comments,
86+ prExtensions = exts,
87+ prShebangs = shebangs,
88+ prUseRecordDot = useRecordDot
89+ }
11790 return (warnings, r)
11891
119−-- | Enable all language extensions that we think should be enabled by
120−-- default for ease of use.
121−setDefaultExts :: DynFlags -> DynFlags
122−setDefaultExts flags = L.foldl' xopt_set flags autoExts
123− where
124− autoExts = allExts L.\\ manualExts
125− allExts = [minBound .. maxBound]
126−
12792-- | Extensions that are not enabled automatically and should be activated
12893-- by user.
12994manualExts :: [Extension]
@@ -143,13 +108,14 @@ manualExts =
143108 MonadComprehensions,
144109 UnboxedSums,
145110 UnicodeSyntax, -- gives special meanings to operators like (→)
146− TemplateHaskellQuotes, -- enables TH subset of quasi-quotes, this
111+ TemplateHaskellQuotes -- enables TH subset of quasi-quotes, this
147112 -- apparently interferes with QuasiQuotes in
148113 -- weird ways
149− ImportQualifiedPost -- affects how Ormolu renders imports, so the
150− -- decision of enabling this style is left to the user
151114 ]
152115
116+----------------------------------------------------------------------------
117+-- Helpers (taken from ghc-exactprint)
118+
153119-- | Run a 'GHC.P' computation.
154120runParser ::
155121 -- | Computation to run
@@ -168,27 +134,67 @@ runParser parser flags filename input = GHC.unP parser parseState
168134 buffer = GHC.stringToStringBuffer input
169135 parseState = GHC.mkPState flags buffer location
170136
171−-- | Wrap GHC's 'Severity' to add 'Ord' instance.
172−newtype SeverityOrd = SeverityOrd Severity
137+-- | Transform given lines possibly returning comments extracted from them.
138+-- This handles LINE pragmas and shebangs.
139+extractCommentsFromLines ::
140+ -- | File name, just to use in the spans
141+ FilePath ->
142+ -- | List of lines from that file
143+ String ->
144+ -- | Adjusted lines together with comments extracted from them
145+ (String, [Located String])
146+extractCommentsFromLines path =
147+ unlines' . unzip . zipWith (extractCommentFromLine path) [1 ..] . lines
148+ where
149+ unlines' (a, b) = (unlines a, catMaybes b)
173150
174−instance Eq SeverityOrd where
175− s1 == s2 = compare s1 s2 == EQ
151+-- | Transform a given line possibly returning a comment extracted from it.
152+extractCommentFromLine ::
153+ -- | File name, just to use in the spans
154+ FilePath ->
155+ -- | Line number of this line
156+ Int ->
157+ -- | The actual line
158+ String ->
159+ -- | Adjusted line and possibly a comment extracted from it
160+ (String, Maybe (Located String))
161+extractCommentFromLine path line s
162+ | "{-# LINE" `isPrefixOf` s =
163+ let (pragma, res) = getPragma s
164+ size = length pragma
165+ ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (size + 1))
166+ in (res, Just $ L ss pragma)
167+ | isShebang s =
168+ let ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (length s))
169+ in ("", Just $ L ss s)
170+ | otherwise = (s, Nothing)
171+ where
172+ mkSrcLoc' = mkSrcLoc (GHC.mkFastString path) line
173+
174+-- | Take a line pragma and output its replacement (where line pragma is
175+-- replaced with spaces) and the contents of the pragma itself.
176+getPragma ::
177+ -- | Pragma line to analyze
178+ String ->
179+ -- | Contents of the pragma and its replacement line
180+ (String, String)
181+getPragma [] = error "Ormolu.Parser.getPragma: input must not be empty"
182+getPragma s@(x : xs)
183+ | "#-}" `isPrefixOf` s = ("#-}", " " ++ drop 3 s)
184+ | otherwise =
185+ let (prag, remline) = getPragma xs
186+ in (x : prag, ' ' : remline)
176187
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
188+-- | Enable all language extensions that we think should be enabled by
189+-- default for ease of use.
190+setDefaultExts :: DynFlags -> DynFlags
191+setDefaultExts flags = foldl' GHC.xopt_set flags autoExts
192+ where
193+ autoExts = allExts \\ manualExts
194+ allExts = [minBound .. maxBound]
189195
190196----------------------------------------------------------------------------
191−-- Helpers taken from HLint
197+-- More helpers (taken from HLint)
192198
193199parsePragmasIntoDynFlags ::
194200 -- | Pre-set 'DynFlags'
src/Ormolu/Parser/CommentStream.hs+61−147
@@ -4,74 +4,78 @@
44
55-- | Functions for working with comment stream.
66module Ormolu.Parser.CommentStream
7− ( -- * Comment stream
8− CommentStream (..),
9− mkCommentStream,
10− showCommentStream,
11−
12− -- * Comment
7+ ( CommentStream (..),
138 Comment (..),
14− unComment,
15− hasAtomsBefore,
9+ mkCommentStream,
10+ isShebang,
11+ isPrevHaddock,
1612 isMultilineComment,
13+ showCommentStream,
1714 )
1815where
1916
2017import Data.Char (isSpace)
2118import Data.Data (Data)
22−import qualified Data.List as L
19+import Data.Either (partitionEithers)
20+import Data.List (dropWhileEnd, isPrefixOf, sortOn)
2321import Data.List.NonEmpty (NonEmpty (..))
2422import qualified Data.List.NonEmpty as NE
2523import Data.Maybe (mapMaybe)
2624import qualified GHC
2725import qualified Lexer as GHC
2826import Ormolu.Parser.Pragma
29−import Ormolu.Parser.Shebang
30−import Ormolu.Processing.Common
31−import Ormolu.Utils (onTheSameLine, showOutputable)
27+import Ormolu.Utils (showOutputable)
3228import SrcLoc
3329
34−----------------------------------------------------------------------------
35−-- Comment stream
36−
3730-- | A stream of 'RealLocated' 'Comment's in ascending order with respect to
3831-- beginning of corresponding spans.
3932newtype CommentStream = CommentStream [RealLocated Comment]
4033 deriving (Eq, Data, Semigroup, Monoid)
4134
35+-- | A wrapper for a single comment. The 'NonEmpty' list inside contains
36+-- lines of multiline comment @{- … -}@ or just single item\/line otherwise.
37+newtype Comment = Comment (NonEmpty String)
38+ deriving (Eq, Show, Data)
39+
4240-- | Create 'CommentStream' from 'GHC.PState'. The pragmas and shebangs are
4341-- removed from the 'CommentStream'. Shebangs are only extracted from the
4442-- comments that come from the first argument.
4543mkCommentStream ::
46− -- | Original input
47− String ->
4844 -- | Extra comments to include
4945 [Located String] ->
5046 -- | Parser state to use for comment extraction
5147 GHC.PState ->
52− -- | Stack header, shebangs, pragmas, and comment stream
53− ( Maybe (RealLocated Comment),
54− [Shebang],
55− [([RealLocated Comment], Pragma)],
56− CommentStream
57− )
58−mkCommentStream input extraComments pstate =
59− ( mstackHeader,
60− shebangs,
48+ -- | Comment stream, a set of extracted pragmas, and extracted shebangs
49+ (CommentStream, [Pragma], [Located String])
50+mkCommentStream extraComments pstate =
51+ ( CommentStream $
52+ mkComment <$> sortOn (realSrcSpanStart . getRealSrcSpan) comments,
6153 pragmas,
62− CommentStream comments
54+ shebangs
6355 )
6456 where
65− (comments, pragmas) = extractPragmas input rawComments1
66− (rawComments1, mstackHeader) = extractStackHeader rawComments0
67− rawComments0 =
68− L.sortOn (realSrcSpanStart . getRealSrcSpan) . mapMaybe toRealSpan $
57+ (comments, pragmas) = partitionEithers (partitionComments <$> rawComments)
58+ rawComments =
59+ mapMaybe toRealSpan $
6960 otherExtraComments
7061 ++ mapMaybe (liftMaybe . fmap unAnnotationComment) (GHC.comment_q pstate)
7162 ++ concatMap
7263 (mapMaybe (liftMaybe . fmap unAnnotationComment) . snd)
7364 (GHC.annotations_comments pstate)
74− (shebangs, otherExtraComments) = extractShebangs extraComments
65+ (shebangs, otherExtraComments) = span (isShebang . unLoc) extraComments
66+
67+-- | Return 'True' if given 'String' is a shebang.
68+isShebang :: String -> Bool
69+isShebang str = "#!" `isPrefixOf` str
70+
71+-- | Test whether a 'Comment' looks like a Haddock following a definition,
72+-- i.e. something starting with @-- ^@.
73+isPrevHaddock :: Comment -> Bool
74+isPrevHaddock (Comment (x :| _)) = "-- ^" `isPrefixOf` x
75+
76+-- | Is this comment multiline-style?
77+isMultilineComment :: Comment -> Bool
78+isMultilineComment (Comment (x :| _)) = "{-" `isPrefixOf` x
7579
7680-- | Pretty-print a 'CommentStream'.
7781showCommentStream :: CommentStream -> String
@@ -82,117 +86,28 @@ showCommentStream (CommentStream xs) =
8286 showComment (GHC.L l str) = showOutputable l ++ " " ++ show str
8387
8488----------------------------------------------------------------------------
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)
89+-- Helpers
9390
9491-- | Normalize comment string. Sometimes one multi-line comment is turned
9592-- into several lines for subsequent outputting with correct indentation for
9693-- each line.
97−mkComment ::
98− -- | Lines of original input with their indices
99− [(Int, String)] ->
100− -- | Raw comment string
101− RealLocated String ->
102− -- | Remaining lines of original input and the constructed 'Comment'
103− ([(Int, String)], RealLocated Comment)
104−mkComment ls (L l s) = (ls', comment)
94+mkComment :: RealLocated String -> RealLocated Comment
95+mkComment (L l s) =
96+ L l . Comment . fmap dropTrailing $
97+ if "{-" `isPrefixOf` s
98+ then case NE.nonEmpty (lines s) of
99+ Nothing -> s :| []
100+ Just (x :| xs) ->
101+ let getIndent y =
102+ if all isSpace y
103+ then startIndent
104+ else length (takeWhile isSpace y)
105+ n = minimum (startIndent : fmap getIndent xs)
106+ in x :| (drop n <$> xs)
107+ else s :| []
105108 where
106− comment =
107− L l . Comment atomsBefore . removeConseqBlanks . fmap dropTrailing $
108− if "{-" `L.isPrefixOf` s
109− then case NE.nonEmpty (lines s) of
110− Nothing -> s :| []
111− Just (x :| xs) ->
112− let getIndent y =
113− if all isSpace y || y == endDisabling
114− then startIndent
115− else length (takeWhile isSpace y)
116− n = minimum (startIndent : fmap getIndent xs)
117− removeIndent y =
118− if y == endDisabling
119− then y
120− else drop n y
121− in x :| (removeIndent <$> xs)
122− else s :| []
123− (atomsBefore, ls') =
124− case dropWhile ((< commentLine) . fst) ls of
125− [] -> (False, [])
126− ((_, i) : ls'') ->
127− case take 2 (dropWhile isSpace i) of
128− "--" -> (False, ls'')
129− "{-" -> (False, ls'')
130− _ -> (True, ls'')
131− dropTrailing = L.dropWhileEnd isSpace
109+ dropTrailing = dropWhileEnd isSpace
132110 startIndent = srcSpanStartCol l - 1
133− commentLine = srcSpanStartLine l
134−
135−-- | Get a collection of lines from a 'Comment'.
136−unComment :: Comment -> NonEmpty String
137−unComment (Comment _ xs) = xs
138−
139−-- | Check whether the 'Comment' had some non-whitespace atoms in front of
140−-- it in the original input.
141−hasAtomsBefore :: Comment -> Bool
142−hasAtomsBefore (Comment atomsBefore _) = atomsBefore
143−
144−-- | Is this comment multiline-style?
145−isMultilineComment :: Comment -> Bool
146−isMultilineComment (Comment _ (x :| _)) = "{-" `L.isPrefixOf` x
147−
148−----------------------------------------------------------------------------
149−-- Helpers
150−
151−-- | Detect and extract stack header if it is present.
152−extractStackHeader ::
153− -- | Comment stream to analyze
154− [RealLocated String] ->
155− ([RealLocated String], Maybe (RealLocated Comment))
156−extractStackHeader = \case
157− [] -> ([], Nothing)
158− (x : xs) ->
159− let comment = snd (mkComment [] x)
160− in if isStackHeader (unRealSrcSpan comment)
161− then (xs, Just comment)
162− else (x : xs, Nothing)
163− where
164− isStackHeader (Comment _ (x :| _)) =
165− "stack" `L.isPrefixOf` dropWhile isSpace (drop 2 x)
166−
167−-- | Extract pragmas and their associated comments.
168−extractPragmas ::
169− -- | Input
170− String ->
171− -- | Comment stream to analyze
172− [RealLocated String] ->
173− ([RealLocated Comment], [([RealLocated Comment], Pragma)])
174−extractPragmas input = go initialLs id id
175− where
176− initialLs = zip [1 ..] (lines input)
177− go ls csSoFar pragmasSoFar = \case
178− [] -> (csSoFar [], pragmasSoFar [])
179− (x : xs) ->
180− case parsePragma (unRealSrcSpan x) of
181− Nothing ->
182− let (ls', x') = mkComment ls x
183− in go ls' (csSoFar . (x' :)) pragmasSoFar xs
184− Just pragma ->
185− let combined ys = (csSoFar ys, pragma)
186− go' ls' ys rest = go ls' id (pragmasSoFar . (combined ys :)) rest
187− in case xs of
188− [] -> go' ls [] xs
189− (y : ys) ->
190− let (ls', y') = mkComment ls y
191− in if onTheSameLine
192− (RealSrcSpan (getRealSrcSpan x))
193− (RealSrcSpan (getRealSrcSpan y))
194− then go' ls' [y'] ys
195− else go' ls [] xs
196111
197112-- | Get a 'String' from 'GHC.AnnotationComment'.
198113unAnnotationComment :: GHC.AnnotationComment -> Maybe String
@@ -214,13 +129,12 @@ toRealSpan :: Located a -> Maybe (RealLocated a)
214129toRealSpan (L (RealSrcSpan l) a) = Just (L l a)
215130toRealSpan _ = Nothing
216131
217−-- | Remove consecutive blank lines.
218−removeConseqBlanks :: NonEmpty String -> NonEmpty String
219−removeConseqBlanks (x :| xs) = x :| go (null x) id xs
220− where
221− go seenBlank acc = \case
222− [] -> acc []
223− (y : ys) ->
224− if seenBlank && null y
225− then go True acc ys
226− else go (null y) (acc . (y :)) ys
132+-- | If a given comment is a pragma, return it in parsed form in 'Right'.
133+-- Otherwise return the original comment unchanged.
134+partitionComments ::
135+ RealLocated String ->
136+ Either (RealLocated String) Pragma
137+partitionComments input =
138+ case parsePragma (unRealSrcSpan input) of
139+ Nothing -> Left input
140+ Just pragma -> Right pragma
src/Ormolu/Parser/Pragma.hs+4−4
@@ -10,7 +10,7 @@ where
1010
1111import Control.Monad
1212import Data.Char (isSpace, toLower)
13−import qualified Data.List as L
13+import Data.List
1414import qualified EnumSet as ES
1515import FastString (mkFastString, unpackFS)
1616import qualified Lexer as L
@@ -35,8 +35,8 @@ parsePragma ::
3535 String ->
3636 Maybe Pragma
3737parsePragma input = do
38− inputNoPrefix <- L.stripPrefix "{-#" input
39− guard ("#-}" `L.isSuffixOf` input)
38+ inputNoPrefix <- stripPrefix "{-#" input
39+ guard ("#-}" `isSuffixOf` input)
4040 let contents = take (length inputNoPrefix - 3) inputNoPrefix
4141 (pragmaName, cs) = (break isSpace . dropWhile isSpace) contents
4242 case toLower <$> pragmaName of
@@ -46,7 +46,7 @@ parsePragma input = do
4646 _ -> Nothing
4747 where
4848 trimSpaces :: String -> String
49− trimSpaces = L.dropWhileEnd isSpace . dropWhile isSpace
49+ trimSpaces = dropWhileEnd isSpace . dropWhile isSpace
5050
5151-- | Assuming the input consists of a series of tokens from a language
5252-- pragma, return the set of enabled extensions.
src/Ormolu/Parser/Result.hs+15−26
@@ -7,38 +7,27 @@ module Ormolu.Parser.Result
77 )
88where
99
10−import Data.Text (Text)
1110import GHC
1211import Ormolu.Parser.Anns
1312import Ormolu.Parser.CommentStream
1413import Ormolu.Parser.Pragma (Pragma)
15−import Ormolu.Parser.Shebang (Shebang)
1614
1715-- | A collection of data that represents a parsed module in Ormolu.
18−data ParseResult = ParseResult
19− { -- | 'ParsedSource' from GHC
20− prParsedSource :: HsModule GhcPs,
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
30− prCommentStream :: CommentStream,
31− -- | Whether or not record dot syntax is enabled
32− prUseRecordDot :: Bool,
33− -- | Whether or not ImportQualifiedPost is enabled
34− prImportQualifiedPost :: Bool,
35− -- | Literal prefix
36− prLiteralPrefix :: Text,
37− -- | Literal suffix
38− prLiteralSuffix :: Text,
39− -- | Indentation level, can be non-zero in case of region formatting
40− prIndent :: Int
41− }
16+data ParseResult
17+ = ParseResult
18+ { -- | 'ParsedSource' from GHC
19+ prParsedSource :: ParsedSource,
20+ -- | Ormolu-specfic representation of annotations
21+ prAnns :: Anns,
22+ -- | Comment stream
23+ prCommentStream :: CommentStream,
24+ -- | Extensions enabled in that module
25+ prExtensions :: [Pragma],
26+ -- | Shebangs found in the input
27+ prShebangs :: [Located String],
28+ -- | Whether or not record dot syntax is enabled
29+ prUseRecordDot :: Bool
30+ }
4231
4332-- | Pretty-print a 'ParseResult'.
4433prettyPrintParseResult :: ParseResult -> String
src/Ormolu/Parser/Shebang.hsdeleted−27
@@ -1,27 +0,0 @@
1−{-# LANGUAGE DeriveDataTypeable #-}
2−
3−-- | A module for dealing with shebangs.
4−module Ormolu.Parser.Shebang
5− ( Shebang (..),
6− extractShebangs,
7− isShebang,
8− )
9−where
10−
11−import Data.Data (Data)
12−import qualified Data.List as L
13−import SrcLoc
14−
15−-- | A wrapper for a shebang.
16−newtype Shebang = Shebang (Located String)
17− deriving (Eq, Data)
18−
19−-- | Extract shebangs from the beginning of a comment stream.
20−extractShebangs :: [Located String] -> ([Shebang], [Located String])
21−extractShebangs comments = (Shebang <$> shebangs, rest)
22− where
23− (shebangs, rest) = span (isShebang . unLoc) comments
24−
25−-- | Return 'True' if given 'String' is a shebang.
26−isShebang :: String -> Bool
27−isShebang str = "#!" `L.isPrefixOf` str
src/Ormolu/Printer.hs+6−17
@@ -11,7 +11,6 @@ import Ormolu.Parser.Result
1111import Ormolu.Printer.Combinators
1212import Ormolu.Printer.Meat.Module
1313import Ormolu.Printer.SpanStream
14−import Ormolu.Processing.Postprocess (postprocess)
1514
1615-- | Render a module.
1716printModule ::
@@ -20,19 +19,9 @@ printModule ::
2019 -- | Resulting rendition
2120 Text
2221printModule ParseResult {..} =
23− prLiteralPrefix <> region <> prLiteralSuffix
24− where
25− region =
26− postprocess prIndent $
27− runR
28− ( p_hsModule
29− prStackHeader
30− prShebangs
31− prPragmas
32− prImportQualifiedPost
33− prParsedSource
34− )
35− (mkSpanStream prParsedSource)
36− prCommentStream
37− prAnns
38− prUseRecordDot
22+ runR
23+ (p_hsModule prShebangs prExtensions prParsedSource)
24+ (mkSpanStream prParsedSource)
25+ prCommentStream
26+ prAnns
27+ prUseRecordDot
src/Ormolu/Printer/Combinators.hs+53−39
@@ -21,9 +21,9 @@ module Ormolu.Printer.Combinators
2121 space,
2222 newline,
2323 inci,
24− inciIf,
2524 located,
2625 located',
26+ locatedPat,
2727 switchLayout,
2828 Layout (..),
2929 vlayout,
@@ -52,57 +52,58 @@ module Ormolu.Printer.Combinators
5252
5353 -- ** Literals
5454 comma,
55− commaDel,
56− equals,
5755
58− -- ** Stateful markers
59− SpanMark (..),
60− spanMarkSpan,
56+ -- ** Comments
6157 HaddockStyle (..),
62− setSpanMark,
63− getSpanMark,
58+ setLastCommentSpan,
59+ getLastCommentSpan,
6460 )
6561where
6662
6763import Control.Monad
64+import Data.Data (Data)
6865import Data.List (intersperse)
6966import Data.Text (Text)
67+import GHC (Pat (XPat), XXPat)
7068import Ormolu.Printer.Comments
7169import Ormolu.Printer.Internal
70+import Ormolu.Utils (isModule)
7271import SrcLoc
7372
7473----------------------------------------------------------------------------
7574-- Basic
7675
77−-- | Indent the inner expression if the first argument is 'True'.
78−inciIf ::
79− -- | Whether to indent
80− Bool ->
81− -- | The expression to indent
82− R () ->
83− R ()
84−inciIf b m = if b then inci m else m
85−
8676-- | Enter a 'Located' entity. This combinator handles outputting comments
8777-- and sets layout (single-line vs multi-line) for the inner computation.
8878-- Roughly, the rule for using 'located' is that every time there is a
8979-- 'Located' wrapper, it should be “discharged” with a corresponding
9080-- 'located' invocation.
9181located ::
82+ Data a =>
9283 -- | Thing to enter
9384 Located a ->
9485 -- | How to render inner value
9586 (a -> R ()) ->
9687 R ()
97−located (L (UnhelpfulSpan _) a) f = f a
98−located (L (RealSrcSpan l) a) f = do
99− spitPrecedingComments l
100− withEnclosingSpan l $
101− switchLayout [RealSrcSpan l] (f a)
102− spitFollowingComments l
88+located loc f = do
89+ let withRealLocated (L l a) g =
90+ case l of
91+ UnhelpfulSpan _ -> return ()
92+ RealSrcSpan l' -> g (L l' a)
93+ withRealLocated loc spitPrecedingComments
94+ let setEnclosingSpan =
95+ case getLoc loc of
96+ UnhelpfulSpan _ -> id
97+ RealSrcSpan orf ->
98+ if isModule (unLoc loc)
99+ then id
100+ else withEnclosingSpan orf
101+ setEnclosingSpan $ switchLayout [getLoc loc] (f (unLoc loc))
102+ withRealLocated loc spitFollowingComments
103103
104104-- | A version of 'located' with arguments flipped.
105105located' ::
106+ Data a =>
106107 -- | How to render inner value
107108 (a -> R ()) ->
108109 -- | Thing to enter
@@ -110,6 +111,28 @@ located' ::
110111 R ()
111112located' = flip located
112113
114+-- | A version of 'located' that works on 'Pat'.
115+--
116+-- Starting from GHC 8.8, @'LPat' == 'Pat'@. Located 'Pat's are always
117+-- constructed with the 'XPat' constructor, containing a @'Located' 'Pat'@.
118+--
119+-- Most of the time, we can just use 'p_pat' directly, because it handles
120+-- located 'Pat's. However, sometimes we want to use the location to render
121+-- something other than the given 'Pat'.
122+--
123+-- If given 'Pat' does not contain a location, we error out.
124+--
125+-- This should become unnecessary if
126+-- <https://gitlab.haskell.org/ghc/ghc/issues/17330> is ever fixed.
127+locatedPat ::
128+ (Data (Pat pass), XXPat pass ~ Located (Pat pass)) =>
129+ Pat pass ->
130+ (Pat pass -> R ()) ->
131+ R ()
132+locatedPat p f = case p of
133+ XPat pat -> located pat f
134+ _ -> error "locatedPat: Pat does not contain a location"
135+
113136-- | Set layout according to combination of given 'SrcSpan's for a given.
114137-- Use this only when you need to set layout based on e.g. combined span of
115138-- several elements when there is no corresponding 'Located' wrapper
@@ -185,12 +208,10 @@ sepSemi f xs = vlayout singleLine multiLine
185208 xs' ->
186209 if ub
187210 then do
188− txt "{"
189− space
190− sep (txt ";" >> space) (dontUseBraces . f) xs'
191− space
192− txt "}"
193− else sep (txt ";" >> space) f xs'
211+ txt "{ "
212+ sep (txt "; ") (dontUseBraces . f) xs'
213+ txt " }"
214+ else sep (txt "; ") f xs'
194215 multiLine =
195216 sep newline (dontUseBraces . f) xs
196217
@@ -203,7 +224,6 @@ data BracketStyle
203224 N
204225 | -- | Shifted one level
205226 S
206− deriving (Eq, Show)
207227
208228-- | Surround given entity by backticks.
209229backticks :: R () -> R ()
@@ -280,7 +300,9 @@ brackets_ needBreaks open close style m = sitcc (vlayout singleLine multiLine)
280300 then newline >> inci m
281301 else space >> sitcc m
282302 newline
283− inciIf (style == S) (txt close)
303+ case style of
304+ N -> txt close
305+ S -> inci (txt close)
284306
285307----------------------------------------------------------------------------
286308-- Literals
@@ -288,11 +310,3 @@ brackets_ needBreaks open close style m = sitcc (vlayout singleLine multiLine)
288310-- | Print @,@.
289311comma :: R ()
290312comma = txt ","
291−
292−-- | Delimiting combination with 'comma'. To be used with 'sep'.
293−commaDel :: R ()
294−commaDel = comma >> breakpoint
295−
296−-- | Print @=@. Do not use @'txt' "="@.
297−equals :: R ()
298−equals = interferingTxt "="
src/Ormolu/Printer/Comments.hs+76−62
@@ -1,4 +1,3 @@
1−{-# LANGUAGE LambdaCase #-}
21{-# LANGUAGE OverloadedStrings #-}
32
43-- | Helpers for formatting of comments. This is low-level code, use
@@ -7,17 +6,21 @@ module Ormolu.Printer.Comments
76 ( spitPrecedingComments,
87 spitFollowingComments,
98 spitRemainingComments,
10− spitCommentNow,
11− spitCommentPending,
9+ spitStackHeader,
1210 )
1311where
1412
1513import Control.Monad
14+import Data.Char (isSpace)
15+import Data.Coerce (coerce)
16+import Data.Data (Data)
17+import Data.List (isPrefixOf)
1618import qualified Data.List.NonEmpty as NE
17−import Data.Maybe (listToMaybe)
19+import Data.List.NonEmpty (NonEmpty (..))
1820import qualified Data.Text as T
1921import Ormolu.Parser.CommentStream
2022import Ormolu.Printer.Internal
23+import Ormolu.Utils (isModule)
2124import SrcLoc
2225
2326----------------------------------------------------------------------------
@@ -25,91 +28,108 @@ import SrcLoc
2528
2629-- | Output all preceding comments for an element at given location.
2730spitPrecedingComments ::
28− -- | Span of the element to attach comments to
29− RealSrcSpan ->
31+ Data a =>
32+ -- | AST element to attach comments to
33+ RealLocated a ->
3034 R ()
3135spitPrecedingComments ref = do
3236 gotSome <- handleCommentSeries (spitPrecedingComment ref)
3337 when gotSome $ do
34− lastMark <- getSpanMark
3538 -- Insert a blank line between the preceding comments and the thing
3639 -- after them if there was a blank line in the input.
37− when (needsNewlineBefore ref lastMark) newline
40+ lastSpn <- fmap snd <$> getLastCommentSpan
41+ when (needsNewlineBefore (getRealSrcSpan ref) lastSpn) newline
3842
3943-- | Output all comments following an element at given location.
4044spitFollowingComments ::
41− -- | Span of the element to attach comments to
42− RealSrcSpan ->
45+ Data a =>
46+ -- | AST element of attach comments to
47+ RealLocated a ->
4348 R ()
4449spitFollowingComments ref = do
45− trimSpanStream ref
50+ trimSpanStream (getRealSrcSpan ref)
4651 void $ handleCommentSeries (spitFollowingComment ref)
4752
4853-- | Output all remaining comments in the comment stream.
4954spitRemainingComments :: R ()
50−spitRemainingComments = do
51− -- Make sure we have a blank a line between the last definition and the
52− -- trailing comments.
53− newline
54− void $ handleCommentSeries spitRemainingComment
55+spitRemainingComments = void $ handleCommentSeries spitRemainingComment
56+
57+-- | If there is a stack header in the comment stream, print it.
58+spitStackHeader :: R ()
59+spitStackHeader = do
60+ let isStackHeader (Comment (x :| _)) =
61+ "stack" `isPrefixOf` dropWhile isSpace (drop 2 x)
62+ mstackHeader <- popComment (isStackHeader . unRealSrcSpan)
63+ forM_ mstackHeader $ \(L spn x) -> do
64+ spitCommentNow spn x
65+ newline
5566
5667----------------------------------------------------------------------------
5768-- Single-comment functions
5869
5970-- | Output a single preceding comment for an element at given location.
6071spitPrecedingComment ::
61− -- | Span of the element to attach comments to
62− RealSrcSpan ->
72+ Data a =>
73+ -- | AST element to attach comments to
74+ RealLocated a ->
75+ -- | Location of last comment in the series
76+ Maybe RealSrcSpan ->
6377 -- | Are we done?
6478 R Bool
65−spitPrecedingComment ref = do
66− mlastMark <- getSpanMark
79+spitPrecedingComment (L ref a) mlastSpn = do
6780 let p (L l _) = realSrcSpanEnd l <= realSrcSpanStart ref
6881 withPoppedComment p $ \l comment -> do
69− lineSpans <- thisLineSpans
70− let thisCommentLine = srcLocLine (realSrcSpanStart l)
71− needsNewline =
72− case listToMaybe lineSpans of
73− Nothing -> False
74− Just spn -> srcLocLine (realSrcSpanEnd spn) /= thisCommentLine
75− when (needsNewline || needsNewlineBefore l mlastMark) newline
82+ dirtyLine <-
83+ case mlastSpn of
84+ -- When the current line is dirty it means that something that can
85+ -- have comments attached to it is already on the line. To avoid
86+ -- problems with idempotence we cannot output the first comment
87+ -- immediately because it'll be attached to the previous element (on
88+ -- the same line) on the next run, so we play safe here and output
89+ -- an extra 'newline' in this case.
90+ Nothing -> isLineDirty -- only for very first preceding comment
91+ Just _ -> return False
92+ when (dirtyLine || needsNewlineBefore l mlastSpn) newline
7693 spitCommentNow l comment
77− if theSameLinePre l ref
94+ if theSameLinePre l ref && not (isModule a)
7895 then space
7996 else newline
8097
8198-- | Output a comment that follows element at given location immediately on
8299-- the same line, if there is any.
83100spitFollowingComment ::
101+ Data a =>
84102 -- | AST element to attach comments to
85− RealSrcSpan ->
103+ RealLocated a ->
104+ -- | Location of last comment in the series
105+ Maybe RealSrcSpan ->
86106 -- | Are we done?
87107 R Bool
88−spitFollowingComment ref = do
89− mlastMark <- getSpanMark
108+spitFollowingComment (L ref a) mlastSpn = do
90109 mnSpn <- nextEltSpan
91110 -- Get first enclosing span that is not equal to reference span, i.e. it's
92111 -- truly something enclosing the AST element.
93112 meSpn <- getEnclosingSpan (/= ref)
94− withPoppedComment (commentFollowsElt ref mnSpn meSpn mlastMark) $ \l comment ->
95− if theSameLinePost l ref
113+ withPoppedComment (commentFollowsElt ref mnSpn meSpn mlastSpn) $ \l comment ->
114+ if theSameLinePost l ref && not (isModule a)
96115 then
97116 if isMultilineComment comment
98117 then space >> spitCommentNow l comment
99118 else spitCommentPending OnTheSameLine l comment
100119 else do
101− when (needsNewlineBefore l mlastMark) $
120+ when (needsNewlineBefore l mlastSpn) $
102121 registerPendingCommentLine OnNextLine ""
103122 spitCommentPending OnNextLine l comment
104123
105124-- | Output a single remaining comment from the comment stream.
106125spitRemainingComment ::
126+ -- | Location of last comment in the series
127+ Maybe RealSrcSpan ->
107128 -- | Are we done?
108129 R Bool
109−spitRemainingComment = do
110− mlastMark <- getSpanMark
130+spitRemainingComment mlastSpn =
111131 withPoppedComment (const True) $ \l comment -> do
112− when (needsNewlineBefore l mlastMark) newline
132+ when (needsNewlineBefore l mlastSpn) newline
113133 spitCommentNow l comment
114134 newline
115135
@@ -120,13 +140,13 @@ spitRemainingComment = do
120140handleCommentSeries ::
121141 -- | Given location of previous comment, output the next comment
122142 -- returning 'True' if we're done
123− R Bool ->
143+ (Maybe RealSrcSpan -> R Bool) ->
124144 -- | Whether we printed any comments
125145 R Bool
126146handleCommentSeries f = go False
127147 where
128148 go gotSome = do
129− done <- f
149+ done <- getLastCommentSpan >>= f . fmap snd
130150 if done
131151 then return gotSome
132152 else go True
@@ -152,14 +172,13 @@ needsNewlineBefore ::
152172 -- | Current comment span
153173 RealSrcSpan ->
154174 -- | Last printed comment span
155− Maybe SpanMark ->
175+ Maybe RealSrcSpan ->
156176 Bool
157−needsNewlineBefore _ (Just (HaddockSpan _ _)) = True
158−needsNewlineBefore l mlastMark =
159− case spanMarkSpan <$> mlastMark of
177+needsNewlineBefore l mlastSpn =
178+ case mlastSpn of
160179 Nothing -> False
161− Just lastMark ->
162− srcSpanStartLine l > srcSpanEndLine lastMark + 1
180+ Just lastSpn ->
181+ srcSpanStartLine l > srcSpanEndLine lastSpn + 1
163182
164183-- | Is the preceding comment and AST element are on the same line?
165184theSameLinePre ::
@@ -190,11 +209,11 @@ commentFollowsElt ::
190209 -- | Location of enclosing AST element
191210 Maybe RealSrcSpan ->
192211 -- | Location of last comment in the series
193− Maybe SpanMark ->
212+ Maybe RealSrcSpan ->
194213 -- | Comment to test
195214 RealLocated Comment ->
196215 Bool
197−commentFollowsElt ref mnSpn meSpn mlastMark (L l comment) =
216+commentFollowsElt ref mnSpn meSpn mlastSpn (L l comment) =
198217 -- A comment follows a AST element if all 4 conditions are satisfied:
199218 goesAfter
200219 && logicallyFollows
@@ -207,8 +226,9 @@ commentFollowsElt ref mnSpn meSpn mlastMark (L l comment) =
207226 -- 2) The comment logically belongs to the element, four cases:
208227 logicallyFollows =
209228 theSameLinePost l ref -- a) it's on the same line
210− || continuation -- b) it's a continuation of a comment block
211− || lastInEnclosing -- c) it's the last element in the enclosing construct
229+ || isPrevHaddock comment -- b) it's a Haddock string starting with -- ^
230+ || continuation -- c) it's a continuation of a comment block
231+ || lastInEnclosing -- d) it's the last element in the enclosing construct
212232
213233 -- 3) There is no other AST element between this element and the comment:
214234 noEltBetween =
@@ -235,15 +255,9 @@ commentFollowsElt ref mnSpn meSpn mlastMark (L l comment) =
235255 >= abs (startColumn ref - startColumn l)
236256 )
237257 continuation =
238− -- A comment is a continuation when it doesn't have non-whitespace
239− -- lexemes in front of it and goes right after the previous comment.
240− not (hasAtomsBefore comment)
241− && ( case mlastMark of
242− Just (HaddockSpan _ _) -> False
243− Just (CommentSpan spn) ->
244− srcSpanEndLine spn + 1 == srcSpanStartLine l
245− _ -> False
246− )
258+ case mlastSpn of
259+ Nothing -> False
260+ Just spn -> srcSpanEndLine spn + 1 == srcSpanStartLine l
247261 lastInEnclosing =
248262 case meSpn of
249263 -- When there is no enclosing element, return false
@@ -265,9 +279,9 @@ spitCommentNow spn comment = do
265279 . sequence_
266280 . NE.intersperse newline
267281 . fmap (txt . T.pack)
268− . unComment
282+ . coerce
269283 $ comment
270− setSpanMark (CommentSpan spn)
284+ setLastCommentSpan Nothing spn
271285
272286-- | Output a 'Comment' at the end of correct line or after it depending on
273287-- 'CommentPosition'. Used for comments that may potentially follow on the
@@ -281,6 +295,6 @@ spitCommentPending position spn comment = do
281295 . sequence_
282296 . NE.toList
283297 . fmap (registerPendingCommentLine position . T.pack)
284− . unComment
298+ . coerce
285299 $ comment
286− setSpanMark (CommentSpan spn)
300+ setLastCommentSpan Nothing spn
src/Ormolu/Printer/Internal.hs+96−149
@@ -1,5 +1,4 @@
11{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2−{-# LANGUAGE LambdaCase #-}
32{-# LANGUAGE OverloadedStrings #-}
43{-# LANGUAGE RankNTypes #-}
54
@@ -14,10 +13,10 @@ module Ormolu.Printer.Internal
1413
1514 -- * Internal functions
1615 txt,
17− interferingTxt,
1816 atom,
1917 space,
2018 newline,
19+ isLineDirty,
2120 useRecordDot,
2221 inci,
2322 sitcc,
@@ -39,14 +38,9 @@ module Ormolu.Printer.Internal
3938 popComment,
4039 getEnclosingSpan,
4140 withEnclosingSpan,
42− thisLineSpans,
43−
44− -- * Stateful markers
45− SpanMark (..),
46− spanMarkSpan,
4741 HaddockStyle (..),
48− setSpanMark,
49− getSpanMark,
42+ setLastCommentSpan,
43+ getLastCommentSpan,
5044
5145 -- * Annotations
5246 getAnns,
@@ -79,44 +73,45 @@ newtype R a = R (ReaderT RC (State SC) a)
7973
8074-- | Reader context of 'R'. This should be used when we control rendering by
8175-- enclosing certain expressions with wrappers.
82−data RC = RC
83− { -- | Indentation level, as the column index we need to start from after
84− -- a newline if we break lines
85− rcIndent :: !Int,
86− -- | Current layout
87− rcLayout :: Layout,
88− -- | Spans of enclosing elements of AST
89− rcEnclosingSpans :: [RealSrcSpan],
90− -- | Collection of annotations
91− rcAnns :: Anns,
92− -- | Whether the last expression in the layout can use braces
93− rcCanUseBraces :: Bool,
94− -- | Whether the source could have used the record dot preprocessor
95− rcUseRecDot :: Bool
96− }
76+data RC
77+ = RC
78+ { -- | Indentation level, as the column index we need to start from after
79+ -- a newline if we break lines
80+ rcIndent :: !Int,
81+ -- | Current layout
82+ rcLayout :: Layout,
83+ -- | Spans of enclosing elements of AST
84+ rcEnclosingSpans :: [RealSrcSpan],
85+ -- | Collection of annotations
86+ rcAnns :: Anns,
87+ -- | Whether the last expression in the layout can use braces
88+ rcCanUseBraces :: Bool,
89+ -- | Whether the source could have used the record dot preprocessor
90+ rcUseRecDot :: Bool
91+ }
9792
9893-- | State context of 'R'.
99−data SC = SC
100− { -- | Index of the next column to render
101− scColumn :: !Int,
102− -- | Indentation level that was used for the current line
103− scIndent :: !Int,
104− -- | Rendered source code so far
105− scBuilder :: Builder,
106− -- | Span stream
107− scSpanStream :: SpanStream,
108− -- | Spans of atoms that have been printed on the current line so far
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)
119− }
94+data SC
95+ = SC
96+ { -- | Index of the next column to render
97+ scColumn :: !Int,
98+ -- | Rendered source code so far
99+ scBuilder :: Builder,
100+ -- | Span stream
101+ scSpanStream :: SpanStream,
102+ -- | Comment stream
103+ scCommentStream :: CommentStream,
104+ -- | Pending comment lines (in reverse order) to be inserted before next
105+ -- newline, 'Int' is the indentation level
106+ scPendingComments :: ![(CommentPosition, Int, Text)],
107+ -- | Whether the current line is “dirty”, that is, already contains
108+ -- atoms that can have comments attached to them
109+ scDirtyLine :: !Bool,
110+ -- | Whether to output a space before the next output
111+ scRequestedDelimiter :: !RequestedDelimiter,
112+ -- | Span of last output comment
113+ scLastCommentSpan :: !(Maybe (Maybe HaddockStyle, RealSrcSpan))
114+ }
120115
121116-- | Make sure next output is delimited by one of the following.
122117data RequestedDelimiter
@@ -177,36 +172,18 @@ runR (R m) sstream cstream anns recDot =
177172 sc =
178173 SC
179174 { scColumn = 0,
180− scIndent = 0,
181175 scBuilder = mempty,
182176 scSpanStream = sstream,
183− scThisLineSpans = [],
184177 scCommentStream = cstream,
185178 scPendingComments = [],
179+ scDirtyLine = False,
186180 scRequestedDelimiter = VeryBeginning,
187− scSpanMark = Nothing
181+ scLastCommentSpan = Nothing
188182 }
189183
190184----------------------------------------------------------------------------
191185-- Internal functions
192186
193−-- | Type of the thing to output. Influences the primary low-level rendering
194−-- function 'spit'.
195−data SpitType
196− = -- | Simple opaque text that breaks comment series.
197− SimpleText
198− | -- | Like 'SimpleText', but assume that when this text is inserted it
199− -- will separate an 'Atom' and its pending comments, so insert an extra
200− -- 'newline' in that case to force the pending comments and continue on
201− -- a fresh line.
202− InterferingText
203− | -- | An atom that typically have span information in the AST and can
204− -- have comments attached to it.
205− Atom
206− | -- | Used for rendering comment lines.
207− CommentPart
208− deriving (Show, Eq)
209−
210187-- | Output a fixed 'Text' fragment. The argument may not contain any line
211188-- breaks. 'txt' is used to output all sorts of “fixed” bits of syntax like
212189-- keywords and pipes @|@ in functional dependencies.
@@ -218,15 +195,7 @@ txt ::
218195 -- | 'Text' to output
219196 Text ->
220197 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
198+txt = spit False False
230199
231200-- | Output 'Outputable' fragment of AST. This can be used to output numeric
232201-- literals and similar. Everything that doesn't have inner structure but
@@ -235,61 +204,48 @@ atom ::
235204 Outputable a =>
236205 a ->
237206 R ()
238−atom = spit Atom . T.pack . showOutputable
207+atom = spit True False . T.pack . showOutputable
239208
240209-- | Low-level non-public helper to define 'txt' and 'atom'.
241210spit ::
242− -- | Type of the thing to spit
243− SpitType ->
211+ -- | Should we mark the line as dirty?
212+ Bool ->
213+ -- | Used during outputting of pending comments?
214+ Bool ->
244215 -- | 'Text' to output
245216 Text ->
246217 R ()
247−spit _ "" = return ()
248−spit stype text = do
218+spit dirty printingComments txt' = do
249219 requestedDel <- R (gets scRequestedDelimiter)
250− pendingComments <- R (gets scPendingComments)
251− when (stype == InterferingText && not (null pendingComments)) newline
252220 case requestedDel of
253221 RequestedNewline -> do
254222 R . modify $ \sc ->
255223 sc
256224 { scRequestedDelimiter = RequestedNothing
257225 }
258− case stype of
259− CommentPart -> newlineRaw
260− _ -> newline
226+ if printingComments
227+ then newlineRaw
228+ else newline
261229 _ -> return ()
262230 R $ do
263231 i <- asks rcIndent
264232 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)
233+ let spaces =
234+ if c < i
235+ then T.replicate (i - c) " "
236+ else bool mempty " " (requestedDel == RequestedSpace)
237+ indentedTxt = spaces <> txt'
272238 modify $ \sc ->
273239 sc
274240 { scBuilder = scBuilder sc <> fromText indentedTxt,
275241 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,
242+ scDirtyLine = scDirtyLine sc || dirty,
287243 scRequestedDelimiter = RequestedNothing,
288− scSpanMark =
244+ scLastCommentSpan =
289245 -- If there are pending comments, do not reset last comment
290246 -- location.
291− if (stype == CommentPart) || (not . null . scPendingComments) sc
292− then scSpanMark sc
247+ if printingComments || (not . null . scPendingComments) sc
248+ then scLastCommentSpan sc
293249 else Nothing
294250 }
295251
@@ -320,22 +276,21 @@ space = R . modify $ \sc ->
320276-- hard to output more than one blank newline in a row.
321277newline :: R ()
322278newline = do
323− indent <- R (gets scIndent)
324279 cs <- reverse <$> R (gets scPendingComments)
325280 case cs of
326281 [] -> newlineRaw
327− ((position, _) : _) -> do
282+ ((position, _, _) : _) -> do
328283 case position of
329284 OnTheSameLine -> space
330285 OnNextLine -> newlineRaw
331− R . forM_ cs $ \(_, text) ->
286+ R . forM_ cs $ \(_, indent, txt') ->
332287 let modRC rc =
333288 rc
334289 { rcIndent = indent
335290 }
336291 R m = do
337− unless (T.null text) $
338− spit CommentPart text
292+ unless (T.null txt') $
293+ spit False True txt'
339294 newlineRaw
340295 in local modRC m
341296 R . modify $ \sc ->
@@ -356,8 +311,7 @@ newlineRaw = R . modify $ \sc ->
356311 VeryBeginning -> builderSoFar
357312 _ -> builderSoFar <> "\n",
358313 scColumn = 0,
359− scIndent = 0,
360− scThisLineSpans = [],
314+ scDirtyLine = False,
361315 scRequestedDelimiter = case scRequestedDelimiter sc of
362316 AfterNewline -> RequestedNewline
363317 RequestedNewline -> RequestedNewline
@@ -365,9 +319,14 @@ newlineRaw = R . modify $ \sc ->
365319 _ -> AfterNewline
366320 }
367321
322+-- | Check if the current line is “dirty”, that is, there is something on it
323+-- that can have comments attached to it.
324+isLineDirty :: R Bool
325+isLineDirty = R (gets scDirtyLine)
326+
368327-- | Return 'True' if we should print record dot syntax.
369328useRecordDot :: R Bool
370−useRecordDot = R (asks rcUseRecDot)
329+useRecordDot = R $ asks rcUseRecDot
371330
372331-- | Increase indentation level by one indentation step for the inner
373332-- computation. 'inci' should be used when a part of code must be more
@@ -384,7 +343,8 @@ inci (R m) = R (local modRC m)
384343
385344-- | Set indentation level for the inner computation equal to current
386345-- column. This makes sure that the entire inner block is uniformly
387−-- \"shifted\" to the right.
346+-- \"shifted\" to the right. Only works (and makes sense) when enclosing
347+-- layout is multi-line.
388348sitcc :: R () -> R ()
389349sitcc (R m) = do
390350 requestedDel <- R (gets scRequestedDelimiter)
@@ -392,9 +352,16 @@ sitcc (R m) = do
392352 c <- R (gets scColumn)
393353 let modRC rc =
394354 rc
395− { rcIndent = max i (c + bool 0 1 (requestedDel == RequestedSpace))
355+ { rcIndent = max i c + bool 0 1 (requestedDel == RequestedSpace)
396356 }
397− R (local modRC m)
357+ vlayout (R m) . R $ do
358+ modify $ \sc ->
359+ sc
360+ { scRequestedDelimiter = case requestedDel of
361+ RequestedSpace -> RequestedNothing
362+ other -> other
363+ }
364+ local modRC m
398365
399366-- | Set 'Layout' for internal computation.
400367enterLayout :: Layout -> R () -> R ()
@@ -435,10 +402,11 @@ registerPendingCommentLine ::
435402 -- | 'Text' to output
436403 Text ->
437404 R ()
438−registerPendingCommentLine position text = R $ do
405+registerPendingCommentLine position txt' = R $ do
406+ i <- asks rcIndent
439407 modify $ \sc ->
440408 sc
441− { scPendingComments = (position, text) : scPendingComments sc
409+ { scPendingComments = (position, i, txt') : scPendingComments sc
442410 }
443411
444412-- | Drop elements that begin before or at the same place as given
@@ -497,29 +465,6 @@ withEnclosingSpan spn (R m) = R (local modRC m)
497465 { rcEnclosingSpans = spn : rcEnclosingSpans rc
498466 }
499467
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−
523468-- | Haddock string style.
524469data HaddockStyle
525470 = -- | @-- |@
@@ -532,18 +477,20 @@ data HaddockStyle
532477 Named String
533478
534479-- | Set span of last output comment.
535−setSpanMark ::
536− -- | Span mark to set
537− SpanMark ->
480+setLastCommentSpan ::
481+ -- | 'HaddockStyle' or 'Nothing' if it's a non-Haddock comment
482+ Maybe HaddockStyle ->
483+ -- | Location of last printed comment
484+ RealSrcSpan ->
538485 R ()
539−setSpanMark spnMark = R . modify $ \sc ->
486+setLastCommentSpan mhStyle spn = R . modify $ \sc ->
540487 sc
541− { scSpanMark = Just spnMark
488+ { scLastCommentSpan = Just (mhStyle, spn)
542489 }
543490
544491-- | Get span of last output comment.
545−getSpanMark :: R (Maybe SpanMark)
546−getSpanMark = R (gets scSpanMark)
492+getLastCommentSpan :: R (Maybe (Maybe HaddockStyle, RealSrcSpan))
493+getLastCommentSpan = R (gets scLastCommentSpan)
547494
548495----------------------------------------------------------------------------
549496-- Annotations
@@ -567,7 +514,7 @@ dontUseBraces (R r) = R (local (\i -> i {rcCanUseBraces = False}) r)
567514
568515-- | Return 'True' if we can use braces in this context.
569516canUseBraces :: R Bool
570−canUseBraces = R (asks rcCanUseBraces)
517+canUseBraces = R $ asks rcCanUseBraces
571518
572519----------------------------------------------------------------------------
573520-- Constants
src/Ormolu/Printer/Meat/Common.hs+11−13
@@ -17,12 +17,14 @@ where
1717
1818import Control.Monad
1919import Data.List (isPrefixOf)
20+import Data.Maybe (isJust)
2021import qualified Data.Text as T
2122import GHC hiding (GhcPs, IE)
2223import Name (nameStableString)
2324import OccName (OccName (..))
2425import Ormolu.Printer.Combinators
2526import Ormolu.Utils
27+import RdrName (RdrName (..))
2628
2729-- | Data and type family style.
2830data FamilyStyle
@@ -114,14 +116,14 @@ p_qualName mname occName = do
114116p_infixDefHelper ::
115117 -- | Whether to format in infix style
116118 Bool ->
117− -- | Whether to bump indentation for arguments
118− Bool ->
119+ -- | Indentation-bumping wrapper
120+ (R () -> R ()) ->
119121 -- | How to print the operator\/name
120122 R () ->
121123 -- | How to print the arguments
122124 [R ()] ->
123125 R ()
124−p_infixDefHelper isInfix indentArgs name args =
126+p_infixDefHelper isInfix inci' name args =
125127 case (isInfix, args) of
126128 (True, p0 : p1 : ps) -> do
127129 let parens' =
@@ -131,18 +133,18 @@ p_infixDefHelper isInfix indentArgs name args =
131133 parens' $ do
132134 p0
133135 breakpoint
134− inci . sitcc $ do
136+ inci $ sitcc $ do
135137 name
136138 space
137139 p1
138− unless (null ps) . inciIf indentArgs $ do
140+ unless (null ps) . inci' $ do
139141 breakpoint
140142 sitcc (sep breakpoint sitcc ps)
141143 (_, ps) -> do
142144 name
143145 unless (null ps) $ do
144146 breakpoint
145− inciIf indentArgs $ sitcc (sep breakpoint sitcc args)
147+ inci' $ sitcc (sep breakpoint sitcc args)
146148
147149-- | Print a Haddock.
148150p_hsDocString ::
@@ -154,11 +156,7 @@ p_hsDocString ::
154156 LHsDocString ->
155157 R ()
156158p_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
159+ goesAfterComment <- isJust <$> getLastCommentSpan
162160 -- Make sure the Haddock is separated by a newline from other comments.
163161 when goesAfterComment newline
164162 forM_ (zip (splitDocString str) (True : repeat False)) $ \(x, isFirst) -> do
@@ -177,8 +175,8 @@ p_hsDocString hstyle needsNewline (L l str) = do
177175 -- It's often the case that the comment itself doesn't have a span
178176 -- attached to it and instead its location can be obtained from
179177 -- nearest enclosing span.
180− getEnclosingSpan (const True) >>= mapM_ (setSpanMark . HaddockSpan hstyle)
181− RealSrcSpan spn -> setSpanMark (HaddockSpan hstyle spn)
178+ getEnclosingSpan (const True) >>= mapM_ (setLastCommentSpan (Just hstyle))
179+ RealSrcSpan spn -> setLastCommentSpan (Just hstyle) spn
182180
183181-- | Print anchor of named doc section.
184182p_hsDocName :: String -> R ()
src/Ormolu/Printer/Meat/Declaration.hs+110−138
@@ -12,7 +12,7 @@ module Ormolu.Printer.Meat.Declaration
1212where
1313
1414import Data.List (sort)
15−import Data.List.NonEmpty (NonEmpty (..), (<|))
15+import Data.List.NonEmpty ((<|), NonEmpty (..))
1616import qualified Data.List.NonEmpty as NE
1717import GHC hiding (InlinePragma)
1818import OccName (occNameFS)
@@ -34,6 +34,7 @@ import Ormolu.Printer.Meat.Declaration.Value
3434import Ormolu.Printer.Meat.Declaration.Warning
3535import Ormolu.Printer.Meat.Type
3636import Ormolu.Utils
37+import RdrName (rdrNameOcc)
3738
3839data UserGrouping
3940 = -- | Always put newlines where we think they should be
@@ -54,27 +55,25 @@ p_hsDeclsRespectGrouping :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
5455p_hsDeclsRespectGrouping = p_hsDecls' Respect
5556
5657p_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)
58+p_hsDecls' grouping style decls = 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)
6464 where
6565 renderGroup = NE.toList . fmap (located' $ dontUseBraces . p_hsDecl style)
6666 renderGroupWithPrev prev curr =
6767 -- We can omit a blank line when the user didn't add one, but we must
6868 -- 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
69+ if or
70+ [ grouping == Disregard,
71+ separatedByBlank getLoc prev curr,
72+ isDocumented prev,
73+ isDocumented curr
74+ ]
75+ then breakpoint : renderGroup curr
76+ else renderGroup curr
7877
7978-- | Is a declaration group documented?
8079isDocumented :: NonEmpty (LHsDecl GhcPs) -> Bool
@@ -85,6 +84,9 @@ isDocumented = any (isHaddock . unLoc)
8584 isHaddock _ = False
8685
8786-- | Group relevant declarations together.
87+--
88+-- Add a declaration to a group iff it is relevant to either the first or
89+-- the last declaration of the group.
8890groupDecls :: [LHsDecl GhcPs] -> [NonEmpty (LHsDecl GhcPs)]
8991groupDecls [] = []
9092groupDecls (l@(L _ DocNext) : xs) =
@@ -93,40 +95,44 @@ groupDecls (l@(L _ DocNext) : xs) =
9395 case groupDecls xs of
9496 [] -> [l :| []]
9597 (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)
98+groupDecls (lhdr : xs) =
99+ let -- Pick the first decl as the group header
100+ hdr = unLoc lhdr
101+ -- Zip rest of the decls with their previous decl
102+ zipped = zip (lhdr : xs) xs
103+ -- Pick decls from the tail if they are relevant to the group header
104+ -- or the previous decl.
105+ (grp, rest) = flip span zipped $ \(L _ prev, L _ cur) ->
106+ let relevantToHdr = groupedDecls hdr cur
107+ relevantToPrev = groupedDecls prev cur
108+ in relevantToHdr || relevantToPrev
109+ in (lhdr :| map snd grp) : groupDecls (map snd rest)
103110
104111p_hsDecl :: FamilyStyle -> HsDecl GhcPs -> R ()
105112p_hsDecl style = \case
106− TyClD NoExtField x -> p_tyClDecl style x
107− ValD NoExtField x -> p_valDecl x
108− SigD NoExtField x -> p_sigDecl x
109− InstD NoExtField x -> p_instDecl style x
110− DerivD NoExtField x -> p_derivDecl x
111− DefD NoExtField x -> p_defaultDecl x
112− ForD NoExtField x -> p_foreignDecl x
113− WarningD NoExtField x -> p_warnDecls x
114− AnnD NoExtField x -> p_annDecl x
115− RuleD NoExtField x -> p_ruleDecls x
116− SpliceD NoExtField x -> p_spliceDecl x
117− DocD NoExtField docDecl ->
113+ TyClD NoExt x -> p_tyClDecl style x
114+ ValD NoExt x -> p_valDecl x
115+ SigD NoExt x -> p_sigDecl x
116+ InstD NoExt x -> p_instDecl style x
117+ DerivD NoExt x -> p_derivDecl x
118+ DefD NoExt x -> p_defaultDecl x
119+ ForD NoExt x -> p_foreignDecl x
120+ WarningD NoExt x -> p_warnDecls x
121+ AnnD NoExt x -> p_annDecl x
122+ RuleD NoExt x -> p_ruleDecls x
123+ SpliceD NoExt x -> p_spliceDecl x
124+ DocD NoExt docDecl ->
118125 case docDecl of
119126 DocCommentNext str -> p_hsDocString Pipe False (noLoc str)
120127 DocCommentPrev str -> p_hsDocString Caret False (noLoc str)
121128 DocCommentNamed name str -> p_hsDocString (Named name) False (noLoc str)
122129 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
130+ RoleAnnotD NoExt x -> p_roleAnnot x
131+ XHsDecl _ -> notImplemented "XHsDecl"
126132
127133p_tyClDecl :: FamilyStyle -> TyClDecl GhcPs -> R ()
128134p_tyClDecl style = \case
129− FamDecl NoExtField x -> p_famDecl style x
135+ FamDecl NoExt x -> p_famDecl style x
130136 SynDecl {..} -> p_synDecl tcdLName tcdFixity tcdTyVars tcdRhs
131137 DataDecl {..} ->
132138 p_dataDecl
@@ -147,65 +153,43 @@ p_tyClDecl style = \case
147153 tcdATs
148154 tcdATDefs
149155 tcdDocs
150− XTyClDecl x -> noExtCon x
156+ XTyClDecl {} -> notImplemented "XTyClDecl"
151157
152158p_instDecl :: FamilyStyle -> InstDecl GhcPs -> R ()
153159p_instDecl style = \case
154− ClsInstD NoExtField x -> p_clsInstDecl x
155− TyFamInstD NoExtField x -> p_tyFamInstDecl style x
156− DataFamInstD NoExtField x -> p_dataFamInstDecl style x
157− XInstDecl x -> noExtCon x
160+ ClsInstD NoExt x -> p_clsInstDecl x
161+ TyFamInstD NoExt x -> p_tyFamInstDecl style x
162+ DataFamInstD NoExt x -> p_dataFamInstDecl style x
163+ XInstDecl _ -> notImplemented "XInstDecl"
158164
159165p_derivDecl :: DerivDecl GhcPs -> R ()
160166p_derivDecl = \case
161− d@DerivDecl {} -> p_standaloneDerivDecl d
162− XDerivDecl x -> noExtCon x
167+ d@DerivDecl {..} -> p_standaloneDerivDecl d
168+ XDerivDecl _ -> notImplemented "XDerivDecl standalone deriving"
163169
164170-- | Determine if these declarations should be grouped together.
165171groupedDecls ::
166− LHsDecl GhcPs ->
167− LHsDecl GhcPs ->
168− Bool
169−groupedDecls (L l_x x') (L l_y y') =
170− case (x', y') of
171− (TypeSignature ns, FunctionBody ns') -> ns `intersects` ns'
172− (TypeSignature ns, DefaultSignature ns') -> ns `intersects` ns'
173− (DefaultSignature ns, TypeSignature ns') -> ns `intersects` ns'
174− (DefaultSignature ns, FunctionBody ns') -> ns `intersects` ns'
175− (x, FunctionBody ns) | Just ns' <- isPragma x -> ns `intersects` ns'
176− (FunctionBody ns, x) | Just ns' <- isPragma x -> ns `intersects` ns'
177− (x, DataDeclaration n) | Just ns <- isPragma x -> n `elem` ns
178− (DataDeclaration n, x)
179− | Just ns <- isPragma x ->
180− let f = occNameFS . rdrNameOcc in f n `elem` map f ns
181− (x, y)
182− | Just ns <- isPragma x,
183− Just ns' <- isPragma y ->
184− ns `intersects` ns'
185− (x, TypeSignature ns) | Just ns' <- isPragma x -> ns `intersects` ns'
186− (TypeSignature ns, x) | Just ns' <- isPragma x -> ns `intersects` ns'
187− (PatternSignature ns, Pattern n) -> n `elem` ns
188− (KindSignature n, DataDeclaration n') -> n == n'
189− (KindSignature n, ClassDeclaration n') -> n == n'
190− (KindSignature n, FamilyDeclaration n') -> n == n'
191− -- Special case for TH splices, we look at locations
192− (Splice, Splice) -> not (separatedByBlank id l_x l_y)
193− -- This looks only at Haddocks, normal comments are handled elsewhere
194− (DocNext, _) -> True
195− (_, DocPrev) -> True
196− _ -> False
197−
198−-- | Detect declaration series that should not have blanks between them.
199−declSeries ::
200− LHsDecl GhcPs ->
201− LHsDecl GhcPs ->
172+ HsDecl GhcPs ->
173+ HsDecl GhcPs ->
202174 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
175+groupedDecls (TypeSignature ns) (FunctionBody ns') = ns `intersects` ns'
176+groupedDecls (TypeSignature ns) (DefaultSignature ns') = ns `intersects` ns'
177+groupedDecls (DefaultSignature ns) (TypeSignature ns') = ns `intersects` ns'
178+groupedDecls (DefaultSignature ns) (FunctionBody ns') = ns `intersects` ns'
179+groupedDecls x (FunctionBody ns) | Just ns' <- isPragma x = ns `intersects` ns'
180+groupedDecls (FunctionBody ns) x | Just ns' <- isPragma x = ns `intersects` ns'
181+groupedDecls x (DataDeclaration n) | Just ns <- isPragma x = n `elem` ns
182+groupedDecls (DataDeclaration n) x
183+ | Just ns <- isPragma x =
184+ let f = occNameFS . rdrNameOcc in f n `elem` map f ns
185+groupedDecls x y | Just ns <- isPragma x, Just ns' <- isPragma y = ns `intersects` ns'
186+groupedDecls x (TypeSignature ns) | Just ns' <- isPragma x = ns `intersects` ns'
187+groupedDecls (TypeSignature ns) x | Just ns' <- isPragma x = ns `intersects` ns'
188+groupedDecls (PatternSignature ns) (Pattern n) = n `elem` ns
189+-- This looks only at Haddocks, normal comments are handled elsewhere
190+groupedDecls DocNext _ = True
191+groupedDecls _ DocPrev = True
192+groupedDecls _ _ = False
209193
210194intersects :: Ord a => [a] -> [a] -> Bool
211195intersects a b = go (sort a) (sort b)
@@ -230,11 +214,6 @@ isPragma = \case
230214 WarningPragma n -> Just n
231215 _ -> Nothing
232216
233−-- Declarations that do not refer to names
234−
235−pattern Splice :: HsDecl GhcPs
236−pattern Splice <- SpliceD NoExtField (SpliceDecl NoExtField _ _)
237−
238217-- Declarations referring to a single name
239218
240219pattern
@@ -244,21 +223,15 @@ pattern
244223 AnnTypePragma,
245224 AnnValuePragma,
246225 Pattern,
247− DataDeclaration,
248− ClassDeclaration,
249− KindSignature,
250− FamilyDeclaration ::
226+ DataDeclaration ::
251227 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) _ _ _ _))
228+pattern InlinePragma n <- SigD NoExt (InlineSig NoExt (L _ n) _)
229+pattern SpecializePragma n <- SigD NoExt (SpecSig NoExt (L _ n) _ _)
230+pattern SCCPragma n <- SigD NoExt (SCCFunSig NoExt _ (L _ n) _)
231+pattern AnnTypePragma n <- AnnD NoExt (HsAnnotation NoExt _ (TypeAnnProvenance (L _ n)) _)
232+pattern AnnValuePragma n <- AnnD NoExt (HsAnnotation NoExt _ (ValueAnnProvenance (L _ n)) _)
233+pattern Pattern n <- ValD NoExt (PatSynBind NoExt (PSB _ (L _ n) _ _ _))
234+pattern DataDeclaration n <- TyClD NoExt (DataDecl NoExt (L _ n) _ _ _)
262235
263236-- Declarations which can refer to multiple names
264237
@@ -276,52 +249,51 @@ pattern PatternSignature n <- (patSigRdrNames -> Just n)
276249pattern WarningPragma n <- (warnSigRdrNames -> Just n)
277250
278251pattern DocNext, DocPrev :: HsDecl GhcPs
279−pattern DocNext <- (DocD NoExtField (DocCommentNext _))
280−pattern DocPrev <- (DocD NoExtField (DocCommentPrev _))
252+pattern DocNext <- (DocD NoExt (DocCommentNext _))
253+pattern DocPrev <- (DocD NoExt (DocCommentPrev _))
281254
282255sigRdrNames :: 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
256+sigRdrNames (SigD NoExt (TypeSig NoExt ns _)) = Just $ map unLoc ns
257+sigRdrNames (SigD NoExt (ClassOpSig NoExt _ ns _)) = Just $ map unLoc ns
258+sigRdrNames (SigD NoExt (PatSynSig NoExt ns _)) = Just $ map unLoc ns
286259sigRdrNames _ = Nothing
287260
288261defSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
289−defSigRdrNames (SigD NoExtField (ClassOpSig NoExtField True ns _)) = Just $ map unLoc ns
262+defSigRdrNames (SigD NoExt (ClassOpSig NoExt True ns _)) = Just $ map unLoc ns
290263defSigRdrNames _ = Nothing
291264
292265funRdrNames :: 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
266+funRdrNames (ValD NoExt (FunBind NoExt (L _ n) _ _ _)) = Just [n]
267+funRdrNames (ValD NoExt (PatBind NoExt n _ _)) = Just $ patBindNames n
295268funRdrNames _ = Nothing
296269
297270patSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
298−patSigRdrNames (SigD NoExtField (PatSynSig NoExtField ns _)) = Just $ map unLoc ns
271+patSigRdrNames (SigD NoExt (PatSynSig NoExt ns _)) = Just $ map unLoc ns
299272patSigRdrNames _ = Nothing
300273
301274warnSigRdrNames :: 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
275+warnSigRdrNames (WarningD NoExt (Warnings NoExt _ ws)) = Just $ flip concatMap ws $ \case
276+ L _ (Warning NoExt ns _) -> map unLoc ns
277+ L _ (XWarnDecl NoExt) -> []
306278warnSigRdrNames _ = Nothing
307279
308280patBindNames :: 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]
281+patBindNames (TuplePat NoExt ps _) = concatMap (patBindNames . unLoc) ps
282+patBindNames (VarPat NoExt (L _ n)) = [n]
283+patBindNames (WildPat NoExt) = []
284+patBindNames (LazyPat NoExt p) = patBindNames p
285+patBindNames (BangPat NoExt p) = patBindNames p
286+patBindNames (ParPat NoExt p) = patBindNames p
287+patBindNames (ListPat NoExt ps) = concatMap (patBindNames . unLoc) ps
288+patBindNames (AsPat NoExt (L _ n) p) = n : patBindNames p
289+patBindNames (SumPat NoExt p _ _) = patBindNames p
290+patBindNames (ViewPat NoExt _ p) = patBindNames p
291+patBindNames (SplicePat NoExt _) = []
292+patBindNames (LitPat NoExt _) = []
293+patBindNames (SigPat _ p _) = patBindNames p
294+patBindNames (NPat NoExt _ _ _) = []
295+patBindNames (NPlusKPat NoExt (L _ n) _ _ _ _) = [n]
324296patBindNames (ConPatIn _ d) = concatMap (patBindNames . unLoc) (hsConPatArgs d)
325297patBindNames ConPatOut {} = notImplemented "ConPatOut" -- created by renamer
326−patBindNames (CoPat NoExtField _ p _) = patBindNames p
327−patBindNames (XPat x) = noExtCon x
298+patBindNames (CoPat NoExt _ p _) = patBindNames p
299+patBindNames (XPat p) = patBindNames (unLoc p)
src/Ormolu/Printer/Meat/Declaration.hs-boot+1
@@ -9,4 +9,5 @@ import Ormolu.Printer.Combinators
99import Ormolu.Printer.Meat.Common
1010
1111p_hsDecls :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
12+
1213p_hsDeclsRespectGrouping :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
src/Ormolu/Printer/Meat/Declaration/Annotation.hs+3−2
@@ -10,14 +10,15 @@ import GHC
1010import Ormolu.Printer.Combinators
1111import Ormolu.Printer.Meat.Common
1212import Ormolu.Printer.Meat.Declaration.Value
13+import Ormolu.Utils
1314
1415p_annDecl :: AnnDecl GhcPs -> R ()
1516p_annDecl = \case
16− HsAnnotation NoExtField _ annProv expr -> pragma "ANN" . inci $ do
17+ HsAnnotation NoExt _ annProv expr -> pragma "ANN" . inci $ do
1718 p_annProv annProv
1819 breakpoint
1920 located expr p_hsExpr
20− XAnnDecl x -> noExtCon x
21+ XAnnDecl {} -> notImplemented "XAnnDecl"
2122
2223p_annProv :: AnnProvenance (IdP GhcPs) -> R ()
2324p_annProv = \case
src/Ormolu/Printer/Meat/Declaration/Class.hs+29−21
@@ -18,6 +18,8 @@ import Ormolu.Printer.Combinators
1818import Ormolu.Printer.Meat.Common
1919import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration
2020import Ormolu.Printer.Meat.Type
21+import Ormolu.Utils
22+import RdrName (RdrName (..))
2123
2224p_classDecl ::
2325 LHsContext GhcPs ->
@@ -28,7 +30,7 @@ p_classDecl ::
2830 [LSig GhcPs] ->
2931 LHsBinds GhcPs ->
3032 [LFamilyDecl GhcPs] ->
31− [LTyFamDefltDecl GhcPs] ->
33+ [LTyFamDefltEqn GhcPs] ->
3234 [LDocDecl] ->
3335 R ()
3436p_classDecl ctx name HsQTvs {..} fixity fdeps csigs cdefs cats catdefs cdocs = do
@@ -36,20 +38,6 @@ p_classDecl ctx name HsQTvs {..} fixity fdeps csigs cdefs cats catdefs cdocs = d
3638 signatureSpans = getLoc name : variableSpans
3739 dependencySpans = getLoc <$> fdeps
3840 combinedSpans = getLoc ctx : (signatureSpans ++ dependencySpans)
39− -- GHC's AST does not necessarily store each kind of element in source
40− -- location order. This happens because different declarations are stored
41− -- in different lists. Consequently, to get all the declarations in proper
42− -- order, they need to be manually sorted.
43− sigs = (getLoc &&& fmap (SigD NoExtField)) <$> csigs
44− vals = (getLoc &&& fmap (ValD NoExtField)) <$> toList cdefs
45− tyFams = (getLoc &&& fmap (TyClD NoExtField . FamDecl NoExtField)) <$> cats
46− docs = (getLoc &&& fmap (DocD NoExtField)) <$> cdocs
47− tyFamDefs =
48− ( getLoc &&& fmap (InstD NoExtField . TyFamInstD NoExtField)
49− )
50− <$> catdefs
51− allDecls =
52− snd <$> sortOn fst (sigs <> vals <> tyFams <> tyFamDefs <> docs)
5341 txt "class"
5442 switchLayout combinedSpans $ do
5543 breakpoint
@@ -58,17 +46,30 @@ p_classDecl ctx name HsQTvs {..} fixity fdeps csigs cdefs cats catdefs cdocs = d
5846 switchLayout signatureSpans $
5947 p_infixDefHelper
6048 (isInfix fixity)
61− True
49+ inci
6250 (p_rdrName name)
6351 (located' p_hsTyVarBndr <$> hsq_explicit)
6452 inci (p_classFundeps fdeps)
65− unless (null allDecls) $ do
66− breakpoint
67− txt "where"
53+ -- GHC's AST does not necessarily store each kind of element in source
54+ -- location order. This happens because different declarations are stored
55+ -- in different lists. Consequently, to get all the declarations in proper
56+ -- order, they need to be manually sorted.
57+ let sigs = (getLoc &&& fmap (SigD NoExt)) <$> csigs
58+ vals = (getLoc &&& fmap (ValD NoExt)) <$> toList cdefs
59+ tyFams = (getLoc &&& fmap (TyClD NoExt . FamDecl NoExt)) <$> cats
60+ docs = (getLoc &&& fmap (DocD NoExt)) <$> cdocs
61+ tyFamDefs =
62+ ( getLoc &&& fmap (InstD NoExt . TyFamInstD NoExt . defltEqnToInstDecl)
63+ )
64+ <$> catdefs
65+ allDecls =
66+ snd <$> sortOn fst (sigs <> vals <> tyFams <> tyFamDefs <> docs)
6867 unless (null allDecls) $ do
68+ space
69+ txt "where"
6970 breakpoint -- Ensure whitespace is added after where clause.
7071 inci (p_hsDeclsRespectGrouping Associated allDecls)
71−p_classDecl _ _ (XLHsQTyVars c) _ _ _ _ _ _ _ = noExtCon c
72+p_classDecl _ _ XLHsQTyVars {} _ _ _ _ _ _ _ = notImplemented "XLHsQTyVars"
7273
7374p_classContext :: LHsContext GhcPs -> R ()
7475p_classContext ctx = unless (null (unLoc ctx)) $ do
@@ -82,7 +83,7 @@ p_classFundeps fdeps = unless (null fdeps) $ do
8283 breakpoint
8384 txt "|"
8485 space
85− inci $ sep commaDel (sitcc . located' p_funDep) fdeps
86+ sitcc $ sep (comma >> breakpoint) (sitcc . located' p_funDep) fdeps
8687
8788p_funDep :: FunDep (Located RdrName) -> R ()
8889p_funDep (before, after) = do
@@ -95,6 +96,13 @@ p_funDep (before, after) = do
9596----------------------------------------------------------------------------
9697-- Helpers
9798
99+defltEqnToInstDecl :: TyFamDefltEqn GhcPs -> TyFamInstDecl GhcPs
100+defltEqnToInstDecl FamEqn {..} = TyFamInstDecl {..}
101+ where
102+ eqn = FamEqn {feqn_pats = map HsValArg (tyVarsToTypes feqn_pats), ..}
103+ tfid_eqn = HsIB {hsib_ext = NoExt, hsib_body = eqn}
104+defltEqnToInstDecl XFamEqn {} = notImplemented "XFamEqn"
105+
98106isInfix :: LexicalFixity -> Bool
99107isInfix = \case
100108 Infix -> True
src/Ormolu/Printer/Meat/Declaration/Data.hs+43−68
@@ -15,6 +15,8 @@ import Ormolu.Printer.Combinators
1515import Ormolu.Printer.Meat.Common
1616import Ormolu.Printer.Meat.Type
1717import Ormolu.Utils
18+import RdrName (RdrName (..))
19+import SrcLoc (Located)
1820
1921p_dataDecl ::
2022 -- | Whether to format as data family
@@ -35,13 +37,12 @@ p_dataDecl style name tpats fixity HsDataDefn {..} = do
3537 txt $ case style of
3638 Associated -> mempty
3739 Free -> " instance"
38− let constructorSpans = getLoc name : fmap getLoc tpats
39− switchLayout constructorSpans $ do
40+ switchLayout (getLoc name : fmap getLoc tpats) $ do
4041 breakpoint
4142 inci $
4243 p_infixDefHelper
4344 (isInfix fixity)
44− True
45+ inci
4546 (p_rdrName name)
4647 (located' p_hsType <$> tpats)
4748 case dd_kindSig of
@@ -54,42 +55,29 @@ p_dataDecl style name tpats fixity HsDataDefn {..} = do
5455 let gadt = isJust dd_kindSig || any (isGadt . unLoc) dd_cons
5556 unless (null dd_cons) $
5657 if gadt
57− then inci $ do
58− switchLayout constructorSpans $ do
59− breakpoint
60− txt "where"
61− breakpoint
62− sepSemi (located' (p_conDecl False)) dd_cons
63− else switchLayout (getLoc name : (getLoc <$> dd_cons)) . inci $ do
64− let singleConstRec = isSingleConstRec dd_cons
65− if singleConstRec
66− then space
67− else
68− if hasHaddocks dd_cons
69− then newline
70− else breakpoint
71− equals
58+ then do
7259 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
60+ txt "where"
61+ breakpoint
62+ inci $ sepSemi (located' p_conDecl) dd_cons
63+ else switchLayout (getLoc name : (getLoc <$> dd_cons))
64+ $ inci
65+ $ do
66+ breakpoint
67+ txt "="
68+ space
69+ let s =
70+ vlayout
71+ (space >> txt "|" >> space)
72+ (newline >> txt "|" >> space)
73+ sep s (sitcc . located' p_conDecl) dd_cons
8374 unless (null $ unLoc dd_derivs) breakpoint
8475 inci . located dd_derivs $ \xs ->
8576 sep newline (located' p_hsDerivingClause) xs
86−p_dataDecl _ _ _ _ (XHsDataDefn x) = noExtCon x
77+p_dataDecl _ _ _ _ (XHsDataDefn NoExt) = notImplemented "XHsDataDefn"
8778
88−p_conDecl ::
89− Bool ->
90− ConDecl GhcPs ->
91− R ()
92−p_conDecl singleConstRec = \case
79+p_conDecl :: ConDecl GhcPs -> R ()
80+p_conDecl = \case
9381 ConDeclGADT {..} -> do
9482 mapM_ (p_hsDocString Pipe True) con_doc
9583 let conDeclSpn =
@@ -104,10 +92,11 @@ p_conDecl singleConstRec = \case
10492 (c : cs) -> do
10593 p_rdrName c
10694 unless (null cs) . inci $ do
107− commaDel
108− sep commaDel p_rdrName cs
95+ comma
96+ breakpoint
97+ sitcc $ sep (comma >> breakpoint) p_rdrName cs
98+ space
10999 inci $ do
110− space
111100 txt "::"
112101 let interArgBreak =
113102 if hasDocStrings (unLoc con_res_ty)
@@ -115,7 +104,7 @@ p_conDecl singleConstRec = \case
115104 else breakpoint
116105 interArgBreak
117106 when (unLoc con_forall) $ do
118− p_forallBndrs ForallInvis p_hsTyVarBndr (hsq_explicit con_qvars)
107+ p_forallBndrs p_hsTyVarBndr (hsq_explicit con_qvars)
119108 interArgBreak
120109 forM_ con_mb_cxt p_lhsContext
121110 case con_args of
@@ -135,27 +124,26 @@ p_conDecl singleConstRec = \case
135124 p_hsType (unLoc con_res_ty)
136125 ConDeclH98 {..} -> do
137126 mapM_ (p_hsDocString Pipe True) con_doc
138− let conDeclWithContextSpn =
139− [getLoc con_forall]
127+ let conDeclSpn =
128+ [getLoc con_name]
129+ <> [getLoc con_forall]
140130 <> fmap getLoc con_ex_tvs
141131 <> maybeToList (fmap getLoc con_mb_cxt)
142− <> conDeclSpn
143− conDeclSpn =
144− getLoc con_name : conArgsSpans con_args
145− switchLayout conDeclWithContextSpn $ do
132+ <> conArgsSpans con_args
133+ switchLayout conDeclSpn $ do
146134 when (unLoc con_forall) $ do
147− p_forallBndrs ForallInvis p_hsTyVarBndr con_ex_tvs
135+ p_forallBndrs p_hsTyVarBndr con_ex_tvs
148136 breakpoint
149137 forM_ con_mb_cxt p_lhsContext
150− switchLayout conDeclSpn $ case con_args of
138+ case con_args of
151139 PrefixCon xs -> do
152140 p_rdrName con_name
153141 unless (null xs) breakpoint
154− inci . sitcc $ sep breakpoint (sitcc . located' p_hsTypePostDoc) xs
142+ inci . sitcc $ sep breakpoint (sitcc . located' p_hsType) xs
155143 RecCon l -> do
156144 p_rdrName con_name
157145 breakpoint
158− inciIf (not singleConstRec) (located l p_conDeclFields)
146+ inci $ located l p_conDeclFields
159147 InfixCon x y -> do
160148 located x p_hsType
161149 breakpoint
@@ -163,7 +151,7 @@ p_conDecl singleConstRec = \case
163151 p_rdrName con_name
164152 space
165153 located y p_hsType
166− XConDecl x -> noExtCon x
154+ XConDecl NoExt -> notImplemented "XConDecl"
167155
168156conArgsSpans :: HsConDeclDetails GhcPs -> [SrcSpan]
169157conArgsSpans = \case
@@ -177,7 +165,7 @@ conArgsSpans = \case
177165conTyVarsSpans :: LHsQTyVars GhcPs -> [SrcSpan]
178166conTyVarsSpans = \case
179167 HsQTvs {..} -> getLoc <$> hsq_explicit
180− XLHsQTyVars x -> noExtCon x
168+ XLHsQTyVars NoExt -> []
181169
182170p_lhsContext ::
183171 LHsContext GhcPs ->
@@ -204,9 +192,9 @@ p_hsDerivingClause HsDerivingClause {..} = do
204192 let derivingWhat = located deriv_clause_tys $ \case
205193 [] -> txt "()"
206194 xs ->
207− parens N $
195+ parens N . sitcc $
208196 sep
209− commaDel
197+ (comma >> breakpoint)
210198 (sitcc . located' p_hsType . hsib_body)
211199 xs
212200 space
@@ -235,9 +223,9 @@ p_hsDerivingClause HsDerivingClause {..} = do
235223 txt "via"
236224 space
237225 located hsib_body p_hsType
238− ViaStrategy (XHsImplicitBndrs x) ->
239− noExtCon x
240−p_hsDerivingClause (XHsDerivingClause x) = noExtCon x
226+ ViaStrategy (XHsImplicitBndrs NoExt) ->
227+ notImplemented "XHsImplicitBndrs"
228+p_hsDerivingClause (XHsDerivingClause NoExt) = notImplemented "XHsDerivingClause"
241229
242230----------------------------------------------------------------------------
243231-- Helpers
@@ -246,16 +234,3 @@ isInfix :: LexicalFixity -> Bool
246234isInfix = \case
247235 Infix -> True
248236 Prefix -> False
249−
250−isSingleConstRec :: [LConDecl GhcPs] -> Bool
251−isSingleConstRec [(L _ ConDeclH98 {..})] =
252− case con_args of
253− RecCon _ -> True
254− _ -> False
255−isSingleConstRec _ = False
256−
257−hasHaddocks :: [LConDecl GhcPs] -> Bool
258−hasHaddocks = any (f . unLoc)
259− where
260− f ConDeclH98 {..} = isJust con_doc
261− f _ = False
src/Ormolu/Printer/Meat/Declaration/Default.hs+5−4
@@ -9,12 +9,13 @@ where
99import GHC
1010import Ormolu.Printer.Combinators
1111import Ormolu.Printer.Meat.Type
12+import Ormolu.Utils
1213
1314p_defaultDecl :: DefaultDecl GhcPs -> R ()
1415p_defaultDecl = \case
15− DefaultDecl NoExtField ts -> do
16+ DefaultDecl NoExt ts -> do
1617 txt "default"
1718 breakpoint
18− inci . parens N $
19− sep commaDel (sitcc . located' p_hsType) ts
20− XDefaultDecl x -> noExtCon x
19+ inci . parens N . sitcc $
20+ sep (comma >> breakpoint) (sitcc . located' p_hsType) ts
21+ XDefaultDecl {} -> notImplemented "XDefaultDecl"
src/Ormolu/Printer/Meat/Declaration/Foreign.hs+3−2
@@ -15,6 +15,7 @@ import GHC
1515import Ormolu.Printer.Combinators
1616import Ormolu.Printer.Meat.Common
1717import Ormolu.Printer.Meat.Declaration.Signature
18+import Ormolu.Utils
1819
1920p_foreignDecl :: ForeignDecl GhcPs -> R ()
2021p_foreignDecl = \case
@@ -24,7 +25,7 @@ p_foreignDecl = \case
2425 fd@ForeignExport {fd_fe} -> do
2526 p_foreignExport fd_fe
2627 p_foreignTypeSig fd
27− XForeignDecl x -> noExtCon x
28+ XForeignDecl {} -> notImplemented "XForeignDecl"
2829
2930-- | Printer for the last part of an import\/export, which is function name
3031-- and type signature.
@@ -38,7 +39,7 @@ p_foreignTypeSig fd = do
3839 ]
3940 $ do
4041 p_rdrName (fd_name fd)
41− p_typeAscription (HsWC NoExtField (fd_sig_ty fd))
42+ p_typeAscription (HsWC NoExt (fd_sig_ty fd))
4243
4344-- | Printer for 'ForeignImport'.
4445--
src/Ormolu/Printer/Meat/Declaration/Instance.hs+17−13
@@ -32,7 +32,9 @@ p_standaloneDerivDecl DerivDecl {..} = do
3232 txt "instance"
3333 breakpoint
3434 match_overlap_mode deriv_overlap_mode breakpoint
35− inciIf toIndent typesAfterInstance
35+ if toIndent
36+ then inci typesAfterInstance
37+ else typesAfterInstance
3638 txt "deriving"
3739 space
3840 case deriv_strategy of
@@ -54,8 +56,8 @@ p_standaloneDerivDecl DerivDecl {..} = do
5456 inci (located hsib_body p_hsType)
5557 breakpoint
5658 instTypes True
57− ViaStrategy (XHsImplicitBndrs x) ->
58− noExtCon x
59+ ViaStrategy (XHsImplicitBndrs NoExt) ->
60+ notImplemented "XHsImplicitBndrs"
5961p_standaloneDerivDecl (XDerivDecl _) = notImplemented "XDerivDecl"
6062
6163p_clsInstDecl :: ClsInstDecl GhcPs -> R ()
@@ -68,14 +70,14 @@ p_clsInstDecl = \case
6870 -- location order. This happens because different declarations are stored in
6971 -- different lists. Consequently, to get all the declarations in proper
7072 -- order, they need to be manually sorted.
71− let sigs = (getLoc &&& fmap (SigD NoExtField)) <$> cid_sigs
72− vals = (getLoc &&& fmap (ValD NoExtField)) <$> toList cid_binds
73+ let sigs = (getLoc &&& fmap (SigD NoExt)) <$> cid_sigs
74+ vals = (getLoc &&& fmap (ValD NoExt)) <$> toList cid_binds
7375 tyFamInsts =
74− ( getLoc &&& fmap (InstD NoExtField . TyFamInstD NoExtField)
76+ ( getLoc &&& fmap (InstD NoExt . TyFamInstD NoExt)
7577 )
7678 <$> cid_tyfam_insts
7779 dataFamInsts =
78− ( getLoc &&& fmap (InstD NoExtField . DataFamInstD NoExtField)
80+ ( getLoc &&& fmap (InstD NoExt . DataFamInstD NoExt)
7981 )
8082 <$> cid_datafam_insts
8183 allDecls =
@@ -88,12 +90,14 @@ p_clsInstDecl = \case
8890 unless (null allDecls) $ do
8991 breakpoint
9092 txt "where"
91− unless (null allDecls) . inci $ do
92− -- Ensure whitespace is added after where clause.
93− breakpoint
94− dontUseBraces $ p_hsDeclsRespectGrouping Associated allDecls
95− XHsImplicitBndrs x -> noExtCon x
96− XClsInstDecl x -> noExtCon x
93+ unless (null allDecls)
94+ $ inci
95+ $ do
96+ -- Ensure whitespace is added after where clause.
97+ breakpoint
98+ dontUseBraces $ p_hsDeclsRespectGrouping Associated allDecls
99+ XHsImplicitBndrs NoExt -> notImplemented "XHsImplicitBndrs"
100+ XClsInstDecl NoExt -> notImplemented "XClsInstDecl"
97101
98102p_tyFamInstDecl :: FamilyStyle -> TyFamInstDecl GhcPs -> R ()
99103p_tyFamInstDecl style = \case
src/Ormolu/Printer/Meat/Declaration/RoleAnnotation.hs+5−2
@@ -12,11 +12,14 @@ import CoAxiom
1212import GHC
1313import Ormolu.Printer.Combinators
1414import Ormolu.Printer.Meat.Common
15+import Ormolu.Utils
16+import RdrName (RdrName (..))
17+import SrcLoc (Located)
1518
1619p_roleAnnot :: RoleAnnotDecl GhcPs -> R ()
1720p_roleAnnot = \case
18− RoleAnnotDecl NoExtField l_name anns -> p_roleAnnot' l_name anns
19− XRoleAnnotDecl x -> noExtCon x
21+ RoleAnnotDecl NoExt l_name anns -> p_roleAnnot' l_name anns
22+ XRoleAnnotDecl _ -> notImplemented "XRoleAnnotDecl"
2023
2124p_roleAnnot' :: Located RdrName -> [Located (Maybe Role)] -> R ()
2225p_roleAnnot' l_name anns = do
src/Ormolu/Printer/Meat/Declaration/Rule.hs+13−12
@@ -14,17 +14,18 @@ import Ormolu.Printer.Meat.Common
1414import Ormolu.Printer.Meat.Declaration.Signature
1515import Ormolu.Printer.Meat.Declaration.Value
1616import Ormolu.Printer.Meat.Type
17+import Ormolu.Utils
1718
1819p_ruleDecls :: RuleDecls GhcPs -> R ()
1920p_ruleDecls = \case
20− HsRules NoExtField _ xs ->
21− pragma "RULES" $
21+ HsRules NoExt _ xs ->
22+ pragma "RULES" . sitcc $
2223 sep breakpoint (sitcc . located' p_ruleDecl) xs
23− XRuleDecls x -> noExtCon x
24+ XRuleDecls NoExt -> notImplemented "XRuleDecls"
2425
2526p_ruleDecl :: RuleDecl GhcPs -> R ()
2627p_ruleDecl = \case
27− HsRule NoExtField ruleName activation tyvars ruleBndrs lhs rhs -> do
28+ HsRule NoExt ruleName activation tyvars ruleBndrs lhs rhs -> do
2829 located ruleName p_ruleName
2930 space
3031 p_activation activation
@@ -32,30 +33,30 @@ p_ruleDecl = \case
3233 case tyvars of
3334 Nothing -> return ()
3435 Just xs -> do
35− p_forallBndrs ForallInvis p_hsTyVarBndr xs
36+ p_forallBndrs p_hsTyVarBndr xs
3637 space
3738 -- It appears that there is no way to tell if there was an empty forall
3839 -- in the input or no forall at all. We do not want to add redundant
3940 -- foralls, so let's just skip the empty ones.
4041 unless (null ruleBndrs) $
41− p_forallBndrs ForallInvis p_ruleBndr ruleBndrs
42+ p_forallBndrs p_ruleBndr ruleBndrs
4243 breakpoint
4344 inci $ do
4445 located lhs p_hsExpr
4546 space
46− equals
47+ txt "="
4748 inci $ do
4849 breakpoint
4950 located rhs p_hsExpr
50− XRuleDecl x -> noExtCon x
51+ XRuleDecl NoExt -> notImplemented "XRuleDecl"
5152
5253p_ruleName :: (SourceText, RuleName) -> R ()
53−p_ruleName (_, name) = atom $ (HsString NoSourceText name :: HsLit GhcPs)
54+p_ruleName (_, name) = atom $ HsString NoSourceText name
5455
5556p_ruleBndr :: RuleBndr GhcPs -> R ()
5657p_ruleBndr = \case
57− RuleBndr NoExtField x -> p_rdrName x
58− RuleBndrSig NoExtField x hswc -> parens N $ do
58+ RuleBndr NoExt x -> p_rdrName x
59+ RuleBndrSig NoExt x hswc -> parens N $ do
5960 p_rdrName x
6061 p_typeAscription hswc
61− XRuleBndr x -> noExtCon x
62+ XRuleBndr NoExt -> notImplemented "XRuleBndr"
src/Ormolu/Printer/Meat/Declaration/Signature.hs+33−49
@@ -7,13 +7,13 @@ module Ormolu.Printer.Meat.Declaration.Signature
77 ( p_sigDecl,
88 p_typeAscription,
99 p_activation,
10− p_standaloneKindSig,
1110 )
1211where
1312
1413import BasicTypes
1514import BooleanFormula
1615import Control.Monad
16+import Data.Bool (bool)
1717import GHC
1818import Ormolu.Printer.Combinators
1919import Ormolu.Printer.Meat.Common
@@ -22,16 +22,16 @@ import Ormolu.Utils
2222
2323p_sigDecl :: Sig GhcPs -> R ()
2424p_sigDecl = \case
25− TypeSig NoExtField names hswc -> p_typeSig True names hswc
26− PatSynSig NoExtField names hsib -> p_patSynSig names hsib
27− ClassOpSig NoExtField def names hsib -> p_classOpSig def names hsib
28− FixSig NoExtField sig -> p_fixSig sig
29− InlineSig NoExtField name inlinePragma -> p_inlineSig name inlinePragma
30− SpecSig NoExtField name ts inlinePragma -> p_specSig name ts inlinePragma
31− SpecInstSig NoExtField _ hsib -> p_specInstSig hsib
32− MinimalSig NoExtField _ booleanFormula -> p_minimalSig booleanFormula
33− CompleteMatchSig NoExtField _sourceText cs ty -> p_completeSig cs ty
34− SCCFunSig NoExtField _ name literal -> p_sccSig name literal
25+ TypeSig NoExt names hswc -> p_typeSig True names hswc
26+ PatSynSig NoExt names hsib -> p_patSynSig names hsib
27+ ClassOpSig NoExt def names hsib -> p_classOpSig def names hsib
28+ FixSig NoExt sig -> p_fixSig sig
29+ InlineSig NoExt name inlinePragma -> p_inlineSig name inlinePragma
30+ SpecSig NoExt name ts inlinePragma -> p_specSig name ts inlinePragma
31+ SpecInstSig NoExt _ hsib -> p_specInstSig hsib
32+ MinimalSig NoExt _ booleanFormula -> p_minimalSig booleanFormula
33+ CompleteMatchSig NoExt _sourceText cs ty -> p_completeSig cs ty
34+ SCCFunSig NoExt _ name literal -> p_sccSig name literal
3535 _ -> notImplemented "certain types of signature declarations"
3636
3737p_typeSig ::
@@ -47,23 +47,25 @@ p_typeSig indentTail (n : ns) hswc = do
4747 p_rdrName n
4848 if null ns
4949 then p_typeAscription hswc
50− else inciIf indentTail $ do
51− commaDel
52− sep commaDel p_rdrName ns
50+ else bool id inci indentTail $ do
51+ comma
52+ breakpoint
53+ sep (comma >> breakpoint) p_rdrName ns
5354 p_typeAscription hswc
5455
5556p_typeAscription ::
5657 LHsSigWcType GhcPs ->
5758 R ()
58−p_typeAscription HsWC {..} = inci $ do
59+p_typeAscription HsWC {..} = do
5960 space
60− txt "::"
61− let t = hsib_body hswc_body
62− if hasDocStrings (unLoc t)
63− then newline
64− else breakpoint
65− located t p_hsType
66−p_typeAscription (XHsWildCardBndrs x) = noExtCon x
61+ inci $ do
62+ txt "::"
63+ let t = hsib_body hswc_body
64+ if hasDocStrings (unLoc t)
65+ then newline
66+ else breakpoint
67+ located t p_hsType
68+p_typeAscription (XHsWildCardBndrs NoExt) = notImplemented "XHsWildCardBndrs"
6769
6870p_patSynSig ::
6971 [Located RdrName] ->
@@ -71,11 +73,7 @@ p_patSynSig ::
7173 R ()
7274p_patSynSig names hsib = do
7375 txt "pattern"
74− let body =
75− p_typeSig
76− False
77− names
78− HsWC {hswc_ext = NoExtField, hswc_body = hsib}
76+ let body = p_typeSig False names HsWC {hswc_ext = NoExt, hswc_body = hsib}
7977 if length names > 1
8078 then breakpoint >> inci body
8179 else space >> body
@@ -90,13 +88,13 @@ p_classOpSig ::
9088 R ()
9189p_classOpSig def names hsib = do
9290 when def (txt "default" >> space)
93− p_typeSig True names HsWC {hswc_ext = NoExtField, hswc_body = hsib}
91+ p_typeSig True names HsWC {hswc_ext = NoExt, hswc_body = hsib}
9492
9593p_fixSig ::
9694 FixitySig GhcPs ->
9795 R ()
9896p_fixSig = \case
99− FixitySig NoExtField names (Fixity _ n dir) -> do
97+ FixitySig NoExt names (Fixity _ n dir) -> do
10098 txt $ case dir of
10199 InfixL -> "infixl"
102100 InfixR -> "infixr"
@@ -104,8 +102,8 @@ p_fixSig = \case
104102 space
105103 atom n
106104 space
107− sitcc $ sep commaDel p_rdrName names
108− XFixitySig x -> noExtCon x
105+ sitcc $ sep (comma >> breakpoint) p_rdrName names
106+ XFixitySig NoExt -> notImplemented "XFixitySig"
109107
110108p_inlineSig ::
111109 -- | Name
@@ -143,7 +141,7 @@ p_specSig name ts InlinePragma {..} = pragmaBraces $ do
143141 space
144142 txt "::"
145143 breakpoint
146− inci $ sep commaDel (located' p_hsType . hsib_body) ts
144+ inci $ sep (comma >> breakpoint) (located' p_hsType . hsib_body) ts
147145
148146p_inlineSpec :: InlineSpec -> R ()
149147p_inlineSpec = \case
@@ -187,13 +185,13 @@ p_booleanFormula = \case
187185 And xs ->
188186 sitcc $
189187 sep
190− commaDel
188+ (comma >> breakpoint)
191189 (located' p_booleanFormula)
192190 xs
193191 Or xs ->
194192 sitcc $
195193 sep
196− (breakpoint >> txt "|" >> space)
194+ (breakpoint >> txt "| ")
197195 (located' p_booleanFormula)
198196 xs
199197 Parens l -> located l (parens N . p_booleanFormula)
@@ -207,7 +205,7 @@ p_completeSig ::
207205p_completeSig cs' mty =
208206 located cs' $ \cs ->
209207 pragma "COMPLETE" . inci $ do
210− sep commaDel p_rdrName cs
208+ sitcc $ sep (comma >> breakpoint) p_rdrName cs
211209 forM_ mty $ \ty -> do
212210 space
213211 txt "::"
@@ -220,17 +218,3 @@ p_sccSig loc literal = pragma "SCC" . inci $ do
220218 forM_ literal $ \x -> do
221219 breakpoint
222220 atom x
223−
224−p_standaloneKindSig :: StandaloneKindSig GhcPs -> R ()
225−p_standaloneKindSig (StandaloneKindSig NoExtField name bndrs) = do
226− txt "type"
227− inci $ do
228− space
229− p_rdrName name
230− space
231− txt "::"
232− breakpoint
233− case bndrs of
234− HsIB NoExtField sig -> located sig p_hsType
235− XHsImplicitBndrs x -> noExtCon x
236−p_standaloneKindSig (XStandaloneKindSig c) = noExtCon c
src/Ormolu/Printer/Meat/Declaration/Splice.hs+3−2
@@ -8,8 +8,9 @@ where
88import GHC
99import Ormolu.Printer.Combinators
1010import Ormolu.Printer.Meat.Declaration.Value (p_hsSplice)
11+import Ormolu.Utils
1112
1213p_spliceDecl :: SpliceDecl GhcPs -> R ()
1314p_spliceDecl = \case
14− SpliceDecl NoExtField splice _explicit -> located splice p_hsSplice
15− XSpliceDecl x -> noExtCon x
15+ SpliceDecl NoExt splice _explicit -> located splice p_hsSplice
16+ XSpliceDecl {} -> notImplemented "XSpliceDecl"
src/Ormolu/Printer/Meat/Declaration/Type.hs+7−6
@@ -11,6 +11,9 @@ import GHC
1111import Ormolu.Printer.Combinators
1212import Ormolu.Printer.Meat.Common
1313import Ormolu.Printer.Meat.Type
14+import Ormolu.Utils (notImplemented)
15+import RdrName (RdrName (..))
16+import SrcLoc (Located)
1417
1518p_synDecl ::
1619 -- | Type constructor
@@ -28,13 +31,11 @@ p_synDecl name fixity HsQTvs {..} t = do
2831 switchLayout (getLoc name : map getLoc hsq_explicit) $
2932 p_infixDefHelper
3033 (case fixity of Infix -> True; _ -> False)
31− True
34+ inci
3235 (p_rdrName name)
3336 (map (located' p_hsTyVarBndr) hsq_explicit)
3437 space
35− equals
36− if hasDocStrings (unLoc t)
37− then newline
38− else breakpoint
38+ txt "="
39+ breakpoint
3940 inci (located t p_hsType)
40−p_synDecl _ _ (XLHsQTyVars x) _ = noExtCon x
41+p_synDecl _ _ XLHsQTyVars {} _ = notImplemented "XLHsQTyVars"
src/Ormolu/Printer/Meat/Declaration/TypeFamily.hs+23−22
@@ -9,13 +9,15 @@ module Ormolu.Printer.Meat.Declaration.TypeFamily
99 )
1010where
1111
12+import BasicTypes (LexicalFixity (..))
1213import Control.Monad
13−import Data.Maybe (isNothing)
14+import Data.Maybe (isJust, isNothing)
1415import GHC
1516import Ormolu.Printer.Combinators
1617import Ormolu.Printer.Meat.Common
1718import Ormolu.Printer.Meat.Type
1819import Ormolu.Utils
20+import SrcLoc (GenLocated (..), Located)
1921
2022p_famDecl :: FamilyStyle -> FamilyDecl GhcPs -> R ()
2123p_famDecl style FamilyDecl {fdTyVars = HsQTvs {..}, ..} = do
@@ -31,21 +33,20 @@ p_famDecl style FamilyDecl {fdTyVars = HsQTvs {..}, ..} = do
3133 switchLayout (getLoc fdLName : (getLoc <$> hsq_explicit)) $
3234 p_infixDefHelper
3335 (isInfix fdFixity)
34− True
36+ inci
3537 (p_rdrName fdLName)
3638 (located' p_hsTyVarBndr <$> hsq_explicit)
37− let resultSig = p_familyResultSigL fdResultSig
38− unless (isNothing resultSig && isNothing fdInjectivityAnn) space
39+ let rsig = p_familyResultSigL fdResultSig
40+ unless (isNothing rsig && isNothing fdInjectivityAnn) space
3941 inci $ do
40− sequence_ resultSig
41− space
42+ sequence_ rsig
43+ when (isJust rsig && isJust fdInjectivityAnn) breakpoint
4244 forM_ fdInjectivityAnn (located' p_injectivityAnn)
4345 case mmeqs of
4446 Nothing -> return ()
4547 Just meqs -> do
46− inci $ do
47− breakpoint
48− txt "where"
48+ space
49+ txt "where"
4950 case meqs of
5051 Nothing -> do
5152 space
@@ -55,7 +56,7 @@ p_famDecl style FamilyDecl {fdTyVars = HsQTvs {..}, ..} = do
5556 sep newline (located' (inci . p_tyFamInstEqn)) eqs
5657p_famDecl _ FamilyDecl {fdTyVars = XLHsQTyVars {}} =
5758 notImplemented "XLHsQTyVars"
58−p_famDecl _ (XFamilyDecl x) = noExtCon x
59+p_famDecl _ (XFamilyDecl NoExt) = notImplemented "XFamilyDecl"
5960
6061p_familyResultSigL ::
6162 Located (FamilyResultSig GhcPs) ->
@@ -63,17 +64,17 @@ p_familyResultSigL ::
6364p_familyResultSigL l =
6465 case l of
6566 L _ a -> case a of
66− NoSig NoExtField -> Nothing
67− KindSig NoExtField k -> Just $ do
67+ NoSig NoExt -> Nothing
68+ KindSig NoExt k -> Just $ do
6869 txt "::"
6970 breakpoint
7071 located k p_hsType
71− TyVarSig NoExtField bndr -> Just $ do
72− equals
72+ TyVarSig NoExt bndr -> Just $ do
73+ txt "="
7374 breakpoint
7475 located bndr p_hsTyVarBndr
75− XFamilyResultSig x ->
76− noExtCon x
76+ XFamilyResultSig NoExt ->
77+ notImplemented "XFamilyResultSig"
7778
7879p_injectivityAnn :: InjectivityAnn GhcPs -> R ()
7980p_injectivityAnn (InjectivityAnn a bs) = do
@@ -90,22 +91,22 @@ p_tyFamInstEqn HsIB {hsib_body = FamEqn {..}} = do
9091 case feqn_bndrs of
9192 Nothing -> return ()
9293 Just bndrs -> do
93− p_forallBndrs ForallInvis p_hsTyVarBndr bndrs
94+ p_forallBndrs p_hsTyVarBndr bndrs
9495 breakpoint
95− inciIf (not $ null feqn_bndrs) $ do
96+ (if null feqn_bndrs then id else inci) $ do
9697 let famLhsSpn = getLoc feqn_tycon : fmap (getLoc . typeArgToType) feqn_pats
9798 switchLayout famLhsSpn $
9899 p_infixDefHelper
99100 (isInfix feqn_fixity)
100− True
101+ inci
101102 (p_rdrName feqn_tycon)
102103 (located' p_hsType . typeArgToType <$> feqn_pats)
103104 space
104− equals
105+ txt "="
105106 breakpoint
106107 inci (located feqn_rhs p_hsType)
107−p_tyFamInstEqn HsIB {hsib_body = XFamEqn x} = noExtCon x
108−p_tyFamInstEqn (XHsImplicitBndrs x) = noExtCon x
108+p_tyFamInstEqn HsIB {hsib_body = XFamEqn {}} = notImplemented "HsIB XFamEqn"
109+p_tyFamInstEqn (XHsImplicitBndrs NoExt) = notImplemented "XHsImplicitBndrs"
109110
110111----------------------------------------------------------------------------
111112-- Helpers
src/Ormolu/Printer/Meat/Declaration/Value.hs+361−375
@@ -1,8 +1,6 @@
11{-# LANGUAGE LambdaCase #-}
2−{-# LANGUAGE MultiWayIf #-}
32{-# LANGUAGE OverloadedStrings #-}
43{-# LANGUAGE RecordWildCards #-}
5−{-# LANGUAGE TypeApplications #-}
64
75module Ormolu.Printer.Meat.Declaration.Value
86 ( p_valDecl,
@@ -22,12 +20,12 @@ import Data.Char (isPunctuation, isSymbol)
2220import Data.Data hiding (Infix, Prefix)
2321import Data.Functor ((<&>))
2422import Data.List (intersperse, sortOn)
25−import Data.List.NonEmpty (NonEmpty (..), (<|))
23+import Data.List.NonEmpty ((<|), NonEmpty ((:|)))
2624import qualified Data.List.NonEmpty as NE
2725import Data.Text (Text)
2826import qualified Data.Text as Text
2927import GHC
30−import OccName (occNameString)
28+import OccName (mkVarOcc)
3129import Ormolu.Printer.Combinators
3230import Ormolu.Printer.Internal
3331import Ormolu.Printer.Meat.Common
@@ -36,6 +34,8 @@ import Ormolu.Printer.Meat.Declaration.Signature
3634import Ormolu.Printer.Meat.Type
3735import Ormolu.Printer.Operators
3836import Ormolu.Utils
37+import RdrName (RdrName (..), rdrNameOcc)
38+import SrcLoc (combineSrcSpans, isOneLineSpan)
3939
4040-- | Style of a group of equations.
4141data MatchGroupStyle
@@ -61,16 +61,16 @@ data Placement
6161 -- should use it and avoid bumping one level
6262 -- of indentation
6363 Hanging
64− deriving (Eq, Show)
64+ deriving (Eq)
6565
6666p_valDecl :: HsBindLR GhcPs GhcPs -> R ()
6767p_valDecl = \case
68− FunBind NoExtField funId funMatches _ _ -> p_funBind funId funMatches
69− PatBind NoExtField pat grhss _ -> p_match PatternBind False NoSrcStrict [pat] grhss
68+ FunBind NoExt funId funMatches _ _ -> p_funBind funId funMatches
69+ PatBind NoExt pat grhss _ -> p_match PatternBind False NoSrcStrict [pat] grhss
7070 VarBind {} -> notImplemented "VarBinds" -- introduced by the type checker
7171 AbsBinds {} -> notImplemented "AbsBinds" -- introduced by the type checker
72− PatSynBind NoExtField psb -> p_patSynBind psb
73− XHsBindsLR x -> noExtCon x
72+ PatSynBind NoExt psb -> p_patSynBind psb
73+ XHsBindsLR NoExt -> notImplemented "XHsBindsLR"
7474
7575p_funBind ::
7676 Located RdrName ->
@@ -114,8 +114,8 @@ p_matchGroup' placer render style MG {..} = do
114114 (matchStrictness m)
115115 m_pats
116116 m_grhss
117− p_Match (XMatch x) = noExtCon x
118−p_matchGroup' _ _ _ (XMatchGroup x) = noExtCon x
117+ p_Match _ = notImplemented "XMatch"
118+p_matchGroup' _ _ _ (XMatchGroup NoExt) = notImplemented "XMatchGroup"
119119
120120-- | Function id obtained through pattern matching on 'FunBind' should not
121121-- be used to print the actual equations because the different ‘RdrNames’
@@ -180,26 +180,27 @@ p_match' placer render style isInfix strictness m_pats GRHSs {..} = do
180180 NoSrcStrict -> return ()
181181 SrcStrict -> txt "!"
182182 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 ()
183+ inci' <- case NE.nonEmpty m_pats of
184+ Nothing -> id <$ case style of
185+ Function name -> p_rdrName name
186+ _ -> return ()
188187 Just ne_pats -> do
189− let combinedSpans = case style of
190− Function name -> combineSrcSpans (getLoc name) patSpans
191− _ -> patSpans
192− patSpans = combineSrcSpans' (getLoc <$> ne_pats)
193− indentBody = not (isOneLineSpan combinedSpans)
188+ let combinedSpans =
189+ combineSrcSpans' $
190+ getLoc <$> ne_pats
191+ inci' =
192+ if isOneLineSpan combinedSpans
193+ then id
194+ else inci
194195 switchLayout [combinedSpans] $ do
195− let stdCase = sep breakpoint (located' p_pat) m_pats
196+ let stdCase = sep breakpoint p_pat m_pats
196197 case style of
197198 Function name ->
198199 p_infixDefHelper
199200 isInfix
200− indentBody
201+ inci'
201202 (p_rdrName name)
202− (located' p_pat <$> m_pats)
203+ (p_pat <$> m_pats)
203204 PatternBind -> stdCase
204205 Case -> stdCase
205206 Lambda -> do
@@ -212,32 +213,40 @@ p_match' placer render style isInfix strictness m_pats GRHSs {..} = do
212213 when needsSpace space
213214 sitcc stdCase
214215 LambdaCase -> stdCase
215− return indentBody
216+ return inci'
216217 let -- Calculate position of end of patterns. This is useful when we decide
217218 -- about putting certain constructions in hanging positions.
218219 endOfPats = case NE.nonEmpty m_pats of
219220 Nothing -> case style of
220− Function name -> Just (getLoc name)
221+ Function name -> (Just . srcSpanEnd . getLoc) name
221222 _ -> Nothing
222− Just pats -> (Just . getLoc . NE.last) pats
223+ Just pats -> (Just . srcSpanEnd . getLoc . NE.last) pats
223224 isCase = \case
224225 Case -> True
225226 LambdaCase -> True
226227 _ -> False
227− hasGuards = withGuards grhssGRHSs
228− grhssSpan =
228+ let hasGuards = withGuards grhssGRHSs
229+ unless (length grhssGRHSs > 1) $
230+ case style of
231+ Function _ | hasGuards -> return ()
232+ Function _ -> space >> txt "="
233+ PatternBind -> space >> txt "="
234+ s | isCase s && hasGuards -> return ()
235+ _ -> space >> txt "->"
236+ let grhssSpan =
229237 combineSrcSpans' $
230238 getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
231239 patGrhssSpan =
232240 maybe
233241 grhssSpan
234− (combineSrcSpans grhssSpan . srcLocSpan . srcSpanEnd)
242+ (combineSrcSpans grhssSpan . srcLocSpan)
235243 endOfPats
236244 placement =
237245 case endOfPats of
238246 Nothing -> blockPlacement placer grhssGRHSs
239247 Just spn ->
240− if onTheSameLine spn grhssSpan
248+ if isOneLineSpan
249+ (mkSrcSpan spn (srcSpanStart grhssSpan))
241250 then blockPlacement placer grhssGRHSs
242251 else Normal
243252 p_body = do
@@ -253,18 +262,11 @@ p_match' placer render style isInfix strictness m_pats GRHSs {..} = do
253262 txt "where"
254263 unless whereIsEmpty breakpoint
255264 inci $ located grhssLocalBinds p_hsLocalBinds
256− inciIf indentBody $ do
257− unless (length grhssGRHSs > 1) $
258− case style of
259− Function _ | hasGuards -> return ()
260− Function _ -> space >> inci equals
261− PatternBind -> space >> inci equals
262− s | isCase s && hasGuards -> return ()
263− _ -> space >> txt "->"
265+ inci' $ do
264266 switchLayout [patGrhssSpan] $
265267 placeHanging placement p_body
266268 inci p_where
267−p_match' _ _ _ _ _ _ (XGRHSs x) = noExtCon x
269+p_match' _ _ _ _ _ _ XGRHSs {} = notImplemented "XGRHSs"
268270
269271p_grhs :: GroupStyle -> GRHS GhcPs (LHsExpr GhcPs) -> R ()
270272p_grhs = p_grhs' exprPlacement p_hsExpr
@@ -278,109 +280,79 @@ p_grhs' ::
278280 GroupStyle ->
279281 GRHS GhcPs (Located body) ->
280282 R ()
281−p_grhs' placer render style (GRHS NoExtField guards body) =
283+p_grhs' placer render style (GRHS NoExt guards body) =
282284 case guards of
283285 [] -> p_body
284286 xs -> do
285287 txt "|"
286288 space
287− sitcc (sep commaDel (sitcc . located' p_stmt) xs)
289+ sitcc (sep (comma >> breakpoint) (sitcc . located' p_stmt) xs)
288290 space
289− inci $ case style of
290− EqualSign -> equals
291− RightArrow -> txt "->"
291+ txt $ case style of
292+ EqualSign -> "="
293+ RightArrow -> "->"
292294 placeHanging placement p_body
293295 where
294296 placement =
295297 case endOfGuards of
296298 Nothing -> placer (unLoc body)
297299 Just spn ->
298− if onTheSameLine spn (getLoc body)
300+ if isOneLineSpan (mkSrcSpan spn (srcSpanStart (getLoc body)))
299301 then placer (unLoc body)
300302 else Normal
301303 endOfGuards =
302304 case NE.nonEmpty guards of
303305 Nothing -> Nothing
304− Just gs -> (Just . getLoc . NE.last) gs
306+ Just gs -> (Just . srcSpanEnd . getLoc . NE.last) gs
305307 p_body = located body render
306−p_grhs' _ _ _ (XGRHS x) = noExtCon x
308+p_grhs' _ _ _ (XGRHS NoExt) = notImplemented "XGRHS"
307309
308310p_hsCmd :: HsCmd GhcPs -> R ()
309311p_hsCmd = \case
310− HsCmdArrApp NoExtField body input arrType _ -> do
312+ HsCmdArrApp NoExt body input arrType _ -> do
311313 located body p_hsExpr
312− breakpoint
313− inci $ do
314− case arrType of
315− HsFirstOrderApp -> txt "-<"
316− HsHigherOrderApp -> txt "-<<"
317− placeHanging (exprPlacement (unLoc input)) $
318− located input p_hsExpr
319− HsCmdArrForm NoExtField form Prefix _ cmds -> banana $ do
314+ space
315+ case arrType of
316+ HsFirstOrderApp -> txt "-<"
317+ HsHigherOrderApp -> txt "-<<"
318+ placeHanging (exprPlacement (unLoc input)) $
319+ located input p_hsExpr
320+ HsCmdArrForm NoExt form Prefix _ cmds -> banana $ sitcc $ do
320321 located form p_hsExpr
321322 unless (null cmds) $ do
322323 breakpoint
323324 inci (sequence_ (intersperse breakpoint (located' p_hsCmdTop <$> cmds)))
324− HsCmdArrForm NoExtField form Infix _ [left, right] -> do
325+ HsCmdArrForm NoExt form Infix _ [left, right] -> do
325326 located left p_hsCmdTop
326327 space
327328 located form p_hsExpr
328329 placeHanging (cmdTopPlacement (unLoc right)) $
329330 located right p_hsCmdTop
330− HsCmdArrForm NoExtField _ Infix _ _ -> notImplemented "HsCmdArrForm"
331+ HsCmdArrForm NoExt _ Infix _ _ -> notImplemented "HsCmdArrForm"
331332 HsCmdApp {} ->
332333 -- XXX Does this ever occur in the syntax tree? It does not seem like it
333334 -- does. Open an issue and ping @yumiova if this ever occurs in output.
334335 notImplemented "HsCmdApp"
335− HsCmdLam NoExtField mgroup -> p_matchGroup' cmdPlacement p_hsCmd Lambda mgroup
336− HsCmdPar NoExtField c -> parens N (located c p_hsCmd)
337− HsCmdCase NoExtField e mgroup ->
336+ HsCmdLam NoExt mgroup -> p_matchGroup' cmdPlacement p_hsCmd Lambda mgroup
337+ HsCmdPar NoExt c -> parens N (located c p_hsCmd)
338+ HsCmdCase NoExt e mgroup ->
338339 p_case cmdPlacement p_hsCmd e mgroup
339− HsCmdIf NoExtField _ if' then' else' ->
340+ HsCmdIf NoExt _ if' then' else' ->
340341 p_if cmdPlacement p_hsCmd if' then' else'
341− HsCmdLet NoExtField localBinds c ->
342+ HsCmdLet NoExt localBinds c ->
342343 p_let p_hsCmd localBinds c
343− HsCmdDo NoExtField es -> do
344+ HsCmdDo NoExt es -> do
344345 txt "do"
345346 newline
346347 inci . located es $
347− sitcc . sep newline (sitcc . withSpacing (p_stmt' cmdPlacement p_hsCmd))
348+ sitcc . sep newline (located' (sitcc . p_stmt' cmdPlacement p_hsCmd))
348349 HsCmdWrap {} -> notImplemented "HsCmdWrap"
349− XCmd x -> noExtCon x
350+ XCmd {} -> notImplemented "XCmd"
350351
351352p_hsCmdTop :: HsCmdTop GhcPs -> R ()
352353p_hsCmdTop = \case
353− HsCmdTop NoExtField cmd -> located cmd p_hsCmd
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)
354+ HsCmdTop NoExt cmd -> located cmd p_hsCmd
355+ XCmdTop {} -> notImplemented "XHsCmdTop"
384356
385357p_stmt :: Stmt GhcPs (LHsExpr GhcPs) -> R ()
386358p_stmt = p_stmt' exprPlacement p_hsExpr
@@ -395,13 +367,16 @@ p_stmt' ::
395367 Stmt GhcPs (Located body) ->
396368 R ()
397369p_stmt' placer render = \case
398− LastStmt NoExtField body _ _ -> located body render
399− BindStmt NoExtField p f _ _ -> do
400− located p p_pat
370+ LastStmt NoExt body _ _ -> located body render
371+ BindStmt NoExt p f _ _ -> do
372+ p_pat p
401373 space
402374 txt "<-"
403− let loc = getLoc p
404− placement =
375+ -- https://gitlab.haskell.org/ghc/ghc/issues/17330
376+ let loc = case p of
377+ XPat pat -> getLoc pat
378+ _ -> error "p_stmt': BindStmt: Pat does not contain a location"
379+ let placement =
405380 case f of
406381 L l' x ->
407382 if isOneLineSpan
@@ -411,8 +386,8 @@ p_stmt' placer render = \case
411386 switchLayout [loc, getLoc f] $
412387 placeHanging placement (located f render)
413388 ApplicativeStmt {} -> notImplemented "ApplicativeStmt" -- generated by renamer
414− BodyStmt NoExtField body _ _ -> located body render
415− LetStmt NoExtField binds -> do
389+ BodyStmt NoExt body _ _ -> located body render
390+ LetStmt NoExt binds -> do
416391 txt "let"
417392 space
418393 sitcc $ located binds p_hsLocalBinds
@@ -453,11 +428,11 @@ p_stmt' placer render = \case
453428 RecStmt {..} -> do
454429 txt "rec"
455430 space
456− sitcc $ sepSemi (withSpacing (p_stmt' placer render)) recS_stmts
457− XStmtLR c -> noExtCon c
431+ sitcc $ sepSemi (located' (p_stmt' placer render)) recS_stmts
432+ XStmtLR {} -> notImplemented "XStmtLR"
458433
459434gatherStmt :: ExprLStmt GhcPs -> [[ExprLStmt GhcPs]]
460−gatherStmt (L _ (ParStmt NoExtField block _ _)) =
435+gatherStmt (L _ (ParStmt NoExt block _ _)) =
461436 foldr ((<>) . gatherStmtBlock) [] block
462437gatherStmt (L s stmt@TransStmt {..}) =
463438 foldr liftAppend [] ((gatherStmt <$> trS_stmts) <> pure [[L s stmt]])
@@ -466,46 +441,46 @@ gatherStmt stmt = [[stmt]]
466441gatherStmtBlock :: ParStmtBlock GhcPs GhcPs -> [[ExprLStmt GhcPs]]
467442gatherStmtBlock (ParStmtBlock _ stmts _ _) =
468443 foldr (liftAppend . gatherStmt) [] stmts
469−gatherStmtBlock (XParStmtBlock x) = noExtCon x
444+gatherStmtBlock XParStmtBlock {} = notImplemented "XParStmtBlock"
470445
471446p_hsLocalBinds :: HsLocalBindsLR GhcPs GhcPs -> R ()
472447p_hsLocalBinds = \case
473− HsValBinds NoExtField (ValBinds NoExtField bag lsigs) -> do
448+ HsValBinds NoExt (ValBinds NoExt bag lsigs) -> do
449+ let ssStart =
450+ either
451+ (srcSpanStart . getLoc)
452+ (srcSpanStart . getLoc)
453+ items =
454+ (Left <$> bagToList bag) ++ (Right <$> lsigs)
455+ p_item (Left x) = located x p_valDecl
456+ p_item (Right x) = located x p_sigDecl
457+ -- Assigns 'False' to the last element, 'True' to the rest.
458+ markInit :: [a] -> [(Bool, a)]
459+ markInit [] = []
460+ markInit [x] = [(False, x)]
461+ markInit (x : xs) = (True, x) : markInit xs
474462 -- When in a single-line layout, there is a chance that the inner
475463 -- elements will also contain semicolons and they will confuse the
476464 -- parser. so we request braces around every element except the last.
477465 br <- layoutToBraces <$> getLayout
478− let items =
479− let injectLeft (L l x) = L l (Left x)
480− injectRight (L l x) = L l (Right x)
481− in (injectLeft <$> bagToList bag) ++ (injectRight <$> lsigs)
482− positionToBracing = \case
483− SinglePos -> id
484− FirstPos -> br
485− MiddlePos -> br
486− LastPos -> id
487− p_item' (p, item) =
488− positionToBracing p $
489− withSpacing (either p_valDecl p_sigDecl) item
490− binds = sortOn (srcSpanStart . getLoc) items
491− sitcc $ sepSemi p_item' (attachRelativePos binds)
492− HsValBinds NoExtField _ -> notImplemented "HsValBinds"
493− HsIPBinds NoExtField (IPBinds NoExtField xs) ->
466+ sitcc $
467+ sepSemi
468+ (\(m, i) -> (if m then br else id) $ p_item i)
469+ (markInit $ sortOn ssStart items)
470+ HsValBinds NoExt _ -> notImplemented "HsValBinds"
471+ HsIPBinds NoExt (IPBinds NoExt xs) ->
494472 -- Second argument of IPBind is always Left before type-checking.
495− let p_ipBind (IPBind NoExtField (Left name) expr) = do
473+ let p_ipBind (IPBind NoExt (Left name) expr) = do
496474 atom name
497475 space
498− equals
476+ txt "="
499477 breakpoint
500478 useBraces $ inci $ located expr p_hsExpr
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
479+ p_ipBind _ = notImplemented "XHsIPBinds"
505480 in sepSemi (located' p_ipBind) xs
506− HsIPBinds NoExtField _ -> notImplemented "HsIpBinds"
507− EmptyLocalBinds NoExtField -> return ()
508− XHsLocalBindsLR x -> noExtCon x
481+ HsIPBinds NoExt _ -> notImplemented "HsIpBinds"
482+ EmptyLocalBinds NoExt -> return ()
483+ XHsLocalBindsLR _ -> notImplemented "XHsLocalBindsLR"
509484
510485p_hsRecField ::
511486 HsRecField' RdrName (LHsExpr GhcPs) ->
@@ -514,45 +489,48 @@ p_hsRecField HsRecField {..} = do
514489 p_rdrName hsRecFieldLbl
515490 unless hsRecPun $ do
516491 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)
492+ txt "="
493+ let placement = exprPlacement (unLoc hsRecFieldArg)
494+ placeHanging placement $ located hsRecFieldArg p_hsExpr
495+
496+p_hsTupArg :: HsTupArg GhcPs -> R ()
497+p_hsTupArg = \case
498+ Present NoExt x -> located x p_hsExpr
499+ Missing NoExt -> pure ()
500+ XTupArg {} -> notImplemented "XTupArg"
523501
524502p_hsExpr :: HsExpr GhcPs -> R ()
525503p_hsExpr = p_hsExpr' N
526504
527505p_hsExpr' :: BracketStyle -> HsExpr GhcPs -> R ()
528506p_hsExpr' s = \case
529− HsVar NoExtField name -> p_rdrName name
530− HsUnboundVar NoExtField v -> atom (unboundVarOcc v)
531− HsConLikeOut NoExtField _ -> notImplemented "HsConLikeOut"
532− HsRecFld NoExtField x ->
507+ HsVar NoExt name -> p_rdrName name
508+ HsUnboundVar NoExt _ -> notImplemented "HsUnboundVar"
509+ HsConLikeOut NoExt _ -> notImplemented "HsConLikeOut"
510+ HsRecFld NoExt x ->
533511 case x of
534− Unambiguous NoExtField name -> p_rdrName name
535− Ambiguous NoExtField name -> p_rdrName name
536− XAmbiguousFieldOcc xx -> noExtCon xx
537− HsOverLabel NoExtField _ v -> do
512+ Unambiguous NoExt name -> p_rdrName name
513+ Ambiguous NoExt name -> p_rdrName name
514+ XAmbiguousFieldOcc NoExt -> notImplemented "XAmbiguousFieldOcc"
515+ HsOverLabel NoExt _ v -> do
538516 txt "#"
539517 atom v
540− HsIPVar NoExtField (HsIPName name) -> do
518+ HsIPVar NoExt (HsIPName name) -> do
541519 txt "?"
542520 atom name
543− HsOverLit NoExtField v -> atom (ol_val v)
544− HsLit NoExtField lit ->
521+ HsOverLit NoExt v -> atom (ol_val v)
522+ HsLit NoExt lit ->
545523 case lit of
546524 HsString (SourceText stxt) _ -> p_stringLit stxt
547525 HsStringPrim (SourceText stxt) _ -> p_stringLit stxt
548526 r -> atom r
549− HsLam NoExtField mgroup ->
527+ HsLam NoExt mgroup ->
550528 p_matchGroup Lambda mgroup
551− HsLamCase NoExtField mgroup -> do
529+ HsLamCase NoExt mgroup -> do
552530 txt "\\case"
553531 breakpoint
554532 inci (p_matchGroup LambdaCase mgroup)
555− HsApp NoExtField f x -> do
533+ HsApp NoExt f x -> do
556534 let -- In order to format function applications with multiple parameters
557535 -- nicer, traverse the AST to gather the function and all the
558536 -- parameters together.
@@ -584,21 +562,23 @@ p_hsExpr' s = \case
584562 -- do-block or case expression it is not a good idea. It seems
585563 -- to be safe to always bump indentation when the function
586564 -- expression is parenthesised.
587− doIndent =
565+ indent =
588566 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
567+ L _ (HsPar NoExt _) -> inci
568+ L _ (HsAppType NoExt _ _) -> inci
569+ L _ (HsMultiIf NoExt _) -> inci
570+ L spn _ ->
571+ if isOneLineSpan spn
572+ then inci
573+ else id
574+ ub <- getLayout <&> \case
575+ SingleLine -> useBraces
576+ MultiLine -> id
597577 ub $ do
598578 located func (p_hsExpr' s)
599579 breakpoint
600− inciIf doIndent $ sep breakpoint (located' p_hsExpr) initp
601− inciIf doIndent $ do
580+ indent $ sep breakpoint (located' p_hsExpr) initp
581+ indent $ do
602582 unless (null initp) breakpoint
603583 located lastp p_hsExpr
604584 Hanging -> do
@@ -608,87 +588,76 @@ p_hsExpr' s = \case
608588 sep breakpoint (located' p_hsExpr) initp
609589 placeHanging placement $
610590 located lastp p_hsExpr
611− HsAppType NoExtField e a -> do
591+ HsAppType NoExt e a -> do
612592 located e p_hsExpr
613593 breakpoint
614594 inci $ do
615595 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 ()
621596 located (hswc_body a) p_hsType
622− OpApp NoExtField x op y -> do
597+ OpApp NoExt x op y -> do
623598 let opTree = OpBranch (exprOpTree x) op (exprOpTree y)
624− p_exprOpTree s (reassociateOpTree getOpName opTree)
625− NegApp NoExtField e _ -> do
599+ p_exprOpTree True s (reassociateOpTree getOpName opTree)
600+ NegApp NoExt e _ -> do
626601 txt "-"
627602 space
628603 located e p_hsExpr
629− HsPar NoExtField e ->
604+ HsPar NoExt e ->
630605 parens s (located e (dontUseBraces . p_hsExpr))
631− SectionL NoExtField x op -> do
606+ SectionL NoExt x op -> do
632607 located x p_hsExpr
633608 breakpoint
634609 inci (located op p_hsExpr)
635− SectionR NoExtField op x -> do
610+ SectionR NoExt op x -> do
636611 located op p_hsExpr
637612 useRecordDot' <- useRecordDot
638613 let isRecordDot' = isRecordDot (unLoc op) (getLoc x)
639614 unless (useRecordDot' && isRecordDot') breakpoint
640615 inci (located x p_hsExpr)
641− ExplicitTuple NoExtField args boxity ->
616+ ExplicitTuple NoExt args boxity -> do
642617 let isSection = any (isMissing . unLoc) args
643618 isMissing = \case
644− Missing NoExtField -> True
619+ Missing NoExt -> True
645620 _ -> False
646− p_arg = \case
647− Present NoExtField x -> located x p_hsExpr
648− Missing NoExtField -> pure ()
649− XTupArg x -> noExtCon x
650− p_larg = sitcc . located' p_arg
651− parens' =
621+ let parens' =
652622 case boxity of
653623 Boxed -> parens
654624 Unboxed -> parensHash
655− in if isSection
656− then
657− switchLayout [] . parens' s $
658− sep comma p_larg args
659− else
660− switchLayout (getLoc <$> args) . parens' s $
661− sep commaDel p_larg args
662− ExplicitSum NoExtField tag arity e ->
625+ if isSection
626+ then
627+ switchLayout [] . parens' s $
628+ sep comma (located' p_hsTupArg) args
629+ else
630+ switchLayout (getLoc <$> args) . parens' s . sitcc $
631+ sep (comma >> breakpoint) (sitcc . located' p_hsTupArg) args
632+ ExplicitSum NoExt tag arity e ->
663633 p_unboxedSum N tag arity (located e p_hsExpr)
664− HsCase NoExtField e mgroup ->
634+ HsCase NoExt e mgroup ->
665635 p_case exprPlacement p_hsExpr e mgroup
666− HsIf NoExtField _ if' then' else' ->
636+ HsIf NoExt _ if' then' else' ->
667637 p_if exprPlacement p_hsExpr if' then' else'
668− HsMultiIf NoExtField guards -> do
669− txt "if"
670− breakpoint
671− inci . inci $ sep newline (located' (p_grhs RightArrow)) guards
672− HsLet NoExtField localBinds e ->
638+ HsMultiIf NoExt guards -> do
639+ txt "if "
640+ inci . inci . sitcc $ sep newline (located' (p_grhs RightArrow)) guards
641+ HsLet NoExt localBinds e ->
673642 p_let p_hsExpr localBinds e
674− HsDo NoExtField ctx es -> do
643+ HsDo NoExt ctx es -> do
675644 let doBody header = do
676645 txt header
677646 breakpoint
678647 ub <- layoutToBraces <$> getLayout
679648 inci $
680649 sepSemi
681− (ub . withSpacing (p_stmt' exprPlacement (p_hsExpr' S)))
650+ (located' (ub . p_stmt' exprPlacement (p_hsExpr' S)))
682651 (unLoc es)
683− compBody = brackets N . located es $ \xs -> do
652+ compBody = brackets N $ located es $ \xs -> do
684653 let p_parBody =
685654 sep
686− (breakpoint >> txt "|" >> space)
655+ (breakpoint >> txt "| ")
687656 p_seqBody
688657 p_seqBody =
689658 sitcc
690659 . sep
691− commaDel
660+ (comma >> breakpoint)
692661 (located' (sitcc . p_stmt))
693662 stmts = init xs
694663 yield = last xs
@@ -709,25 +678,25 @@ p_hsExpr' s = \case
709678 ParStmtCtxt _ -> notImplemented "ParStmtCtxt"
710679 TransStmtCtxt _ -> notImplemented "TransStmtCtxt"
711680 ExplicitList _ _ xs ->
712− brackets s $
713− sep commaDel (sitcc . located' p_hsExpr) xs
681+ brackets s . sitcc $
682+ sep (comma >> breakpoint) (sitcc . located' p_hsExpr) xs
714683 RecordCon {..} -> do
715684 located rcon_con_name atom
716685 breakpoint
717686 let HsRecFields {..} = rcon_flds
718687 updName f =
719− (f :: HsRecField GhcPs (LHsExpr GhcPs))
688+ f
720689 { hsRecFieldLbl = case unLoc $ hsRecFieldLbl f of
721690 FieldOcc _ n -> n
722− XFieldOcc x -> noExtCon x
691+ XFieldOcc _ -> notImplemented "XFieldOcc"
723692 }
724693 fields = located' (p_hsRecField . updName) <$> rec_flds
725694 dotdot =
726695 case rec_dotdot of
727696 Just {} -> [txt ".."]
728697 Nothing -> []
729− inci . braces N $
730− sep commaDel sitcc (fields <> dotdot)
698+ inci . braces N . sitcc $
699+ sep (comma >> breakpoint) sitcc (fields <> dotdot)
731700 RecordUpd {..} -> do
732701 located rupd_expr p_hsExpr
733702 useRecordDot' <- useRecordDot
@@ -739,66 +708,67 @@ p_hsExpr' s = \case
739708 == (srcSpanStartCol <$> mrs (head rupd_flds))
740709 unless (useRecordDot' && isPluginForm) breakpoint
741710 let updName f =
742− (f :: HsRecUpdField GhcPs)
711+ f
743712 { hsRecFieldLbl = case unLoc $ hsRecFieldLbl f of
744713 Ambiguous _ n -> n
745714 Unambiguous _ n -> n
746− XAmbiguousFieldOcc x -> noExtCon x
715+ XAmbiguousFieldOcc _ -> notImplemented "XAmbiguousFieldOcc"
747716 }
748− inci . braces N $
717+ inci . braces N . sitcc $
749718 sep
750− commaDel
719+ (comma >> breakpoint)
751720 (sitcc . located' (p_hsRecField . updName))
752721 rupd_flds
753− ExprWithTySig NoExtField x HsWC {hswc_body = HsIB {..}} -> sitcc $ do
722+ ExprWithTySig NoExt x HsWC {hswc_body = HsIB {..}} -> sitcc $ do
754723 located x p_hsExpr
755724 space
756725 txt "::"
757726 breakpoint
758727 inci $ located hsib_body p_hsType
759− ExprWithTySig NoExtField _ HsWC {hswc_body = XHsImplicitBndrs x} -> noExtCon x
760− ExprWithTySig NoExtField _ (XHsWildCardBndrs x) -> noExtCon x
761− ArithSeq NoExtField _ x ->
728+ ExprWithTySig NoExt _ HsWC {hswc_body = XHsImplicitBndrs {}} ->
729+ notImplemented "XHsImplicitBndrs"
730+ ExprWithTySig NoExt _ XHsWildCardBndrs {} -> notImplemented "XHsWildCardBndrs"
731+ ArithSeq NoExt _ x ->
762732 case x of
763− From from -> brackets s $ do
733+ From from -> brackets s . sitcc $ do
764734 located from p_hsExpr
765735 breakpoint
766736 txt ".."
767− FromThen from next -> brackets s $ do
768− sep commaDel (located' p_hsExpr) [from, next]
737+ FromThen from next -> brackets s . sitcc $ do
738+ sitcc $ sep (comma >> breakpoint) (located' p_hsExpr) [from, next]
769739 breakpoint
770740 txt ".."
771− FromTo from to -> brackets s $ do
741+ FromTo from to -> brackets s . sitcc $ do
772742 located from p_hsExpr
773743 breakpoint
774744 txt ".."
775745 space
776746 located to p_hsExpr
777− FromThenTo from next to -> brackets s $ do
778− sep commaDel (located' p_hsExpr) [from, next]
747+ FromThenTo from next to -> brackets s . sitcc $ do
748+ sitcc $ sep (comma >> breakpoint) (located' p_hsExpr) [from, next]
779749 breakpoint
780750 txt ".."
781751 space
782752 located to p_hsExpr
783− HsSCC NoExtField _ name x -> do
753+ HsSCC NoExt _ name x -> do
784754 txt "{-# SCC "
785755 atom name
786756 txt " #-}"
787757 breakpoint
788758 located x p_hsExpr
789− HsCoreAnn NoExtField _ value x -> do
759+ HsCoreAnn NoExt _ value x -> do
790760 txt "{-# CORE "
791761 atom value
792762 txt " #-}"
793763 breakpoint
794764 located x p_hsExpr
795− HsBracket NoExtField x -> p_hsBracket x
765+ HsBracket NoExt x -> p_hsBracket x
796766 HsRnBracketOut {} -> notImplemented "HsRnBracketOut"
797767 HsTcBracketOut {} -> notImplemented "HsTcBracketOut"
798− HsSpliceE NoExtField splice -> p_hsSplice splice
799− HsProc NoExtField p e -> do
768+ HsSpliceE NoExt splice -> p_hsSplice splice
769+ HsProc NoExt p e -> do
800770 txt "proc"
801− located p $ \x -> do
771+ locatedPat p $ \x -> do
802772 breakpoint
803773 inci (p_pat x)
804774 breakpoint
@@ -809,11 +779,31 @@ p_hsExpr' s = \case
809779 txt "static"
810780 breakpoint
811781 inci (located e p_hsExpr)
782+ HsArrApp NoExt body input arrType cond ->
783+ p_hsCmd (HsCmdArrApp NoExt body input arrType cond)
784+ HsArrForm NoExt form mfixity cmds ->
785+ p_hsCmd (HsCmdArrForm NoExt form Prefix mfixity cmds)
812786 HsTick {} -> notImplemented "HsTick"
813787 HsBinTick {} -> notImplemented "HsBinTick"
814788 HsTickPragma {} -> notImplemented "HsTickPragma"
789+ -- These four constructs should never appear in correct programs.
790+ -- See: https://github.com/tweag/ormolu/issues/343
791+ EWildPat NoExt -> txt "_"
792+ EAsPat NoExt n p -> do
793+ p_rdrName n
794+ txt "@"
795+ located p p_hsExpr
796+ EViewPat NoExt p e -> do
797+ located p p_hsExpr
798+ space
799+ txt "->"
800+ breakpoint
801+ inci (located e p_hsExpr)
802+ ELazyPat NoExt p -> do
803+ txt "~"
804+ located p p_hsExpr
815805 HsWrap {} -> notImplemented "HsWrap"
816− XExpr x -> noExtCon x
806+ XExpr {} -> notImplemented "XExpr"
817807
818808p_patSynBind :: PatSynBind GhcPs GhcPs -> R ()
819809p_patSynBind PSB {..} = do
@@ -823,15 +813,15 @@ p_patSynBind PSB {..} = do
823813 Unidirectional -> do
824814 txt "<-"
825815 breakpoint
826− located psb_def p_pat
816+ p_pat psb_def
827817 ImplicitBidirectional -> do
828− equals
818+ txt "="
829819 breakpoint
830− located psb_def p_pat
820+ p_pat psb_def
831821 ExplicitBidirectional mgroup -> do
832822 txt "<-"
833823 breakpoint
834− located psb_def p_pat
824+ p_pat psb_def
835825 newline
836826 txt "where"
837827 newline
@@ -852,8 +842,8 @@ p_patSynBind PSB {..} = do
852842 inci $ do
853843 switchLayout (getLoc . recordPatSynPatVar <$> xs) $ do
854844 unless (null xs) breakpoint
855− braces N $
856− sep commaDel (p_rdrName . recordPatSynPatVar) xs
845+ braces N . sitcc $
846+ sep (comma >> breakpoint) (p_rdrName . recordPatSynPatVar) xs
857847 rhs
858848 InfixCon l r -> do
859849 switchLayout [getLoc l, getLoc r] $ do
@@ -865,7 +855,7 @@ p_patSynBind PSB {..} = do
865855 space
866856 p_rdrName r
867857 inci rhs
868−p_patSynBind (XPatSynBind x) = noExtCon x
858+p_patSynBind (XPatSynBind NoExt) = notImplemented "XPatSynBind"
869859
870860p_case ::
871861 Data body =>
@@ -907,12 +897,10 @@ p_if placer render if' then' else' = do
907897 breakpoint
908898 inci $ do
909899 txt "then"
910− space
911900 located then' $ \x ->
912901 placeHanging (placer x) (render x)
913902 breakpoint
914903 txt "else"
915− space
916904 located else' $ \x ->
917905 placeHanging (placer x) (render x)
918906
@@ -934,77 +922,77 @@ p_let render localBinds e = sitcc $ do
934922
935923p_pat :: Pat GhcPs -> R ()
936924p_pat = \case
937− WildPat NoExtField -> txt "_"
938− VarPat NoExtField name -> p_rdrName name
939− LazyPat NoExtField pat -> do
925+ -- Note: starting from GHC 8.8, 'LPat' == 'Pat'. Located 'Pat's are always
926+ -- constructed with the 'XPat' constructor, containing a @Located Pat@.
927+ XPat pat -> located pat p_pat
928+ WildPat NoExt -> txt "_"
929+ VarPat NoExt name -> p_rdrName name
930+ LazyPat NoExt pat -> do
940931 txt "~"
941− located pat p_pat
942− AsPat NoExtField name pat -> do
932+ p_pat pat
933+ AsPat NoExt name pat -> do
943934 p_rdrName name
944935 txt "@"
945− located pat p_pat
946− ParPat NoExtField pat ->
947− located pat (parens S . p_pat)
948− BangPat NoExtField pat -> do
936+ p_pat pat
937+ ParPat NoExt pat ->
938+ locatedPat pat (parens S . p_pat)
939+ BangPat NoExt pat -> do
949940 txt "!"
950− located pat p_pat
951− ListPat NoExtField pats ->
952− brackets S $ sep commaDel (located' p_pat) pats
953− TuplePat NoExtField pats boxing -> do
954− let parens' =
941+ p_pat pat
942+ ListPat NoExt pats ->
943+ brackets S . sitcc $ sep (comma >> breakpoint) p_pat pats
944+ TuplePat NoExt pats boxing -> do
945+ let f =
955946 case boxing of
956947 Boxed -> parens S
957948 Unboxed -> parensHash S
958− parens' $ sep commaDel (sitcc . located' p_pat) pats
959− SumPat NoExtField pat tag arity ->
960− p_unboxedSum S tag arity (located pat p_pat)
949+ f . sitcc $ sep (comma >> breakpoint) (sitcc . p_pat) pats
950+ SumPat NoExt pat tag arity ->
951+ p_unboxedSum S tag arity (p_pat pat)
961952 ConPatIn pat details ->
962953 case details of
963954 PrefixCon xs -> sitcc $ do
964955 p_rdrName pat
965956 unless (null xs) $ do
966957 breakpoint
967− inci . sitcc $ sep breakpoint (sitcc . located' p_pat) xs
958+ inci . sitcc $ sep breakpoint (sitcc . p_pat) xs
968959 RecCon (HsRecFields fields dotdot) -> do
969960 p_rdrName pat
970961 breakpoint
971962 let f = \case
972963 Nothing -> txt ".."
973964 Just x -> located x p_pat_hsRecField
974− inci . braces N . sep commaDel f $
965+ inci . braces N . sitcc . sep (comma >> breakpoint) f $
975966 case dotdot of
976967 Nothing -> Just <$> fields
977− Just (L _ n) -> (Just <$> take n fields) ++ [Nothing]
978− InfixCon l r -> do
979− switchLayout [getLoc l, getLoc r] $ do
980− located l p_pat
981− breakpoint
982− inci $ do
983− p_rdrName pat
984− space
985− located r p_pat
968+ Just n -> (Just <$> take n fields) ++ [Nothing]
969+ InfixCon x y -> do
970+ p_pat x
971+ space
972+ p_rdrName pat
973+ breakpoint
974+ inci (p_pat y)
986975 ConPatOut {} -> notImplemented "ConPatOut" -- presumably created by renamer?
987− ViewPat NoExtField expr pat -> sitcc $ do
976+ ViewPat NoExt expr pat -> sitcc $ do
988977 located expr p_hsExpr
989978 space
990979 txt "->"
991980 breakpoint
992− inci (located pat p_pat)
993− SplicePat NoExtField splice -> p_hsSplice splice
994− LitPat NoExtField p -> atom p
995− NPat NoExtField v _ _ -> located v (atom . ol_val)
996− NPlusKPat NoExtField n k _ _ _ -> sitcc $ do
981+ inci (p_pat pat)
982+ SplicePat NoExt splice -> p_hsSplice splice
983+ LitPat NoExt p -> atom p
984+ NPat NoExt v _ _ -> located v (atom . ol_val)
985+ NPlusKPat NoExt n k _ _ _ -> sitcc $ do
997986 p_rdrName n
998987 breakpoint
999988 inci $ do
1000989 txt "+"
1001990 space
1002991 located k (atom . ol_val)
1003− SigPat NoExtField pat hswc -> do
1004− located pat p_pat
992+ SigPat NoExt pat hswc -> do
993+ p_pat pat
1005994 p_typeAscription hswc
1006995 CoPat {} -> notImplemented "CoPat" -- apparently created at some later stage
1007− XPat x -> noExtCon x
1008996
1009997p_pat_hsRecField :: HsRecField' (FieldOcc GhcPs) (LPat GhcPs) -> R ()
1010998p_pat_hsRecField HsRecField {..} = do
@@ -1012,30 +1000,32 @@ p_pat_hsRecField HsRecField {..} = do
10121000 p_rdrName (rdrNameFieldOcc x)
10131001 unless hsRecPun $ do
10141002 space
1015− equals
1003+ txt "="
10161004 breakpoint
1017− inci (located hsRecFieldArg p_pat)
1005+ inci (p_pat hsRecFieldArg)
10181006
10191007p_unboxedSum :: BracketStyle -> ConTag -> Arity -> R () -> R ()
10201008p_unboxedSum s tag arity m = do
10211009 let before = tag - 1
10221010 after = arity - before - 1
10231011 args = replicate before Nothing <> [Just m] <> replicate after Nothing
1024− f x =
1012+ f (x, i) = do
1013+ let isFirst = i == 0
1014+ isLast = i == arity - 1
10251015 case x :: Maybe (R ()) of
10261016 Nothing ->
1027− space
1017+ unless (isFirst || isLast) space
10281018 Just m' -> do
1029− space
1019+ unless isFirst space
10301020 m'
1031− space
1032− parensHash s $ sep (txt "|") f args
1021+ unless isLast space
1022+ parensHash s $ sep (txt "|") f (zip args [0 ..])
10331023
10341024p_hsSplice :: HsSplice GhcPs -> R ()
10351025p_hsSplice = \case
1036− HsTypedSplice NoExtField deco _ expr -> p_hsSpliceTH True expr deco
1037− HsUntypedSplice NoExtField deco _ expr -> p_hsSpliceTH False expr deco
1038− HsQuasiQuote NoExtField _ quoterName srcSpan str -> do
1026+ HsTypedSplice NoExt deco _ expr -> p_hsSpliceTH True expr deco
1027+ HsUntypedSplice NoExt deco _ expr -> p_hsSpliceTH False expr deco
1028+ HsQuasiQuote NoExt _ quoterName srcSpan str -> do
10391029 txt "["
10401030 p_rdrName (L srcSpan quoterName)
10411031 txt "|"
@@ -1045,7 +1035,7 @@ p_hsSplice = \case
10451035 txt "|]"
10461036 HsSpliced {} -> notImplemented "HsSpliced"
10471037 HsSplicedT {} -> notImplemented "HsSplicedT"
1048− XSplice x -> noExtCon x
1038+ XSplice {} -> notImplemented "XSplice"
10491039
10501040p_hsSpliceTH ::
10511041 -- | Typed splice?
@@ -1069,17 +1059,17 @@ p_hsSpliceTH isTyped expr = \case
10691059
10701060p_hsBracket :: HsBracket GhcPs -> R ()
10711061p_hsBracket = \case
1072− ExpBr NoExtField expr -> do
1062+ ExpBr NoExt expr -> do
10731063 anns <- getEnclosingAnns
10741064 let name = case anns of
10751065 AnnOpenEQ : _ -> ""
10761066 _ -> "e"
10771067 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
1068+ PatBr NoExt pat -> quote "p" (p_pat pat)
1069+ DecBrL NoExt decls -> quote "d" (p_hsDecls Free decls)
1070+ DecBrG NoExt _ -> notImplemented "DecBrG" -- result of renamer
1071+ TypBr NoExt ty -> quote "t" (located ty p_hsType)
1072+ VarBr NoExt isSingleQuote name -> do
10831073 txt (bool "''" "'" isSingleQuote)
10841074 -- HACK As you can see we use 'noLoc' here to be able to pass name into
10851075 -- 'p_rdrName' since the latter expects a "located" thing. The problem
@@ -1094,13 +1084,13 @@ p_hsBracket = \case
10941084 && not (doesNotNeedExtraParens name)
10951085 wrapper = if isOperator then parens N else id
10961086 wrapper $ p_rdrName (noLoc name)
1097− TExpBr NoExtField expr -> do
1087+ TExpBr NoExt expr -> do
10981088 txt "[||"
10991089 breakpoint'
11001090 located expr p_hsExpr
11011091 breakpoint'
11021092 txt "||]"
1103− XBracket x -> noExtCon x
1093+ XBracket {} -> notImplemented "XBracket"
11041094 where
11051095 quote :: Text -> R () -> R ()
11061096 quote name body = do
@@ -1179,9 +1169,9 @@ liftAppend (x : xs) [] = x : xs
11791169liftAppend (x : xs) (y : ys) = x <> y : liftAppend xs ys
11801170
11811171getGRHSSpan :: GRHS GhcPs (Located body) -> SrcSpan
1182−getGRHSSpan (GRHS NoExtField guards body) =
1172+getGRHSSpan (GRHS NoExt guards body) =
11831173 combineSrcSpans' $ getLoc body :| map getLoc guards
1184−getGRHSSpan (XGRHS x) = noExtCon x
1174+getGRHSSpan (XGRHS NoExt) = notImplemented "XGRHS"
11851175
11861176-- | Place a thing that may have a hanging form. This function handles how
11871177-- to separate it from preceding expressions and whether to bump indentation
@@ -1202,74 +1192,78 @@ blockPlacement ::
12021192 (body -> Placement) ->
12031193 [LGRHS GhcPs (Located body)] ->
12041194 Placement
1205−blockPlacement placer [L _ (GRHS NoExtField _ (L _ x))] = placer x
1195+blockPlacement placer [L _ (GRHS NoExt _ (L _ x))] = placer x
12061196blockPlacement _ _ = Normal
12071197
12081198-- | Check if given command has a hanging form.
12091199cmdPlacement :: HsCmd GhcPs -> Placement
12101200cmdPlacement = \case
1211− HsCmdLam NoExtField _ -> Hanging
1212− HsCmdCase NoExtField _ _ -> Hanging
1213− HsCmdDo NoExtField _ -> Hanging
1201+ HsCmdLam NoExt _ -> Hanging
1202+ HsCmdCase NoExt _ _ -> Hanging
1203+ HsCmdDo NoExt _ -> Hanging
12141204 _ -> Normal
12151205
12161206cmdTopPlacement :: HsCmdTop GhcPs -> Placement
12171207cmdTopPlacement = \case
1218− HsCmdTop NoExtField (L _ x) -> cmdPlacement x
1219− XCmdTop x -> noExtCon x
1208+ HsCmdTop NoExt (L _ x) -> cmdPlacement x
1209+ XCmdTop {} -> notImplemented "XCmdTop"
12201210
12211211-- | Check if given expression has a hanging form.
12221212exprPlacement :: HsExpr GhcPs -> Placement
12231213exprPlacement = \case
12241214 -- Only hang lambdas with single line parameter lists
1225− HsLam NoExtField mg -> case mg of
1226− MG _ (L _ [L _ (Match NoExtField _ (x : xs) _)]) _
1215+ HsLam NoExt mg -> case mg of
1216+ MG _ (L _ [L _ (Match NoExt _ (x : xs) _)]) _
12271217 | isOneLineSpan (combineSrcSpans' $ fmap getLoc (x :| xs)) ->
12281218 Hanging
12291219 _ -> Normal
1230− HsLamCase NoExtField _ -> Hanging
1231− HsCase NoExtField _ _ -> Hanging
1232− HsDo NoExtField DoExpr _ -> Hanging
1233− HsDo NoExtField MDoExpr _ -> Hanging
1234− OpApp NoExtField _ op y ->
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
1220+ HsLamCase NoExt _ -> Hanging
1221+ HsCase NoExt _ _ -> Hanging
1222+ HsDo NoExt DoExpr _ -> Hanging
1223+ HsDo NoExt MDoExpr _ -> Hanging
1224+ -- If the rightmost expression in an operator chain is hanging, make the
1225+ -- whole block hanging; so that we can use the common @f = foo $ do@
1226+ -- style.
1227+ OpApp NoExt _ _ y -> exprPlacement (unLoc y)
1228+ -- Same thing for function applications (usually with -XBlockArguments)
1229+ HsApp NoExt _ y -> exprPlacement (unLoc y)
1230+ HsProc NoExt p _ ->
1231+ -- https://gitlab.haskell.org/ghc/ghc/issues/17330
1232+ let loc = case p of
1233+ XPat pat -> getLoc pat
1234+ _ -> error "exprPlacement: HsProc: Pat does not contain a location"
1235+ in -- Indentation breaks if pattern is longer than one line and left
1236+ -- hanging. Consequently, only apply hanging when it is safe.
1237+ if isOneLineSpan loc
1238+ then Hanging
1239+ else Normal
12451240 _ -> Normal
12461241
12471242withGuards :: [LGRHS GhcPs (Located body)] -> Bool
12481243withGuards = any (checkOne . unLoc)
12491244 where
12501245 checkOne :: GRHS GhcPs (Located body) -> Bool
1251− checkOne (GRHS NoExtField [] _) = False
1246+ checkOne (GRHS NoExt [] _) = False
12521247 checkOne _ = True
12531248
12541249exprOpTree :: LHsExpr GhcPs -> OpTree (LHsExpr GhcPs) (LHsExpr GhcPs)
1255−exprOpTree (L _ (OpApp NoExtField x op y)) = OpBranch (exprOpTree x) op (exprOpTree y)
1250+exprOpTree (L _ (OpApp NoExt x op y)) = OpBranch (exprOpTree x) op (exprOpTree y)
12561251exprOpTree n = OpNode n
12571252
12581253getOpName :: HsExpr GhcPs -> Maybe RdrName
12591254getOpName = \case
1260− HsVar NoExtField (L _ a) -> Just a
1255+ HsVar NoExt (L _ a) -> Just a
12611256 _ -> Nothing
12621257
1263−getOpNameStr :: RdrName -> String
1264−getOpNameStr = occNameString . rdrNameOcc
1265−
12661258p_exprOpTree ::
1259+ -- | Can use special handling of dollar?
1260+ Bool ->
12671261 -- | Bracket style to use
12681262 BracketStyle ->
12691263 OpTree (LHsExpr GhcPs) (LHsExpr GhcPs) ->
12701264 R ()
1271−p_exprOpTree s (OpNode x) = located x (p_hsExpr' s)
1272−p_exprOpTree s (OpBranch x op y) = do
1265+p_exprOpTree _ s (OpNode x) = located x (p_hsExpr' s)
1266+p_exprOpTree isDollarSpecial s (OpBranch x op y) = do
12731267 -- If the beginning of the first argument and the second argument are on
12741268 -- the same line, and the second argument has a hanging form, use hanging
12751269 -- placement.
@@ -1280,10 +1274,8 @@ p_exprOpTree s (OpBranch x op y) = do
12801274 OpNode (L _ n) -> exprPlacement n
12811275 _ -> Normal
12821276 else Normal
1283− -- Distinguish holes used in infix notation.
1284− -- eg. '1 _foo 2' and '1 `_foo` 2'
12851277 opWrapper = case unLoc op of
1286− HsUnboundVar NoExtField _ -> backticks
1278+ EWildPat NoExt -> backticks
12871279 _ -> id
12881280 layout <- getLayout
12891281 let ub = case layout of
@@ -1291,54 +1283,44 @@ p_exprOpTree s (OpBranch x op y) = do
12911283 MultiLine -> case placement of
12921284 Hanging -> useBraces
12931285 Normal -> dontUseBraces
1294− opNameStr = (fmap getOpNameStr . getOpName . unLoc) op
1295− gotDollar = opNameStr == Just "$"
1296− gotColon = opNameStr == Just ":"
1297− gotRecordDot = isRecordDot (unLoc op) (opTreeLoc y)
1286+ gotDollar = case getOpName (unLoc op) of
1287+ Just rname -> mkVarOcc "$" == rdrNameOcc rname
1288+ _ -> False
12981289 lhs =
12991290 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)
1291+ p_exprOpTree (not gotDollar) s x
1292+ let p_op = located op (opWrapper . p_hsExpr)
1293+ p_y = switchLayout [opTreeLoc y] (p_exprOpTree True N y)
13031294 isSection = case (opTreeLoc x, getLoc op) of
13041295 (RealSrcSpan treeSpan, RealSrcSpan opSpan) ->
13051296 srcSpanEndCol treeSpan /= srcSpanStartCol opSpan
13061297 _ -> False
1307− isDoBlock = \case
1308− OpNode (L _ HsDo {}) -> True
1309− _ -> False
13101298 useRecordDot' <- useRecordDot
1311− if
1312− | gotColon -> do
1313− lhs
1314− space
1315− p_op
1316− case placement of
1317− Hanging -> do
1299+ let isRecordDot' = isRecordDot (unLoc op) (opTreeLoc y)
1300+ if useRecordDot' && isRecordDot'
1301+ then do
1302+ lhs
1303+ when isSection space
1304+ p_op
1305+ p_y
1306+ else
1307+ if isDollarSpecial
1308+ && gotDollar
1309+ && placement
1310+ == Normal
1311+ && isOneLineSpan (opTreeLoc x)
1312+ then do
1313+ useBraces lhs
1314+ space
1315+ p_op
1316+ breakpoint
1317+ inci p_y
1318+ else do
1319+ ub lhs
1320+ placeHanging placement $ do
1321+ p_op
13181322 space
13191323 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
13421324
13431325-- | Return 'True' if given expression is a record-dot operator expression.
13441326isRecordDot ::
@@ -1348,11 +1330,15 @@ isRecordDot ::
13481330 SrcSpan ->
13491331 Bool
13501332isRecordDot op (RealSrcSpan ySpan) = case op of
1351− HsVar NoExtField (L (RealSrcSpan opSpan) opName) ->
1352− (getOpNameStr opName == ".") && (srcSpanEndCol opSpan == srcSpanStartCol ySpan)
1333+ HsVar NoExt (L (RealSrcSpan opSpan) opName) ->
1334+ isDot opName && (srcSpanEndCol opSpan == srcSpanStartCol ySpan)
13531335 _ -> False
13541336isRecordDot _ _ = False
13551337
1338+-- | Check whether a given 'RdrName' is the dot operator.
1339+isDot :: RdrName -> Bool
1340+isDot name = rdrNameOcc name == mkVarOcc "."
1341+
13561342-- | Get annotations for the enclosing element.
13571343getEnclosingAnns :: R [AnnKeywordId]
13581344getEnclosingAnns = do
src/Ormolu/Printer/Meat/Declaration/Value.hs-boot+4
@@ -11,7 +11,11 @@ import GHC
1111import Ormolu.Printer.Combinators
1212
1313p_valDecl :: HsBindLR GhcPs GhcPs -> R ()
14+
1415p_pat :: Pat GhcPs -> R ()
16+
1517p_hsExpr :: HsExpr GhcPs -> R ()
18+
1619p_hsSplice :: HsSplice GhcPs -> R ()
20+
1721p_stringLit :: String -> R ()
src/Ormolu/Printer/Meat/Declaration/Warning.hs+13−9
@@ -13,28 +13,32 @@ import Data.Text (Text)
1313import GHC
1414import Ormolu.Printer.Combinators
1515import Ormolu.Printer.Meat.Common
16+import Ormolu.Utils
1617
1718p_warnDecls :: WarnDecls GhcPs -> R ()
18−p_warnDecls (Warnings NoExtField _ warnings) =
19+p_warnDecls (Warnings NoExt _ warnings) =
1920 traverse_ (located' p_warnDecl) warnings
20−p_warnDecls (XWarnDecls x) = noExtCon x
21+p_warnDecls XWarnDecls {} = notImplemented "XWarnDecls"
2122
2223p_warnDecl :: WarnDecl GhcPs -> R ()
23−p_warnDecl (Warning NoExtField functions warningTxt) =
24+p_warnDecl (Warning NoExt functions warningTxt) =
2425 p_topLevelWarning functions warningTxt
25−p_warnDecl (XWarnDecl x) = noExtCon x
26+p_warnDecl XWarnDecl {} = notImplemented "XWarnDecl"
2627
2728p_moduleWarning :: WarningTxt -> R ()
2829p_moduleWarning wtxt = do
2930 let (pragmaText, lits) = warningText wtxt
30− inci $ pragma pragmaText $ inci $ p_lits lits
31+ switchLayout (getLoc <$> lits)
32+ $ inci
33+ $ pragma pragmaText (inci $ p_lits lits)
3134
3235p_topLevelWarning :: [Located RdrName] -> WarningTxt -> R ()
3336p_topLevelWarning fnames wtxt = do
3437 let (pragmaText, lits) = warningText wtxt
35− switchLayout (fmap getLoc fnames ++ fmap getLoc lits) $
36− pragma pragmaText . inci $ do
37− sep commaDel p_rdrName fnames
38+ switchLayout (fmap getLoc fnames ++ fmap getLoc lits)
39+ $ pragma pragmaText . inci
40+ $ do
41+ sitcc $ sep (comma >> breakpoint) p_rdrName fnames
3842 breakpoint
3943 p_lits lits
4044
@@ -46,4 +50,4 @@ warningText = \case
4650p_lits :: [Located StringLiteral] -> R ()
4751p_lits = \case
4852 [l] -> atom l
49− ls -> brackets N $ sep commaDel atom ls
53+ ls -> brackets N . sitcc $ sep (comma >> breakpoint) atom ls
src/Ormolu/Printer/Meat/ImportExport.hs+35−44
@@ -11,9 +11,10 @@ where
1111
1212import Control.Monad
1313import GHC
14+import HsImpExp (IE (..))
1415import Ormolu.Printer.Combinators
1516import Ormolu.Printer.Meat.Common
16−import Ormolu.Utils (RelativePos (..), attachRelativePos)
17+import Ormolu.Utils
1718
1819p_hsmodExports :: [LIE GhcPs] -> R ()
1920p_hsmodExports [] = do
@@ -21,24 +22,19 @@ p_hsmodExports [] = do
2122 breakpoint'
2223 txt ")"
2324p_hsmodExports xs =
24− parens N $ do
25+ parens N . sitcc $ do
2526 layout <- getLayout
26− sep
27− breakpoint
28− (\(p, l) -> sitcc (located l (p_lie layout p)))
29− (attachRelativePos xs)
27+ sep breakpoint (sitcc . located' (uncurry (p_lie layout))) (attachPositions xs)
3028
31−p_hsmodImport :: Bool -> ImportDecl GhcPs -> R ()
32−p_hsmodImport useQualifiedPost ImportDecl {..} = do
29+p_hsmodImport :: ImportDecl GhcPs -> R ()
30+p_hsmodImport ImportDecl {..} = do
3331 txt "import"
3432 space
3533 when ideclSource (txt "{-# SOURCE #-}")
3634 space
3735 when ideclSafe (txt "safe")
3836 space
39− when
40− (isImportDeclQualified ideclQualified && not useQualifiedPost)
41− (txt "qualified")
37+ when ideclQualified (txt "qualified")
4238 space
4339 case ideclPkgQual of
4440 Nothing -> return ()
@@ -46,9 +42,6 @@ p_hsmodImport useQualifiedPost ImportDecl {..} = do
4642 space
4743 inci $ do
4844 located ideclName atom
49− when
50− (isImportDeclQualified ideclQualified && useQualifiedPost)
51− (space >> txt "qualified")
5245 case ideclAs of
5346 Nothing -> return ()
5447 Just l -> do
@@ -65,62 +58,60 @@ p_hsmodImport useQualifiedPost ImportDecl {..} = do
6558 Nothing -> return ()
6659 Just (_, L _ xs) -> do
6760 breakpoint
68− parens N $ do
61+ parens N . sitcc $ do
6962 layout <- getLayout
70− sep
71− breakpoint
72− (\(p, l) -> sitcc (located l (p_lie layout p)))
73− (attachRelativePos xs)
63+ sep breakpoint (sitcc . located' (uncurry (p_lie layout))) (attachPositions xs)
7464 newline
75−p_hsmodImport _ (XImportDecl x) = noExtCon x
65+p_hsmodImport (XImportDecl NoExt) = notImplemented "XImportDecl"
7666
77−p_lie :: Layout -> RelativePos -> IE GhcPs -> R ()
78−p_lie encLayout relativePos = \case
79− IEVar NoExtField l1 -> do
67+p_lie :: Layout -> (Int, Int) -> IE GhcPs -> R ()
68+p_lie encLayout (i, totalItems) = \case
69+ IEVar NoExt l1 -> do
8070 located l1 p_ieWrappedName
8171 p_comma
82− IEThingAbs NoExtField l1 -> do
72+ IEThingAbs NoExt l1 -> do
8373 located l1 p_ieWrappedName
8474 p_comma
85− IEThingAll NoExtField l1 -> do
75+ IEThingAll NoExt l1 -> do
8676 located l1 p_ieWrappedName
8777 space
8878 txt "(..)"
8979 p_comma
90− IEThingWith NoExtField l1 w xs _ -> sitcc $ do
80+ IEThingWith NoExt l1 w xs _ -> sitcc $ do
9181 located l1 p_ieWrappedName
9282 breakpoint
9383 inci $ do
9484 let names :: [R ()]
9585 names = located' p_ieWrappedName <$> xs
96− parens N . sep commaDel sitcc $
97− case w of
86+ parens N . sitcc
87+ $ sep (comma >> breakpoint) sitcc
88+ $ case w of
9889 NoIEWildcard -> names
9990 IEWildcard n ->
10091 let (before, after) = splitAt n names
10192 in before ++ [txt ".."] ++ after
10293 p_comma
103− IEModuleContents NoExtField l1 -> do
94+ IEModuleContents NoExt l1 -> do
10495 located l1 p_hsmodName
10596 p_comma
106− IEGroup NoExtField n str -> do
107− case relativePos of
108− SinglePos -> return ()
109− FirstPos -> return ()
110− MiddlePos -> newline
111− LastPos -> newline
97+ IEGroup NoExt n str -> do
98+ unless (i == 0) newline
11299 p_hsDocString (Asterisk n) False (noLoc str)
113− IEDoc NoExtField str ->
100+ IEDoc NoExt str ->
114101 p_hsDocString Pipe False (noLoc str)
115− IEDocNamed NoExtField str -> p_hsDocName str
116− XIE x -> noExtCon x
102+ IEDocNamed NoExt str -> p_hsDocName str
103+ XIE NoExt -> notImplemented "XIE"
117104 where
118105 p_comma =
119106 case encLayout of
120− SingleLine ->
121− case relativePos of
122− SinglePos -> return ()
123− FirstPos -> comma
124− MiddlePos -> comma
125− LastPos -> return ()
107+ SingleLine -> unless (i + 1 == totalItems) comma
126108 MultiLine -> comma
109+
110+-- | Attach positions to 'Located' things in a list.
111+attachPositions ::
112+ [Located a] ->
113+ [Located ((Int, Int), a)]
114+attachPositions xs =
115+ let f i (L l x) = L l ((i, n), x)
116+ n = length xs
117+ in zipWith f [0 ..] xs
src/Ormolu/Printer/Meat/Module.hs+20−26
@@ -1,4 +1,3 @@
1−{-# LANGUAGE LambdaCase #-}
21{-# LANGUAGE OverloadedStrings #-}
32{-# LANGUAGE RecordWildCards #-}
43
@@ -11,10 +10,8 @@ where
1110import Control.Monad
1211import qualified Data.Text as T
1312import GHC
14−import Ormolu.Imports (normalizeImports)
15−import Ormolu.Parser.CommentStream
13+import Ormolu.Imports
1614import Ormolu.Parser.Pragma
17−import Ormolu.Parser.Shebang
1815import Ormolu.Printer.Combinators
1916import Ormolu.Printer.Comments
2017import Ormolu.Printer.Meat.Common
@@ -25,28 +22,26 @@ import Ormolu.Printer.Meat.Pragma
2522
2623-- | Render a module.
2724p_hsModule ::
28− -- | Stack header
29− Maybe (RealLocated Comment) ->
3025 -- | Shebangs
31− [Shebang] ->
32− -- | Pragmas and the associated comments
33− [([RealLocated Comment], Pragma)] ->
34− -- | Whether to use postfix qualified imports
35− Bool ->
26+ [Located String] ->
27+ -- | Pragmas
28+ [Pragma] ->
3629 -- | AST to print
37− HsModule GhcPs ->
30+ ParsedSource ->
3831 R ()
39−p_hsModule mstackHeader shebangs pragmas qualifiedPost HsModule {..} = do
40− let deprecSpan = maybe [] (\(L s _) -> [s]) hsmodDeprecMessage
41− exportSpans = maybe [] (\(L s _) -> [s]) hsmodExports
42− switchLayout (deprecSpan <> exportSpans) $ do
43− forM_ shebangs $ \(Shebang x) ->
32+p_hsModule shebangs pragmas (L moduleSpan HsModule {..}) = do
33+ -- If span of exports in multiline, the whole thing is multiline. This is
34+ -- especially important because span of module itself always seems to have
35+ -- length zero, so it's not reliable for layout selection.
36+ let exportSpans = maybe [] (\(L s _) -> [s]) hsmodExports
37+ deprecSpan = maybe [] (\(L s _) -> [s]) hsmodDeprecMessage
38+ spans' = exportSpans ++ deprecSpan ++ [moduleSpan]
39+ switchLayout spans' $ do
40+ forM_ shebangs $ \x ->
4441 located x $ \shebang -> do
4542 txt (T.pack shebang)
4643 newline
47− forM_ mstackHeader $ \(L spn comment) -> do
48− spitCommentNow spn comment
49− newline
44+ spitStackHeader
5045 newline
5146 p_pragmas pragmas
5247 newline
@@ -56,20 +51,19 @@ p_hsModule mstackHeader shebangs pragmas qualifiedPost HsModule {..} = do
5651 located hsmodName' $ \name -> do
5752 forM_ hsmodHaddockModHeader (p_hsDocString Pipe True)
5853 p_hsmodName name
59− breakpoint
6054 forM_ hsmodDeprecMessage $ \w -> do
61− located' p_moduleWarning w
6255 breakpoint
56+ located' p_moduleWarning w
6357 case hsmodExports of
6458 Nothing -> return ()
65− Just l -> do
66− located l $ \exports -> do
67− inci (p_hsmodExports exports)
59+ Just hsmodExports' -> do
6860 breakpoint
61+ inci (p_hsmodExports (unLoc hsmodExports'))
62+ breakpoint
6963 txt "where"
7064 newline
7165 newline
72− forM_ (normalizeImports hsmodImports) (located' (p_hsmodImport qualifiedPost))
66+ forM_ (sortImports hsmodImports) (located' p_hsmodImport)
7367 newline
7468 switchLayout (getLoc <$> hsmodDecls) $ do
7569 p_hsDecls Free hsmodDecls
src/Ormolu/Printer/Meat/Pragma.hs+12−22
@@ -8,16 +8,12 @@ module Ormolu.Printer.Meat.Pragma
88 )
99where
1010
11−import Control.Monad
1211import Data.Char (isUpper)
13−import qualified Data.List as L
1412import Data.Maybe (listToMaybe)
13+import qualified Data.Set as S
1514import qualified Data.Text as T
16−import Ormolu.Parser.CommentStream
1715import Ormolu.Parser.Pragma (Pragma (..))
1816import Ormolu.Printer.Combinators
19−import Ormolu.Printer.Comments
20−import SrcLoc
2117
2218-- | Pragma classification.
2319data PragmaTy
@@ -46,31 +42,25 @@ data LanguagePragmaClass
4642 Final
4743 deriving (Eq, Ord)
4844
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))
45+p_pragmas :: [Pragma] -> R ()
46+p_pragmas ps =
47+ let prepare = concatMap $ \case
48+ PragmaLanguage xs ->
49+ let f x = (Language (classifyLanguagePragma x), x)
5650 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
51+ PragmaOptionsGHC x -> [(OptionsGHC, x)]
52+ PragmaOptionsHaddock x -> [(OptionsHaddock, x)]
53+ in mapM_ (uncurry p_pragma) (S.toAscList . S.fromList . prepare $ ps)
6154
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
55+p_pragma :: PragmaTy -> String -> R ()
56+p_pragma ty c = do
6757 txt "{-# "
6858 txt $ case ty of
6959 Language _ -> "LANGUAGE"
7060 OptionsGHC -> "OPTIONS_GHC"
7161 OptionsHaddock -> "OPTIONS_HADDOCK"
7262 space
73− txt (T.pack x)
63+ txt (T.pack c)
7464 txt " #-}"
7565 newline
7666
src/Ormolu/Printer/Meat/Type.hs+61−85
@@ -5,7 +5,6 @@
55-- | Rendering of types.
66module Ormolu.Printer.Meat.Type
77 ( p_hsType,
8− p_hsTypePostDoc,
98 hasDocStrings,
109 p_hsContext,
1110 p_hsTyVarBndr,
@@ -24,23 +23,15 @@ import Ormolu.Printer.Operators
2423import Ormolu.Utils
2524
2625p_hsType :: HsType GhcPs -> R ()
27−p_hsType t = p_hsType' (hasDocStrings t) PipeStyle t
26+p_hsType t = p_hsType' (hasDocStrings t) t
2827
29−p_hsTypePostDoc :: HsType GhcPs -> R ()
30−p_hsTypePostDoc t = p_hsType' (hasDocStrings t) CaretStyle t
31−
32−-- | How to render Haddocks associated with a type.
33−data TypeDocStyle
34− = PipeStyle
35− | CaretStyle
36−
37−p_hsType' :: Bool -> TypeDocStyle -> HsType GhcPs -> R ()
38−p_hsType' multilineArgs docStyle = \case
39− HsForAllTy NoExtField visibility bndrs t -> do
40− p_forallBndrs visibility p_hsTyVarBndr bndrs
28+p_hsType' :: Bool -> HsType GhcPs -> R ()
29+p_hsType' multilineArgs = \case
30+ HsForAllTy NoExt bndrs t -> do
31+ p_forallBndrs p_hsTyVarBndr bndrs
4132 interArgBreak
42− p_hsTypeR (unLoc t)
43− HsQualTy NoExtField qs t -> do
33+ p_hsType' multilineArgs (unLoc t)
34+ HsQualTy NoExt qs t -> do
4435 located qs p_hsContext
4536 space
4637 txt "=>"
@@ -49,7 +40,7 @@ p_hsType' multilineArgs docStyle = \case
4940 HsQualTy {} -> p_hsTypeR (unLoc t)
5041 HsFunTy {} -> p_hsTypeR (unLoc t)
5142 _ -> located t p_hsTypeR
52− HsTyVar NoExtField p n -> do
43+ HsTyVar NoExt p n -> do
5344 case p of
5445 IsPromoted -> do
5546 txt "'"
@@ -58,20 +49,10 @@ p_hsType' multilineArgs docStyle = \case
5849 _ -> return ()
5950 NotPromoted -> return ()
6051 p_rdrName n
61− HsAppTy NoExtField f x -> do
62− let -- In order to format type applications with multiple parameters
63− -- nicer, traverse the AST to gather the function and all the
64− -- parameters together.
65− gatherArgs f' knownArgs =
66− case f' of
67− L _ (HsAppTy _ l r) -> gatherArgs l (r : knownArgs)
68− _ -> (f', knownArgs)
69− (func, args) = gatherArgs f [x]
70− switchLayout (getLoc f : fmap getLoc args) . sitcc $ do
71− located func p_hsType
72− breakpoint
73− inci $
74− sep breakpoint (located' p_hsType) args
52+ HsAppTy NoExt f x -> sitcc $ do
53+ located f p_hsType
54+ breakpoint
55+ inci (located x p_hsType)
7556 HsAppKindTy _ ty kd -> sitcc $ do
7657 -- The first argument is the location of the "@..." part. Not 100% sure,
7758 -- but I think we can ignore it as long as we use 'located' on both the
@@ -81,7 +62,7 @@ p_hsType' multilineArgs docStyle = \case
8162 inci $ do
8263 txt "@"
8364 located kd p_hsType
84− HsFunTy NoExtField x y@(L _ y') -> do
65+ HsFunTy NoExt x y@(L _ y') -> do
8566 located x p_hsType
8667 space
8768 txt "->"
@@ -89,49 +70,44 @@ p_hsType' multilineArgs docStyle = \case
8970 case y' of
9071 HsFunTy {} -> p_hsTypeR y'
9172 _ -> located y p_hsTypeR
92− HsListTy NoExtField t ->
73+ HsListTy NoExt t ->
9374 located t (brackets N . p_hsType)
94− HsTupleTy NoExtField tsort xs ->
75+ HsTupleTy NoExt tsort xs ->
9576 let parens' =
9677 case tsort of
9778 HsUnboxedTuple -> parensHash N
9879 HsBoxedTuple -> parens N
9980 HsConstraintTuple -> parens N
10081 HsBoxedOrConstraintTuple -> parens N
101− in parens' $ sep commaDel (sitcc . located' p_hsType) xs
102− HsSumTy NoExtField xs ->
103− parensHash N $
82+ in parens' . sitcc $
83+ sep (comma >> breakpoint) (sitcc . located' p_hsType) xs
84+ HsSumTy NoExt xs ->
85+ parensHash N . sitcc $
10486 sep (txt "|" >> breakpoint) (sitcc . located' p_hsType) xs
105− HsOpTy NoExtField x op y ->
87+ HsOpTy NoExt x op y ->
10688 sitcc $
10789 let opTree = OpBranch (tyOpTree x) op (tyOpTree y)
10890 in p_tyOpTree (reassociateOpTree Just opTree)
109− HsParTy NoExtField t ->
91+ HsParTy NoExt t ->
11092 parens N (located t p_hsType)
111− HsIParamTy NoExtField n t -> sitcc $ do
93+ HsIParamTy NoExt n t -> sitcc $ do
11294 located n atom
11395 space
11496 txt "::"
11597 breakpoint
11698 inci (located t p_hsType)
117− HsStarTy NoExtField _ -> txt "*"
118− HsKindSig NoExtField t k -> sitcc $ do
99+ HsStarTy NoExt _ -> txt "*"
100+ HsKindSig NoExt t k -> sitcc $ do
119101 located t p_hsType
120− space
102+ space -- FIXME
121103 txt "::"
122− breakpoint
104+ space
123105 inci (located k p_hsType)
124− HsSpliceTy NoExtField splice -> p_hsSplice splice
125− HsDocTy NoExtField t str ->
126− case docStyle of
127− PipeStyle -> do
128− p_hsDocString Pipe True str
129− located t p_hsType
130− CaretStyle -> do
131− located t p_hsType
132− newline
133− p_hsDocString Caret False str
134− HsBangTy NoExtField (HsSrcBang _ u s) t -> do
106+ HsSpliceTy NoExt splice -> p_hsSplice splice
107+ HsDocTy NoExt t str -> do
108+ p_hsDocString Pipe True str
109+ located t p_hsType
110+ HsBangTy NoExt (HsSrcBang _ u s) t -> do
135111 case u of
136112 SrcUnpack -> txt "{-# UNPACK #-}" >> space
137113 SrcNoUnpack -> txt "{-# NOUNPACK #-}" >> space
@@ -141,9 +117,9 @@ p_hsType' multilineArgs docStyle = \case
141117 SrcStrict -> txt "!"
142118 NoSrcStrict -> return ()
143119 located t p_hsType
144− HsRecTy NoExtField fields ->
120+ HsRecTy NoExt fields ->
145121 p_conDeclFields fields
146− HsExplicitListTy NoExtField p xs -> do
122+ HsExplicitListTy NoExt p xs -> do
147123 case p of
148124 IsPromoted -> txt "'"
149125 NotPromoted -> return ()
@@ -153,31 +129,31 @@ p_hsType' multilineArgs docStyle = \case
153129 case (p, xs) of
154130 (IsPromoted, L _ t : _) | isPromoted t -> space
155131 _ -> return ()
156− sep commaDel (sitcc . located' p_hsType) xs
157− HsExplicitTupleTy NoExtField xs -> do
132+ sitcc $ sep (comma >> breakpoint) (sitcc . located' p_hsType) xs
133+ HsExplicitTupleTy NoExt xs -> do
158134 txt "'"
159135 parens N $ do
160136 case xs of
161137 L _ t : _ | isPromoted t -> space
162138 _ -> return ()
163− sep commaDel (located' p_hsType) xs
164− HsTyLit NoExtField t ->
139+ sep (comma >> breakpoint) (located' p_hsType) xs
140+ HsTyLit NoExt t ->
165141 case t of
166142 HsStrTy (SourceText s) _ -> p_stringLit s
167143 a -> atom a
168− HsWildCardTy NoExtField -> txt "_"
144+ HsWildCardTy NoExt -> txt "_"
169145 XHsType (NHsCoreTy t) -> atom t
170146 where
171147 isPromoted = \case
172148 HsTyVar _ IsPromoted _ -> True
173− HsExplicitTupleTy {} -> True
174149 HsExplicitListTy {} -> True
150+ HsExplicitTupleTy {} -> True
175151 _ -> False
176152 interArgBreak =
177153 if multilineArgs
178154 then newline
179155 else breakpoint
180− p_hsTypeR = p_hsType' multilineArgs docStyle
156+ p_hsTypeR = p_hsType' multilineArgs
181157
182158-- | Return 'True' if at least one argument in 'HsType' has a doc string
183159-- attached to it.
@@ -191,54 +167,54 @@ p_hsContext :: HsContext GhcPs -> R ()
191167p_hsContext = \case
192168 [] -> txt "()"
193169 [x] -> located x p_hsType
194− xs -> parens N $ sep commaDel (sitcc . located' p_hsType) xs
170+ xs ->
171+ parens N . sitcc $
172+ sep (comma >> breakpoint) (sitcc . located' p_hsType) xs
195173
196174p_hsTyVarBndr :: HsTyVarBndr GhcPs -> R ()
197175p_hsTyVarBndr = \case
198− UserTyVar NoExtField x ->
176+ UserTyVar NoExt x ->
199177 p_rdrName x
200− KindedTyVar NoExtField l k -> parens N $ do
178+ KindedTyVar NoExt l k -> parens N $ do
201179 located l atom
202180 space
203181 txt "::"
204182 breakpoint
205183 inci (located k p_hsType)
206− XTyVarBndr x -> noExtCon x
184+ XTyVarBndr NoExt -> notImplemented "XTyVarBndr"
207185
208186-- | 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 =
187+p_forallBndrs :: Data a => (a -> R ()) -> [Located a] -> R ()
188+p_forallBndrs _ [] = txt "forall."
189+p_forallBndrs p tyvars =
213190 switchLayout (getLoc <$> tyvars) $ do
214191 txt "forall"
215192 breakpoint
216193 inci $ do
217194 sitcc $ sep breakpoint (sitcc . located' p) tyvars
218− case vis of
219− ForallInvis -> txt "."
220− ForallVis -> space >> txt "->"
195+ txt "."
221196
222197p_conDeclFields :: [LConDeclField GhcPs] -> R ()
223198p_conDeclFields xs =
224− braces N $ sep commaDel (sitcc . located' p_conDeclField) xs
199+ braces N . sitcc $
200+ sep (comma >> breakpoint) (sitcc . located' p_conDeclField) xs
225201
226202p_conDeclField :: ConDeclField GhcPs -> R ()
227203p_conDeclField ConDeclField {..} = do
228204 mapM_ (p_hsDocString Pipe True) cd_fld_doc
229205 sitcc $
230206 sep
231− commaDel
207+ (comma >> breakpoint)
232208 (located' (p_rdrName . rdrNameFieldOcc))
233209 cd_fld_names
234210 space
235211 txt "::"
236212 breakpoint
237213 sitcc . inci $ p_hsType (unLoc cd_fld_type)
238−p_conDeclField (XConDeclField x) = noExtCon x
214+p_conDeclField (XConDeclField NoExt) = notImplemented "XConDeclField"
239215
240216tyOpTree :: LHsType GhcPs -> OpTree (LHsType GhcPs) (Located RdrName)
241−tyOpTree (L _ (HsOpTy NoExtField l op r)) =
217+tyOpTree (L _ (HsOpTy NoExt l op r)) =
242218 OpBranch (tyOpTree l) op (tyOpTree r)
243219tyOpTree n = OpNode n
244220
@@ -259,17 +235,17 @@ p_tyOpTree (OpBranch l op r) = do
259235tyVarsToTypes :: LHsQTyVars GhcPs -> [LHsType GhcPs]
260236tyVarsToTypes = \case
261237 HsQTvs {..} -> fmap tyVarToType <$> hsq_explicit
262− XLHsQTyVars x -> noExtCon x
238+ XLHsQTyVars {} -> notImplemented "XLHsQTyVars"
263239
264240tyVarToType :: HsTyVarBndr GhcPs -> HsType GhcPs
265241tyVarToType = \case
266− UserTyVar NoExtField tvar -> HsTyVar NoExtField NotPromoted tvar
267− KindedTyVar NoExtField tvar kind ->
242+ UserTyVar NoExt tvar -> HsTyVar NoExt NotPromoted tvar
243+ KindedTyVar NoExt tvar kind ->
268244 -- Note: we always add parentheses because for whatever reason GHC does
269245 -- not use HsParTy for left-hand sides of declarations. Please see
270246 -- <https://gitlab.haskell.org/ghc/ghc/issues/17404>. This is fine as
271247 -- long as 'tyVarToType' does not get applied to right-hand sides of
272248 -- declarations.
273− HsParTy NoExtField . noLoc $
274− HsKindSig NoExtField (noLoc (HsTyVar NoExtField NotPromoted tvar)) kind
275− XTyVarBndr x -> noExtCon x
249+ HsParTy NoExt $ noLoc $
250+ HsKindSig NoExt (noLoc (HsTyVar NoExt NotPromoted tvar)) kind
251+ XTyVarBndr {} -> notImplemented "XTyVarBndr"
src/Ormolu/Printer/Operators.hs+66−50
@@ -10,14 +10,16 @@ module Ormolu.Printer.Operators
1010 )
1111where
1212
13+import BasicTypes (Fixity (..), SourceText (NoSourceText), compareFixity, defaultFixity)
1314import Data.Function (on)
14−import qualified Data.List as L
15−import Data.Map.Strict (Map)
16−import qualified Data.Map.Strict as M
15+import Data.List
1716import Data.Maybe (fromMaybe, mapMaybe)
17+import Data.Ord (Down (Down), comparing)
1818import GHC
19−import OccName (occNameString)
19+import OccName (mkVarOcc)
2020import Ormolu.Utils (unSrcSpan)
21+import RdrName (mkRdrUnqual)
22+import SrcLoc (combineSrcSpans)
2123
2224-- | Intermediate representation of operator trees. It has two type
2325-- parameters: @ty@ is the type of sub-expressions, while @op@ is the type
@@ -57,7 +59,7 @@ reassociateOpTree getOpName opTree =
5759reassociateOpTreeWith ::
5860 forall ty op.
5961 -- | Fixity map for operators
60− Map String Fixity ->
62+ [(RdrName, Fixity)] ->
6163 -- | How to get the name of an operator
6264 (op -> Maybe RdrName) ->
6365 -- | Original 'OpTree'
@@ -68,13 +70,13 @@ reassociateOpTreeWith fixityMap getOpName = go
6870 where
6971 fixityOf :: op -> Fixity
7072 fixityOf op = fromMaybe defaultFixity $ do
71− s <- occNameString . rdrNameOcc <$> getOpName op
72− M.lookup s fixityMap
73+ opName <- getOpName op
74+ lookup opName fixityMap
7375 -- Here, left branch is already associated and the root alongside with
7476 -- the right branch is right-associated. This function picks up one item
7577 -- from the right and inserts it correctly to the left.
7678 --
77− -- Also, we are using the 'compareFixity' function which tells if the
79+ -- Also, we are using the 'compareFixity' function which returns if the
7880 -- expression should associate to right.
7981 go :: OpTree ty op -> OpTree ty op
8082 -- base cases
@@ -94,16 +96,6 @@ reassociateOpTreeWith fixityMap getOpName = go
9496 then go $ OpBranch (OpBranch l op (go $ OpBranch r op' l')) op'' r'
9597 else go $ OpBranch (OpBranch (OpBranch l op r) op' l') op'' r'
9698
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−
10799-- | Build a map of inferred 'Fixity's from an 'OpTree'.
108100buildFixityMap ::
109101 forall ty op.
@@ -112,26 +104,23 @@ buildFixityMap ::
112104 -- | Operator tree
113105 OpTree (Located ty) (Located op) ->
114106 -- | Fixity map
115− Map String Fixity
107+ [(RdrName, Fixity)]
116108buildFixityMap 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
109+ concatMap (\(i, ns) -> map (\(n, _) -> (n, fixity i InfixL)) ns)
110+ . zip [0 ..]
111+ . groupBy (doubleWithinEps 0.00001 `on` snd)
112+ . (overrides ++)
113+ . modeScores
123114 $ score opTree
124115 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)]
116+ -- Add a special case for ($), since it is pretty unlikely for someone
117+ -- to override it.
118+ overrides :: [(RdrName, Double)]
119+ overrides =
120+ [ (mkRdrUnqual $ mkVarOcc "$", -1)
121+ ]
122+ -- Assign scores to operators based on their location in the source.
123+ score :: OpTree (Located ty) (Located op) -> [(RdrName, Double)]
135124 score (OpNode _) = []
136125 score (OpBranch l o r) = fromMaybe (score r) $ do
137126 -- If we fail to get any of these, 'defaultFixity' will be used by
@@ -141,27 +130,48 @@ buildFixityMap getOpName opTree =
141130 oe <- srcSpanEndLine <$> unSrcSpan (getLoc o) -- operator end
142131 rb <- srcSpanStartLine <$> unSrcSpan (opTreeLoc r) -- right begin
143132 oc <- srcSpanStartCol <$> unSrcSpan (getLoc o) -- operator column
144− opName <- occNameString . rdrNameOcc <$> getOpName (unLoc o)
133+ opName <- getOpName (unLoc o)
145134 let s
146− | le < ob = AtBeginning oc
147− | oe < rb = AtEnd
148− | otherwise = InBetween
135+ | le < ob =
136+ -- if the operator is in the beginning of a line, assign
137+ -- a score relative to its column within range [0, 1).
138+ fromIntegral oc / fromIntegral (maxCol + 1)
139+ | oe < rb =
140+ -- if the operator is in the end of the line, assign the
141+ -- score 1.
142+ 1
143+ | otherwise =
144+ 2 -- otherwise, assign a high score.
149145 return $ (opName, s) : score r
150− selectScores :: [(String, Score)] -> [(String, Score)]
151− selectScores =
152− L.sortOn snd
146+ -- Pick the most common score per 'RdrName'.
147+ modeScores :: [(RdrName, Double)] -> [(RdrName, Double)]
148+ modeScores =
149+ sortOn snd
153150 . mapMaybe
154151 ( \case
155152 [] -> Nothing
156− xs@((n, _) : _) -> Just (n, selectScore $ map snd xs)
153+ xs@((n, _) : _) -> Just (n, mode $ map snd xs)
157154 )
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'
155+ . groupBy ((==) `on` fst)
156+ . sort
157+ -- Return the most common number, leaning to the smaller
158+ -- one in case of a tie.
159+ mode :: [Double] -> Double
160+ mode =
161+ head
162+ . minimumBy (comparing (Down . length))
163+ . groupBy (doubleWithinEps 0.0001)
164+ . sort
165+ -- The start column of the rightmost operator.
166+ maxCol = go opTree
167+ where
168+ go (OpNode (L _ _)) = 0
169+ go (OpBranch l (L o _) r) =
170+ maximum
171+ [ go l,
172+ maybe 0 srcSpanStartCol (unSrcSpan o),
173+ go r
174+ ]
165175
166176----------------------------------------------------------------------------
167177-- Helpers
@@ -175,3 +185,9 @@ normalizeOpTree (OpBranch (OpNode l) lop r) =
175185 OpBranch (OpNode l) lop (normalizeOpTree r)
176186normalizeOpTree (OpBranch (OpBranch l' lop' r') lop r) =
177187 normalizeOpTree (OpBranch l' lop' (OpBranch r' lop r))
188+
189+fixity :: Int -> FixityDirection -> Fixity
190+fixity = Fixity NoSourceText
191+
192+doubleWithinEps :: Double -> Double -> Double -> Bool
193+doubleWithinEps eps a b = abs (a - b) < eps
src/Ormolu/Processing/Common.hsdeleted−27
@@ -1,27 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−
3−-- | Common definitions for pre- and post- processing.
4−module Ormolu.Processing.Common
5− ( OrmoluState (..),
6− startDisabling,
7− endDisabling,
8− )
9−where
10−
11−import Data.String (IsString (..))
12−
13−-- | Ormolu state.
14−data OrmoluState
15− = -- | Enabled
16− OrmoluEnabled
17− | -- | Disabled
18− OrmoluDisabled
19− deriving (Eq, Show)
20−
21−-- | Marker for the beginning of the region where Ormolu should be disabled.
22−startDisabling :: IsString s => s
23−startDisabling = "{- ORMOLU_DISABLE_START"
24−
25−-- | Marker for the end of the region where Ormolu should be disabled.
26−endDisabling :: IsString s => s
27−endDisabling = "ORMOLU_DISABLE_END -}"
src/Ormolu/Processing/Cpp.hsdeleted−70
@@ -1,70 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−
3−-- | Support for CPP.
4−module Ormolu.Processing.Cpp
5− ( State (..),
6− processLine,
7− unmaskLine,
8− )
9−where
10−
11−import Control.Monad
12−import Data.Char (isSpace)
13−import qualified Data.List as L
14−import Data.Maybe (isJust)
15−import Data.String
16−import Data.Text (Text)
17−import qualified Data.Text as T
18−
19−-- | State of the CPP processor.
20−data State
21− = -- | Outside of CPP directives
22− Outside
23− | -- | In a conditional expression
24− InConditional
25− | -- | In a continuation (after @\\@)
26− InContinuation
27− deriving (Eq, Show)
28−
29−-- | Automatically mask the line when needed and update the 'State'.
30−processLine :: String -> State -> (String, State)
31−processLine line state
32− | for "define " = (masked, state')
33− | for "include " = (masked, state')
34− | for "undef " = (masked, state')
35− | for "ifdef " = (masked, InConditional)
36− | for "ifndef " = (masked, InConditional)
37− | for "if " = (masked, InConditional)
38− | for "else" = (masked, InConditional)
39− | for "elif" = (masked, InConditional)
40− | for "endif" = (masked, state')
41− | otherwise =
42− case state of
43− Outside -> (line, Outside)
44− InConditional -> (masked, InConditional)
45− InContinuation -> (masked, state')
46− where
47− for directive = isJust $ do
48− s <- dropWhile isSpace <$> L.stripPrefix "#" line
49− void (L.stripPrefix directive s)
50− masked = maskLine line
51− state' =
52− if "\\" `L.isSuffixOf` line
53− then InContinuation
54− else Outside
55−
56−-- | Mask the given line.
57−maskLine :: String -> String
58−maskLine x = maskPrefix ++ x
59−
60−-- | If the given line is masked, unmask it. Otherwise return the line
61−-- unchanged.
62−unmaskLine :: Text -> Text
63−unmaskLine x =
64− case T.stripPrefix maskPrefix (T.stripStart x) of
65− Nothing -> x
66− Just x' -> x'
67−
68−-- | Mask prefix for CPP.
69−maskPrefix :: IsString s => s
70−maskPrefix = "-- ORMOLU_CPP_MASK"
src/Ormolu/Processing/Postprocess.hsdeleted−31
@@ -1,31 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE ViewPatterns #-}
3−
4−-- | Postprocessing for the results of printing.
5−module Ormolu.Processing.Postprocess
6− ( postprocess,
7− )
8−where
9−
10−import Data.Text (Text)
11−import qualified Data.Text as T
12−import Ormolu.Processing.Common
13−import qualified Ormolu.Processing.Cpp as Cpp
14−
15−-- | Postprocess output of the formatter.
16−postprocess ::
17− -- | Desired indentation level
18− Int ->
19− -- | Input to process
20− Text ->
21− Text
22−postprocess indent =
23− T.unlines
24− . fmap indentLine
25− . fmap Cpp.unmaskLine
26− . filter (not . magicComment)
27− . T.lines
28− where
29− magicComment (T.stripStart -> x) =
30− x == startDisabling || x == endDisabling
31− indentLine x = T.replicate indent " " <> x
src/Ormolu/Processing/Preprocess.hsdeleted−149
@@ -1,149 +0,0 @@
1−{-# LANGUAGE BangPatterns #-}
2−{-# LANGUAGE LambdaCase #-}
3−{-# LANGUAGE RecordWildCards #-}
4−
5−-- | Preprocessing for input source code.
6−module Ormolu.Processing.Preprocess
7− ( preprocess,
8− )
9−where
10−
11−import Control.Monad
12−import Data.Char (isSpace)
13−import qualified Data.List as L
14−import Data.Maybe (isJust, maybeToList)
15−import FastString
16−import Ormolu.Config (RegionDeltas (..))
17−import Ormolu.Parser.Shebang (isShebang)
18−import Ormolu.Processing.Common
19−import qualified Ormolu.Processing.Cpp as Cpp
20−import SrcLoc
21−
22−-- | Transform given input possibly returning comments extracted from it.
23−-- This handles LINE pragmas, CPP, shebangs, and the magic comments for
24−-- enabling\/disabling of Ormolu.
25−preprocess ::
26− -- | File name, just to use in the spans
27− FilePath ->
28− -- | Input to process
29− String ->
30− -- | Region deltas
31− RegionDeltas ->
32− -- | Literal prefix, pre-processed input, literal suffix, extra comments
33− (String, String, String, [Located String])
34−preprocess path input RegionDeltas {..} =
35− go 1 OrmoluEnabled Cpp.Outside id id regionLines
36− where
37− (prefixLines, otherLines) = splitAt regionPrefixLength (lines input)
38− (regionLines, suffixLines) =
39− let regionLength = length otherLines - regionSuffixLength
40− in splitAt regionLength otherLines
41− go !n ormoluState cppState inputSoFar csSoFar = \case
42− [] ->
43− let input' = unlines (inputSoFar [])
44− in ( unlines prefixLines,
45− case ormoluState of
46− OrmoluEnabled -> input'
47− OrmoluDisabled -> input' ++ endDisabling,
48− unlines suffixLines,
49− csSoFar []
50− )
51− (x : xs) ->
52− let (x', ormoluState', cppState', cs) =
53− processLine path n ormoluState cppState x
54− in go
55− (n + 1)
56− ormoluState'
57− cppState'
58− (inputSoFar . (x' :))
59− (csSoFar . (maybeToList cs ++))
60− xs
61−
62−-- | Transform a given line possibly returning a comment extracted from it.
63−processLine ::
64− -- | File name, just to use in the spans
65− FilePath ->
66− -- | Line number of this line
67− Int ->
68− -- | Whether Ormolu is currently enabled
69− OrmoluState ->
70− -- | CPP state
71− Cpp.State ->
72− -- | The actual line
73− String ->
74− -- | Adjusted line and possibly a comment extracted from it
75− (String, OrmoluState, Cpp.State, Maybe (Located String))
76−processLine path n ormoluState Cpp.Outside line
77− | "{-# LINE" `L.isPrefixOf` line =
78− let (pragma, res) = getPragma line
79− size = length pragma
80− ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (size + 1))
81− in (res, ormoluState, Cpp.Outside, Just (L ss pragma))
82− | isOrmoluEnable line =
83− case ormoluState of
84− OrmoluEnabled ->
85− (enableMarker, OrmoluEnabled, Cpp.Outside, Nothing)
86− OrmoluDisabled ->
87− (endDisabling ++ enableMarker, OrmoluEnabled, Cpp.Outside, Nothing)
88− | isOrmoluDisable line =
89− case ormoluState of
90− OrmoluEnabled ->
91− (disableMarker ++ startDisabling, OrmoluDisabled, Cpp.Outside, Nothing)
92− OrmoluDisabled ->
93− (disableMarker, OrmoluDisabled, Cpp.Outside, Nothing)
94− | isShebang line =
95− let ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (length line))
96− in ("", ormoluState, Cpp.Outside, Just (L ss line))
97− | otherwise =
98− let (line', cppState') = Cpp.processLine line Cpp.Outside
99− in (line', ormoluState, cppState', Nothing)
100− where
101− mkSrcLoc' = mkSrcLoc (mkFastString path) n
102−processLine _ _ ormoluState cppState line =
103− let (line', cppState') = Cpp.processLine line cppState
104− in (line', ormoluState, cppState', Nothing)
105−
106−-- | Take a line pragma and output its replacement (where line pragma is
107−-- replaced with spaces) and the contents of the pragma itself.
108−getPragma ::
109− -- | Pragma line to analyze
110− String ->
111− -- | Contents of the pragma and its replacement line
112− (String, String)
113−getPragma [] = error "Ormolu.Preprocess.getPragma: input must not be empty"
114−getPragma s@(x : xs)
115− | "#-}" `L.isPrefixOf` s = ("#-}", " " ++ drop 3 s)
116− | otherwise =
117− let (prag, remline) = getPragma xs
118− in (x : prag, ' ' : remline)
119−
120−-- | Canonical enable marker.
121−enableMarker :: String
122−enableMarker = "{- ORMOLU_ENABLE -}"
123−
124−-- | Canonical disable marker.
125−disableMarker :: String
126−disableMarker = "{- ORMOLU_DISABLE -}"
127−
128−-- | Return 'True' if the given string is an enabling marker.
129−isOrmoluEnable :: String -> Bool
130−isOrmoluEnable = magicComment "ORMOLU_ENABLE"
131−
132−-- | Return 'True' if the given string is a disabling marker.
133−isOrmoluDisable :: String -> Bool
134−isOrmoluDisable = magicComment "ORMOLU_DISABLE"
135−
136−-- | Construct a function for whitespace-insensitive matching of string.
137−magicComment ::
138− -- | What to expect
139− String ->
140− -- | String to test
141− String ->
142− -- | Whether or not the two strings watch
143− Bool
144−magicComment expected s0 = isJust $ do
145− let trim = dropWhile isSpace
146− s1 <- trim <$> L.stripPrefix "{-" (trim s0)
147− s2 <- trim <$> L.stripPrefix expected s1
148− s3 <- L.stripPrefix "-}" s2
149− guard (all isSpace s3)
src/Ormolu/Utils.hs+16−74
@@ -1,66 +1,45 @@
11{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE ViewPatterns #-}
43
54-- | Random utilities used by the code.
65module Ormolu.Utils
7− ( RelativePos (..),
8− attachRelativePos,
9− combineSrcSpans',
6+ ( combineSrcSpans',
7+ isModule,
108 notImplemented,
119 showOutputable,
1210 splitDocString,
1311 typeArgToType,
1412 unSrcSpan,
15− incSpanLine,
1613 separatedByBlank,
17− separatedByBlankNE,
18− onTheSameLine,
19− removeIndentation,
2014 )
2115where
2216
23−import Data.Char (isSpace)
17+import Data.Data (Data, showConstr, toConstr)
2418import Data.List (dropWhileEnd)
25−import Data.List.NonEmpty (NonEmpty (..))
2619import qualified Data.List.NonEmpty as NE
20+import Data.List.NonEmpty (NonEmpty (..))
2721import Data.Maybe (fromMaybe)
2822import Data.Text (Text)
2923import qualified Data.Text as T
3024import GHC
31−import GHC.DynFlags (baseDynFlags)
25+import HsDoc (HsDocString, unpackHDS)
3226import qualified Outputable as GHC
3327
34−-- | Relative positions in a list.
35−data RelativePos
36− = SinglePos
37− | FirstPos
38− | MiddlePos
39− | LastPos
40− deriving (Eq, Show)
41−
42−-- | Attach 'RelativePos'es to elements of a given list.
43−attachRelativePos :: [a] -> [(RelativePos, a)]
44−attachRelativePos = \case
45− [] -> []
46− [x] -> [(SinglePos, x)]
47− (x : xs) -> (FirstPos, x) : markLast xs
48− where
49− markLast [] = []
50− markLast [x] = [(LastPos, x)]
51− markLast (x : xs) = (MiddlePos, x) : markLast xs
52−
5328-- | Combine all source spans from the given list.
5429combineSrcSpans' :: NonEmpty SrcSpan -> SrcSpan
5530combineSrcSpans' (x :| xs) = foldr combineSrcSpans x xs
5631
32+-- | Return 'True' if given element of AST is module.
33+isModule :: Data a => a -> Bool
34+isModule x = showConstr (toConstr x) == "HsModule"
35+
5736-- | Placeholder for things that are not yet implemented.
5837notImplemented :: String -> a
5938notImplemented msg = error $ "not implemented yet: " ++ msg
6039
6140-- | Pretty-print an 'GHC.Outputable' thing.
6241showOutputable :: GHC.Outputable o => o -> String
63−showOutputable = GHC.showSDoc baseDynFlags . GHC.ppr
42+showOutputable = GHC.showSDocUnsafe . GHC.ppr
6443
6544-- | Split and normalize a doc string. The result is a list of lines that
6645-- make up the comment.
@@ -99,57 +78,20 @@ splitDocString docStr =
9978 then dropSpace <$> xs
10079 else xs
10180
102−-- | Get 'LHsType' out of 'LHsTypeArg'.
10381typeArgToType :: LHsTypeArg p -> LHsType p
10482typeArgToType = \case
10583 HsValArg tm -> tm
10684 HsTypeArg _ ty -> ty
10785 HsArgPar _ -> notImplemented "HsArgPar"
10886
109−-- | Get 'RealSrcSpan' out of 'SrcSpan' if the span is “helpful”.
11087unSrcSpan :: 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
88+unSrcSpan (RealSrcSpan r) = Just r
89+unSrcSpan (UnhelpfulSpan _) = Nothing
12890
129−-- | Do two declarations have a blank between them?
130−separatedByBlank :: (a -> SrcSpan) -> a -> a -> Bool
91+-- | Do two declaration groups have a blank between them?
92+separatedByBlank :: (a -> SrcSpan) -> NonEmpty a -> NonEmpty a -> Bool
13193separatedByBlank loc a b =
13294 fromMaybe False $ do
133− endA <- srcSpanEndLine <$> unSrcSpan (loc a)
134− startB <- srcSpanStartLine <$> unSrcSpan (loc b)
95+ endA <- srcSpanEndLine <$> unSrcSpan (loc $ NE.last a)
96+ startB <- srcSpanStartLine <$> unSrcSpan (loc $ NE.head b)
13597 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/PrinterSpec.hs+10−7
@@ -1,6 +1,9 @@
11{-# LANGUAGE TemplateHaskell #-}
22
3−module Ormolu.PrinterSpec (spec) where
3+module Ormolu.PrinterSpec
4+ ( spec,
5+ )
6+where
47
58import Control.Exception
69import Control.Monad
@@ -12,7 +15,7 @@ import qualified Data.Text.IO as T
1215import Ormolu
1316import Path
1417import Path.IO
15−import qualified System.FilePath as F
18+import System.FilePath (addExtension, dropExtensions, splitExtensions)
1619import Test.Hspec
1720
1821spec :: Spec
@@ -50,19 +53,19 @@ locateExamples =
5053isInput :: Path Rel File -> Bool
5154isInput path =
5255 let s = fromRelFile path
53− (s', exts) = F.splitExtensions s
56+ (s', exts) = splitExtensions s
5457 in exts == ".hs" && not ("-out" `isSuffixOf` s')
5558
5659-- | For given path of input file return expected name of output.
5760deriveOutput :: Path Rel File -> IO (Path Rel File)
5861deriveOutput path =
5962 parseRelFile $
60− F.addExtension (F.dropExtensions (fromRelFile path) ++ "-out") "hs"
63+ addExtension (dropExtensions (fromRelFile path) ++ "-out") "hs"
6164
6265-- | A version of 'shouldBe' that is specialized to comparing 'Text' values.
6366-- It also prints multi-line snippets in a more readable form.
6467shouldMatch :: Bool -> Text -> Text -> Expectation
65−shouldMatch idempotenceTest actual expected =
68+shouldMatch idempotencyTest actual expected =
6669 when (actual /= expected) . expectationFailure $
6770 unlines
6871 [ ">>>>>>>>>>>>>>>>>>>>>> expected (" ++ pass ++ "):",
@@ -72,8 +75,8 @@ shouldMatch idempotenceTest actual expected =
7275 ]
7376 where
7477 pass =
75− if idempotenceTest
76− then "idempotence pass"
78+ if idempotencyTest
79+ then "idempotency pass"
7780 else "first pass"
7881
7982examplesDir :: Path Rel Dir