on master help sign in
748 files changed+12510−4139
since splitsnapshots
unifiedsplit
.buildkite/pipeline.yml+18 .circleci/config.yml−44 .github/workflows/binaries.yml+39 .github/workflows/build.sh+7 .gitignore+1 CHANGELOG.md+231 CONTRIBUTING.md+28−34 DESIGN.md+26−50 EXAMPLES.md−296 LICENSE.md+1−1 README.md+119−28 app/Main.hs+160−92 data/examples/declaration/annotation/annotation-out.hs+13−3 data/examples/declaration/annotation/annotation.hs+8−2 data/examples/declaration/class/associated-data1-out.hs+13 data/examples/declaration/class/associated-data1.hs+12 data/examples/declaration/class/associated-data-out.hs → data/examples/declaration/class/associated-data2-out.hs+2−10 data/examples/declaration/class/associated-data.hs → data/examples/declaration/class/associated-data2.hs+2−11 data/examples/declaration/class/associated-type-defaults-out.hs+4−2 data/examples/declaration/class/associated-types1-out.hs+13 data/examples/declaration/class/associated-types1.hs+12 data/examples/declaration/class/associated-types-out.hs → data/examples/declaration/class/associated-types2-out.hs+2−10 data/examples/declaration/class/associated-types.hs → data/examples/declaration/class/associated-types2.hs+2−11 data/examples/declaration/class/default-implementations-comments-out.hs+26 data/examples/declaration/class/default-implementations-comments.hs+22 data/examples/declaration/class/default-implementations-out.hs+5−24 data/examples/declaration/class/default-implementations.hs+2−21 data/examples/declaration/class/default-signatures-out.hs+12−17 data/examples/declaration/class/default-signatures-simple-out.hs+8 data/examples/declaration/class/default-signatures-simple.hs+8 data/examples/declaration/class/default-signatures.hs+2−7 data/examples/declaration/class/dependency-super-classes-out.hs+15−10 data/examples/declaration/class/dependency-super-classes.hs+2 data/examples/declaration/class/empty-classes-out.hs+2 data/examples/declaration/class/empty-classes.hs+2 data/examples/declaration/class/functional-dependencies-out.hs+11−8 data/examples/declaration/class/functional-dependencies.hs+2 data/examples/declaration/class/multi-parameters-out.hs−29 data/examples/declaration/class/multi-parameters1-out.hs+15 data/examples/declaration/class/multi-parameters1.hs+18 data/examples/declaration/class/multi-parameters2-out.hs+19 data/examples/declaration/class/multi-parameters.hs → data/examples/declaration/class/multi-parameters2.hs+2−16 data/examples/declaration/class/newlines-after-where-out.hs+5 data/examples/declaration/class/newlines-after-where.hs+7 data/examples/declaration/class/newlines-and-default-decls-out.hs+11 data/examples/declaration/class/newlines-and-default-decls.hs+13 data/examples/declaration/class/newlines-and-haddocks-out.hs+23 data/examples/declaration/class/newlines-and-haddocks.hs+19 data/examples/declaration/class/newlines-between-methods-out.hs+17 data/examples/declaration/class/newlines-between-methods.hs+15 data/examples/declaration/class/poly-kinded-classes-out.hs+6−4 data/examples/declaration/class/single-parameters-out.hs+14−10 data/examples/declaration/class/single-parameters.hs+2 data/examples/declaration/class/super-classes-out.hs+9−7 data/examples/declaration/class/type-operators-out.hs−29 data/examples/declaration/class/type-operators1-out.hs+21 data/examples/declaration/class/type-operators.hs → data/examples/declaration/class/type-operators1.hs−13 data/examples/declaration/class/type-operators2-out.hs+16 data/examples/declaration/class/type-operators2.hs+16 data/examples/declaration/class/type-operators3-out.hs+10 data/examples/declaration/class/type-operators3.hs+7 data/examples/declaration/data/deriving-out.hs+2 data/examples/declaration/data/deriving-strategies-out.hs+7−5 data/examples/declaration/data/deriving-strategies.hs+2 data/examples/declaration/data/deriving.hs+2 data/examples/declaration/data/empty-out.hs+1 data/examples/declaration/data/existential-multiline-out.hs+13 data/examples/declaration/data/existential-multiline.hs+7 data/examples/declaration/data/existential-out.hs+3 data/examples/declaration/data/existential.hs+2 data/examples/declaration/data/fat-multiline-out.hs+6−4 data/examples/declaration/data/fat-multiline.hs+2 data/examples/declaration/data/field-layout/gadt-out.hs+11 data/examples/declaration/data/field-layout/gadt.hs+10 data/examples/declaration/data/field-layout/record-out.hs+12 data/examples/declaration/data/field-layout/record.hs+11 data/examples/declaration/data/field-layout/variants-out.hs+10 data/examples/declaration/data/field-layout/variants.hs+10 data/examples/declaration/data/gadt-syntax-out.hs+3−3 data/examples/declaration/data/gadt-syntax.hs+1−1 data/examples/declaration/data/gadt/multiline-out.hs+17−13 data/examples/declaration/data/gadt/multiline-where-out.hs+7 data/examples/declaration/data/gadt/multiline-where.hs+6 data/examples/declaration/data/gadt/multiline.hs+2 data/examples/declaration/data/gadt/multiple-declaration-out.hs+15 data/examples/declaration/data/gadt/multiple-declaration.hs+11 data/examples/declaration/data/gadt/record-out.hs+11−8 data/examples/declaration/data/gadt/record.hs+4−1 data/examples/declaration/data/gadt/simple-out.hs+12−2 data/examples/declaration/data/gadt/simple.hs+2 data/examples/declaration/data/gadt/strictness-out.hs+2−1 data/examples/declaration/data/gadt/strictness.hs+2−1 data/examples/declaration/data/kind-annotations-out.hs+11 data/examples/declaration/data/kind-annotations.hs+10 data/examples/declaration/data/multiline-arg-parens-out.hs+4−2 data/examples/declaration/data/multiline-arg-parens.hs+2 data/examples/declaration/data/multiline-names-out.hs+29 data/examples/declaration/data/multiline-names.hs+23 data/examples/declaration/data/multiline-out.hs+8−3 data/examples/declaration/data/multiline.hs+2 data/examples/declaration/data/newtype-out.hs+2 data/examples/declaration/data/newtype.hs+2 data/examples/declaration/data/operators-out.hs+12 data/examples/declaration/data/operators.hs+12 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+21−16 data/examples/declaration/data/record-singleline-out.hs+2 data/examples/declaration/data/record-singleline.hs+2 data/examples/declaration/data/record.hs+2 data/examples/declaration/data/simple-broken-out.hs+5−4 data/examples/declaration/data/simple-broken.hs+2 data/examples/declaration/data/simple-out.hs+2 data/examples/declaration/data/simple.hs+2 data/examples/declaration/data/strictness-out.hs+5−1 data/examples/declaration/data/strictness.hs+5−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/default/default-out.hs+3−3 data/examples/declaration/deriving/multiline-out.hs−20 data/examples/declaration/deriving/multiline.hs−17 data/examples/declaration/deriving/overlapping-out.hs+19 data/examples/declaration/deriving/overlapping.hs+17 data/examples/declaration/foreign/foreign-export-out.hs+2−1 data/examples/declaration/foreign/foreign-import-out.hs+11−10 data/examples/declaration/instance/associated-data-out.hs+5−3 data/examples/declaration/instance/associated-data.hs+1 data/examples/declaration/instance/associated-types-out.hs+3−2 data/examples/declaration/instance/associated-types.hs+2 data/examples/declaration/instance/contexts-comments-out.hs+17 data/examples/declaration/instance/contexts-comments.hs+18 data/examples/declaration/instance/contexts-out.hs+16−7 data/examples/declaration/instance/contexts.hs+7 data/examples/declaration/instance/data-family-instances-gadt-out.hs+13 data/examples/declaration/instance/data-family-instances-gadt.hs+10 data/examples/declaration/instance/data-family-instances-newtype-out.hs+6 data/examples/declaration/instance/data-family-instances-newtype.hs+6 data/examples/declaration/instance/data-family-instances-out.hs+8−19 data/examples/declaration/instance/data-family-instances.hs−12 data/examples/declaration/instance/instance-sigs-multiple-out.hs+10 data/examples/declaration/instance/instance-sigs-multiple.hs+10 data/examples/declaration/instance/instance-sigs-out.hs+5−13 data/examples/declaration/instance/instance-sigs.hs−9 data/examples/declaration/instance/multi-parameter-out.hs+1−2 data/examples/declaration/instance/newlines-after-where-out.hs+5 data/examples/declaration/instance/newlines-after-where.hs+7 data/examples/declaration/instance/newlines-between-methods-out.hs+18 data/examples/declaration/instance/newlines-between-methods.hs+16 data/examples/declaration/instance/overlappable-instances-out.hs+6−3 data/examples/declaration/instance/overlappable-instances.hs+3−1 data/examples/declaration/instance/single-parameter-out.hs+6−4 data/examples/declaration/instance/single-parameter.hs+2 data/examples/declaration/instance/type-family-instances-out.hs+5−4 data/examples/declaration/rewrite-rule/basic1-out.hs+19 data/examples/declaration/rewrite-rule/basic1.hs+17 data/examples/declaration/rewrite-rule/basic2-out.hs+16 data/examples/declaration/rewrite-rule/basic2.hs+16 data/examples/declaration/rewrite-rule/empty-out.hs+3 data/examples/declaration/rewrite-rule/empty.hs+2 data/examples/declaration/rewrite-rule/forall-0-out.hs+9 data/examples/declaration/rewrite-rule/forall-0.hs+8 data/examples/declaration/rewrite-rule/forall-1-out.hs+23 data/examples/declaration/rewrite-rule/forall-1.hs+17 data/examples/declaration/rewrite-rule/phase-out.hs+23 data/examples/declaration/rewrite-rule/phase.hs+19 data/examples/declaration/rewrite-rule/prelude1-out.hs+18 data/examples/declaration/rewrite-rule/prelude1.hs+17 data/examples/declaration/rewrite-rule/prelude2-out.hs+31 data/examples/declaration/rewrite-rule/prelude2.hs+29 data/examples/declaration/rewrite-rule/prelude3-out.hs+10 data/examples/declaration/rewrite-rule/prelude3.hs+10 data/examples/declaration/rewrite-rule/prelude4-out.hs+7 data/examples/declaration/rewrite-rule/prelude4.hs+9 data/examples/declaration/rewrite-rule/type-signature-out.hs+17 data/examples/declaration/rewrite-rule/type-signature.hs+12 data/examples/declaration/role-annotation/multi-line-out.hs+15 data/examples/declaration/role-annotation/multi-line.hs+15 data/examples/declaration/role-annotation/simple-out.hs → data/examples/declaration/role-annotation/single-line-out.hs+2−17 data/examples/declaration/role-annotation/simple.hs → data/examples/declaration/role-annotation/single-line.hs−16 data/examples/declaration/signature/complete/complete-out.hs+4−4 data/examples/declaration/signature/inline/conlike-out.hs+7 data/examples/declaration/signature/inline/conlike.hs+7 data/examples/declaration/signature/inline/inline-out.hs+4 data/examples/declaration/signature/inline/inline.hs+5 data/examples/declaration/signature/minimal/minimal-out.hs+5−3 data/examples/declaration/signature/pattern/multiline-out.hs+18−4 data/examples/declaration/signature/pattern/multiline.hs+10 data/examples/declaration/signature/pattern/single-line-out.hs+3 data/examples/declaration/signature/pattern/single-line.hs+2 data/examples/declaration/signature/specialize/specialize-out.hs+14−5 data/examples/declaration/signature/specialize/specialize.hs+10−2 data/examples/declaration/signature/standalone-kind-out.hs+13 data/examples/declaration/signature/standalone-kind.hs+13 data/examples/declaration/signature/type/arguments-out.hs+15−13 data/examples/declaration/signature/type/context-multi-line-out.hs+10−10 data/examples/declaration/signature/type/context-single-line-out.hs+7−7 data/examples/declaration/signature/type/infix-promoted-type-constructor-out.hs+2−3 data/examples/declaration/signature/type/long-function-name-out.hs+6−6 data/examples/declaration/signature/type/long-multiline-applications-out.hs+16−15 data/examples/declaration/signature/type/long-multiline-applications.hs+2−1 data/examples/declaration/signature/type/multi-value-out.hs+13−4 data/examples/declaration/signature/type/multi-value.hs+9 data/examples/declaration/signature/type/unicode-out.hs+4 data/examples/declaration/signature/type/unicode.hs+4 data/examples/declaration/signature/type/unrelated-out.hs+4 data/examples/declaration/signature/type/unrelated.hs+4 data/examples/declaration/splice/bracket-declaration-out.hs+26 data/examples/declaration/splice/bracket-declaration.hs+22 data/examples/declaration/splice/bracket-out.hs+6−13 data/examples/declaration/splice/bracket.hs−5 data/examples/declaration/splice/grouped-splices-out.hs+3 data/examples/declaration/splice/grouped-splices.hs+3 data/examples/declaration/splice/quasiquote-out.hs+1 data/examples/declaration/splice/quotes-out.hs+17 data/examples/declaration/splice/quotes.hs+17 data/examples/declaration/splice/splice-decl-out.hs+2−1 data/examples/declaration/splice/typed-splice-out.hs+1 data/examples/declaration/splice/untyped-splice-out.hs+1 data/examples/declaration/type-families/closed-type-family/multi-line-out.hs+9−8 data/examples/declaration/type-families/closed-type-family/simple-out.hs+2 data/examples/declaration/type-families/closed-type-family/simple.hs+2 data/examples/declaration/type-families/closed-type-family/with-equal-sign-out.hs+2 data/examples/declaration/type-families/closed-type-family/with-equal-sign.hs+2 data/examples/declaration/type-families/closed-type-family/with-forall-out.hs+3 data/examples/declaration/type-families/closed-type-family/with-forall.hs+3 data/examples/declaration/type-families/data-family/no-annotation-out.hs+2 data/examples/declaration/type-families/data-family/no-annotation.hs+2 data/examples/declaration/type-families/data-family/simple-out.hs+2 data/examples/declaration/type-families/data-family/simple.hs+2 data/examples/declaration/type-families/type-family/no-annotation-out.hs+2 data/examples/declaration/type-families/type-family/no-annotation.hs+2 data/examples/declaration/type-families/type-family/operator-out.hs+3 data/examples/declaration/type-families/type-family/operator.hs+2 data/examples/declaration/type-families/type-family/simple-out.hs+2 data/examples/declaration/type-families/type-family/simple.hs+2 data/examples/declaration/type-synonyms/multi-line-out.hs+16−5 data/examples/declaration/type-synonyms/multi-line.hs+10 data/examples/declaration/type-synonyms/simple-out.hs+6 data/examples/declaration/type-synonyms/simple.hs+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/forall-out.hs+4 data/examples/declaration/type/forall.hs+4 data/examples/declaration/type/lits-out.hs+6 data/examples/declaration/type/lits.hs+4 data/examples/declaration/type/misc-kind-signatures-out.hs+5 data/examples/declaration/type/misc-kind-signatures.hs+5 data/examples/declaration/type/promotion-out.hs+19 data/examples/declaration/type/promotion.hs+15 data/examples/declaration/type/splice-out.hs+3 data/examples/declaration/type/splice.hs+3 data/examples/declaration/type/type-applications-out.hs+3 data/examples/declaration/type/type-applications.hs+3 data/examples/declaration/type/visible-forall-out.hs+2 data/examples/declaration/type/visible-forall.hs+2 data/examples/declaration/value/function/application-0-out.hs+17 data/examples/declaration/value/function/application-0.hs+12 data/examples/declaration/value/function/application-1-out.hs+19 data/examples/declaration/value/function/application-1.hs+14 data/examples/declaration/value/function/arg-breakpoints-out.hs+3 data/examples/declaration/value/function/arg-breakpoints.hs+3 data/examples/declaration/value/function/arithmetic-sequences-out.hs+16−6 data/examples/declaration/value/function/arithmetic-sequences.hs+5 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+19 data/examples/declaration/value/function/arrow/proc-applications.hs+17 data/examples/declaration/value/function/arrow/proc-cases-out.hs+16 data/examples/declaration/value/function/arrow/proc-cases.hs+17 data/examples/declaration/value/function/arrow/proc-do-complex-out.hs+62 data/examples/declaration/value/function/arrow/proc-do-complex.hs+49 data/examples/declaration/value/function/arrow/proc-do-simple1-out.hs+18 data/examples/declaration/value/function/arrow/proc-do-simple1.hs+20 data/examples/declaration/value/function/arrow/proc-do-simple2-out.hs+22 data/examples/declaration/value/function/arrow/proc-do-simple2.hs+20 data/examples/declaration/value/function/arrow/proc-forms1-out.hs+21 data/examples/declaration/value/function/arrow/proc-forms1.hs+19 data/examples/declaration/value/function/arrow/proc-forms2-out.hs+22 data/examples/declaration/value/function/arrow/proc-forms2.hs+19 data/examples/declaration/value/function/arrow/proc-ifs-out.hs+15 data/examples/declaration/value/function/arrow/proc-ifs.hs+14 data/examples/declaration/value/function/arrow/proc-lambdas-out.hs+9 data/examples/declaration/value/function/arrow/proc-lambdas.hs+10 data/examples/declaration/value/function/arrow/proc-lets-out.hs+12 data/examples/declaration/value/function/arrow/proc-lets.hs+14 data/examples/declaration/value/function/arrow/proc-parentheses-out.hs+19 data/examples/declaration/value/function/arrow/proc-parentheses.hs+12 data/examples/declaration/value/function/arrow/recursive-procs-out.hs+23 data/examples/declaration/value/function/arrow/recursive-procs.hs+18 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/backticks-lhs-out.hs+7 data/examples/declaration/value/function/backticks-lhs.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/block-arguments-out.hs+34 data/examples/declaration/value/function/block-arguments.hs+30 data/examples/declaration/value/function/case-multi-line-guards-out.hs+16 data/examples/declaration/value/function/case-multi-line-guards.hs+15 data/examples/declaration/value/function/case-multi-line-out.hs+11−14 data/examples/declaration/value/function/case-multi-line.hs+3−8 data/examples/declaration/value/function/case-single-line-out.hs+4 data/examples/declaration/value/function/case-single-line.hs+4 data/examples/declaration/value/function/complex-list-out.hs+15 data/examples/declaration/value/function/complex-list.hs+15 data/examples/declaration/value/function/comprehension/transform-multi-line1-out.hs+12 data/examples/declaration/value/function/comprehension/transform-multi-line1.hs+10 data/examples/declaration/value/function/comprehension/transform-multi-line2-out.hs+16 data/examples/declaration/value/function/comprehension/transform-multi-line2.hs+15 data/examples/declaration/value/function/comprehension/transform-multi-line3-out.hs+12 data/examples/declaration/value/function/comprehension/transform-multi-line3.hs+12 data/examples/declaration/value/function/comprehension/transform-multi-line4-out.hs+17 data/examples/declaration/value/function/comprehension/transform-multi-line4.hs+15 data/examples/declaration/value/function/comprehension/transform-single-line-out.hs+9 data/examples/declaration/value/function/comprehension/transform-single-line.hs+9 data/examples/declaration/value/function/do-out.hs−34 data/examples/declaration/value/function/do-single-multi-out.hs+4 data/examples/declaration/value/function/do-single-multi.hs+2 data/examples/declaration/value/function/do.hs−29 data/examples/declaration/value/function/do/applications-and-parens-out.hs+9 data/examples/declaration/value/function/do/applications-and-parens.hs+6 data/examples/declaration/value/function/do/blocks-out.hs+19 data/examples/declaration/value/function/do/blocks.hs+17 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/expr-out.hs+10 data/examples/declaration/value/function/do/expr.hs+10 data/examples/declaration/value/function/do/hang-rhs-arrow-out.hs+9 data/examples/declaration/value/function/do/hang-rhs-arrow.hs+9 data/examples/declaration/value/function/do/let-out.hs+18 data/examples/declaration/value/function/do/let.hs+18 data/examples/declaration/value/function/do/operator-and-parens-out.hs+7 data/examples/declaration/value/function/do/operator-and-parens.hs+7 data/examples/declaration/value/function/do/recursive-do-mdo-out.hs+12 data/examples/declaration/value/function/do/recursive-do-mdo.hs+8 data/examples/declaration/value/function/do/recursive-do-rec-out.hs+19 data/examples/declaration/value/function/do/recursive-do-rec.hs+20 data/examples/declaration/value/function/equality-constraints-out.hs+2 data/examples/declaration/value/function/equality-constraints.hs+2 data/examples/declaration/value/function/explicit-type-out.hs+2−2 data/examples/declaration/value/function/fancy-forall-0-out.hs+10 data/examples/declaration/value/function/fancy-forall-0.hs+6 data/examples/declaration/value/function/fancy-forall-1-out.hs+10 data/examples/declaration/value/function/fancy-forall-1.hs+6 data/examples/declaration/value/function/guards-out.hs+11−13 data/examples/declaration/value/function/guards.hs+11−11 data/examples/declaration/value/function/if-multi-line-out.hs+14−7 data/examples/declaration/value/function/if-multi-line.hs+10 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+11 data/examples/declaration/value/function/implicit-params.hs+7 data/examples/declaration/value/function/infix/applicative-out.hs+4 data/examples/declaration/value/function/infix/applicative.hs+4 data/examples/declaration/value/function/infix/comments-out.hs+8 data/examples/declaration/value/function/infix/comments.hs+8 data/examples/declaration/value/function/infix/do-out.hs+13 data/examples/declaration/value/function/infix/do.hs+13 data/examples/declaration/value/function/infix/dollar-chains-out.hs+22 data/examples/declaration/value/function/infix/dollar-chains.hs+22 data/examples/declaration/value/function/infix/hanging-out.hs+23 data/examples/declaration/value/function/infix/hanging.hs+19 data/examples/declaration/value/function/infix/lenses-out.hs+21 data/examples/declaration/value/function/infix/lenses.hs+16 data/examples/declaration/value/function/infix.hs → data/examples/declaration/value/function/infix/simple-out.hs+2−2 data/examples/declaration/value/function/infix-out.hs → data/examples/declaration/value/function/infix/simple.hs data/examples/declaration/value/function/infix/unicode-out.hs+3 data/examples/declaration/value/function/infix/unicode.hs+3 data/examples/declaration/value/function/lambda-case-out.hs+3 data/examples/declaration/value/function/lambda-case.hs+2 data/examples/declaration/value/function/lambda-multi-line-out.hs−9 data/examples/declaration/value/function/lambda-multi-line.hs−9 data/examples/declaration/value/function/lambda-multi-line1-out.hs+15 data/examples/declaration/value/function/lambda-multi-line1.hs+14 data/examples/declaration/value/function/lambda-multi-line2-out.hs+12 data/examples/declaration/value/function/lambda-multi-line2.hs+12 data/examples/declaration/value/function/lambda-single-line-out.hs+13−1 data/examples/declaration/value/function/lambda-single-line.hs+11 data/examples/declaration/value/function/let-multi-line-out.hs+19−3 data/examples/declaration/value/function/let-multi-line.hs+15 data/examples/declaration/value/function/let-nested-out.hs+3 data/examples/declaration/value/function/let-nested.hs+3 data/examples/declaration/value/function/let-single-line-out.hs+8 data/examples/declaration/value/function/let-single-line.hs+6 data/examples/declaration/value/function/list-comprehensions-out.hs+17−18 data/examples/declaration/value/function/list-comprehensions.hs+1−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+12−4 data/examples/declaration/value/function/multi-way-if.hs+5 data/examples/declaration/value/function/multiline-arguments-out.hs+1−1 data/examples/declaration/value/function/multiple-guards-out.hs+14 data/examples/declaration/value/function/multiple-guards.hs+13 data/examples/declaration/value/function/negation-out.hs+6 data/examples/declaration/value/function/negation.hs+6 data/examples/declaration/value/function/operator-comments-0-out.hs+16 data/examples/declaration/value/function/operator-comments-0.hs+17 data/examples/declaration/value/function/operator-comments-1-out.hs+16 data/examples/declaration/value/function/operator-comments-1.hs+17 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/operator-sections-out.hs+2−2 data/examples/declaration/value/function/operators-0-out.hs+5 data/examples/declaration/value/function/operators-0.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/overindentation-out.hs+11 data/examples/declaration/value/function/overindentation.hs+9 data/examples/declaration/value/function/overloaded-labels-out.hs+1 data/examples/declaration/value/function/parallel-comprehensions-complex-out.hs+35 data/examples/declaration/value/function/parallel-comprehensions.hs → data/examples/declaration/value/function/parallel-comprehensions-complex.hs−4 data/examples/declaration/value/function/parallel-comprehensions-out.hs−37 data/examples/declaration/value/function/parallel-comprehensions-single-line-out.hs+3 data/examples/declaration/value/function/parallel-comprehensions-single-line.hs+4 data/examples/declaration/value/function/parens-out.hs+1 data/examples/declaration/value/function/parens.hs+1 data/examples/declaration/value/function/parenthesis-lhs-out.hs+9 data/examples/declaration/value/function/parenthesis-lhs.hs+9 data/examples/declaration/value/function/pattern/as-pattern-out.hs+3 data/examples/declaration/value/function/pattern/as-pattern.hs+3 data/examples/declaration/value/function/pattern/famous-cardano-pattern-out.hs+8 data/examples/declaration/value/function/pattern/famous-cardano-pattern.hs+7 data/examples/declaration/value/function/pattern/multiline-case-pattern-out.hs+15 data/examples/declaration/value/function/pattern/multiline-case-pattern.hs+12 data/examples/declaration/value/function/pattern/n-plus-k-pattern-out.hs+5−1 data/examples/declaration/value/function/pattern/n-plus-k-pattern.hs+3 data/examples/declaration/value/function/pattern/pattern-bind-out.hs+4−1 data/examples/declaration/value/function/pattern/pattern-bind.hs+4−1 data/examples/declaration/value/function/pattern/quasi-quotes-pattern-out.hs+1 data/examples/declaration/value/function/pattern/record-patterns-out.hs+3−3 data/examples/declaration/value/function/pattern/sig-pattern-out.hs+2−2 data/examples/declaration/value/function/pattern/splice-pattern-out.hs+3−2 data/examples/declaration/value/function/pattern/strictness-out.hs+5 data/examples/declaration/value/function/pattern/strictness.hs+4 data/examples/declaration/value/function/pattern/unboxed-sum-pattern-out.hs+26 data/examples/declaration/value/function/pattern/unboxed-sum-pattern.hs+23 data/examples/declaration/value/function/pattern/view-pattern-out.hs+2−1 data/examples/declaration/value/function/quasi-quotes-out.hs+1 data/examples/declaration/value/function/record-constructors-out.hs−8 data/examples/declaration/value/function/record-constructors.hs−6 data/examples/declaration/value/function/record-updaters-out.hs−9 data/examples/declaration/value/function/record/constructors-out.hs+31 data/examples/declaration/value/function/record/constructors.hs+22 data/examples/declaration/value/function/record/dot-out.hs+15 data/examples/declaration/value/function/record/dot.hs+14 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/record/inter-comments-out.hs+13 data/examples/declaration/value/function/record/inter-comments.hs+11 data/examples/declaration/value/function/record/updaters-out.hs+11 data/examples/declaration/value/function/record-updaters.hs → data/examples/declaration/value/function/record/updaters.hs+1 data/examples/declaration/value/function/record-wildcards-out.hs → data/examples/declaration/value/function/record/wildcards-out.hs+8−6 data/examples/declaration/value/function/record-wildcards.hs → data/examples/declaration/value/function/record/wildcards.hs data/examples/declaration/value/function/splice-out.hs+1 data/examples/declaration/value/function/static-pointers-out.hs+7−5 data/examples/declaration/value/function/strings-out.hs+10 data/examples/declaration/value/function/strings.hs+7 data/examples/declaration/value/function/tricky-parens-out.hs+4 data/examples/declaration/value/function/tricky-parens.hs+4 data/examples/declaration/value/function/tuple-sections-out.hs+2−2 data/examples/declaration/value/function/tuples-out.hs+10−3 data/examples/declaration/value/function/tuples.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/declaration/value/function/type-applications-out.hs+7 data/examples/declaration/value/function/type-applications.hs+5 data/examples/declaration/value/function/typed-expressions-out.hs+2−2 data/examples/declaration/value/function/typed-hole-out.hs+5 data/examples/declaration/value/function/typed-hole.hs+5 data/examples/declaration/value/function/unboxed-string-lit-out.hs+3 data/examples/declaration/value/function/unboxed-string-lit.hs+3 data/examples/declaration/value/function/unboxed-sums-out.hs+3−1 data/examples/declaration/value/function/unboxed-tuples-out.hs+5−3 data/examples/declaration/value/function/where-nested-out.hs+12 data/examples/declaration/value/function/where-nested.hs+12 data/examples/declaration/value/function/where-out.hs+5−3 data/examples/declaration/value/function/where.hs+4 data/examples/declaration/value/other/comments-get-before-op-out.hs+10 data/examples/declaration/value/other/comments-get-before-op.hs+11 data/examples/declaration/value/other/line-multi-line-out.hs+3−3 data/examples/declaration/value/pattern-synonyms/bidirectional-out.hs+21 data/examples/declaration/value/pattern-synonyms/bidirectional.hs+14 data/examples/declaration/value/pattern-synonyms/explicitely-bidirectional-out.hs+11 data/examples/declaration/value/pattern-synonyms/explicitely-bidirectional.hs+10 data/examples/declaration/value/pattern-synonyms/unidirectional-out.hs+18 data/examples/declaration/value/pattern-synonyms/unidirectional.hs+14 data/examples/declaration/warning/warning-multiline-out.hs+9 data/examples/declaration/warning/warning-multiline.hs+4 data/examples/declaration/warning/warning-single-line-out.hs+13 data/examples/declaration/warning/warning-single-line.hs+15 data/examples/import/comments-inside-imports-out.hs+7 data/examples/import/comments-inside-imports.hs+9 data/examples/import/deduplication-bug-out.hs+6 data/examples/import/deduplication-bug.hs+6 data/examples/import/explicit-imports-out.hs+10−10 data/examples/import/explicit-imports-with-comments-out.hs+4−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+1−7 data/examples/import/nested-explicit-imports-out.hs+8−8 data/examples/import/qualified-post-out.hs+5 data/examples/import/qualified-post.hs+5 data/examples/import/qualified-prelude-out.hs+4 data/examples/import/qualified-prelude.hs+4 data/examples/import/simple-out.hs+2−3 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+17 data/examples/module-header/double-dot-with-names.hs+17 data/examples/module-header/leading-empty-line-out.hs+11 data/examples/module-header/leading-empty-line.hs+11 data/examples/module-header/multiline-out.hs+3−3 data/examples/module-header/multiline-with-comments-out.hs+13−12 data/examples/module-header/multiline2-out.hs+3−3 data/examples/module-header/multiline2.hs+2−2 data/examples/module-header/named-section-out.hs+13 data/examples/module-header/named-section.hs+13 data/examples/module-header/preceding-comment-with-haddock-out.hs+8 data/examples/module-header/preceding-comment-with-haddock.hs+8 data/examples/module-header/shebang-out.hs+6 data/examples/module-header/shebang-with-pragmas-out.hs+5 data/examples/module-header/shebang-with-pragmas.hs+5 data/examples/module-header/shebang.hs+6 data/examples/module-header/singleline-empty-out.hs+2 data/examples/module-header/singleline-empty.hs+2 data/examples/module-header/stack-header-0-out.hs+7 data/examples/module-header/stack-header-0.hs+4 data/examples/module-header/stack-header-1-out.hs+8 data/examples/module-header/stack-header-1.hs+5 data/examples/module-header/stack-header-2-out.hs+12 data/examples/module-header/stack-header-2.hs+12 data/examples/module-header/warning-pragma-list-multiline-out.hs+5−5 data/examples/module-header/warning-pragma-multiline-out.hs+3−5 data/examples/module-header/warning-pragma-out.hs+5−1 data/examples/other/argument-comment-out.hs+15−3 data/examples/other/argument-comment.hs+9 data/examples/other/ascii-out.hs+9 data/examples/other/ascii.hs+9 data/examples/other/comment-after-preceding-haddock-out.hs+12 data/examples/other/comment-after-preceding-haddock.hs+12 data/examples/other/comment-alignment-out.hs+9 data/examples/other/comment-alignment.hs+11 data/examples/other/comment-before-hanging-out.hs+5 data/examples/other/comment-before-hanging.hs+5 data/examples/other/comment-following-preceding-gap-out.hs+6 data/examples/other/comment-following-preceding-gap.hs+6 data/examples/other/comment-glued-together-out.hs+7 data/examples/other/comment-glued-together.hs+6 data/examples/other/comment-inside-construct-out.hs+8 data/examples/other/comment-inside-construct.hs+9 data/examples/other/comment-multiline-after-out.hs+7 data/examples/other/comment-multiline-after.hs+1 data/examples/other/comment-style-transform-out.hs+17 data/examples/other/comment-style-transform.hs+22 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+8 data/examples/other/comment-two-blocks.hs+9 data/examples/other/consequetive-pipe-comments-out.hs+7 data/examples/other/consequetive-pipe-comments.hs+8 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/empty-forall-out.hs+18 data/examples/other/empty-forall.hs+17 data/examples/other/empty-haddock-out.hs+5 data/examples/other/empty-haddock.hs+6 data/examples/other/following-comment-last-0-out.hs+5 data/examples/other/following-comment-last-0.hs+5 data/examples/other/following-comment-last-1-out.hs+8 data/examples/other/following-comment-last-1.hs+8 data/examples/other/following-comment-last-2-out.hs+10 data/examples/other/following-comment-last-2.hs+10 data/examples/other/following-comment-last-3-out.hs+6 data/examples/other/following-comment-last-3.hs+6 data/examples/other/haddock-sections-out.hs+7 data/examples/other/haddock-sections.hs+7 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/merging-comments-out.hs+12 data/examples/other/merging-comments.hs+9 data/examples/other/multiline-comments-reindent-out.hs+3−3 data/examples/other/multiline-forall-out.hs+58 data/examples/other/multiline-forall.hs+46 data/examples/other/multiple-blank-line-comment-out.hs+9 data/examples/other/multiple-blank-line-comment.hs+10 data/examples/other/overly-indented-out.hs+11 data/examples/other/overly-indented.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-no-header-out.hs+3 data/examples/other/pragma-no-header.hs+3 data/examples/other/pragma-out.hs+12 data/examples/other/pragma-sorting-out.hs+11 data/examples/other/pragma-sorting.hs+10 data/examples/other/pragma.hs+13 data/examples/other/trailing-whitespace-out.hs+7 data/examples/other/trailing-whitespace.hs+7 data/printer/list0-multi.hs−4 data/printer/list0-single.hs−1 data/printer/list1-multi.hs−8 data/printer/list1-single.hs−1 data/printer/mhdr-multi.hs−7 data/printer/mhdr-single.hs−3 data/printer/ssig-multi.hs−5 data/printer/ssig-single.hs−1 default.nix+163−12 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+14 nix/gitignore/default.nix−8 nix/nixpkgs/default.nix+7−3 nix/ormolize/default.nix+53 ormolu.cabal+174−122 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+5−1 src/GHC.hs+12 src/GHC/DynFlags.hs+49 src/Ormolu.hs+98−70 src/Ormolu/CommentStream.hs−96 src/Ormolu/Config.hs+68−44 src/Ormolu/Diff.hs+143−40 src/Ormolu/Exception.hs+63−43 src/Ormolu/Imports.hs+176−61 src/Ormolu/Parser.hs+193−127 src/Ormolu/Anns.hs → src/Ormolu/Parser/Anns.hs+19−21 src/Ormolu/Parser/CommentStream.hs+226 src/Ormolu/Parser/Pragma.hs+89 src/Ormolu/Parser/Result.hs+51 src/Ormolu/Parser/Shebang.hs+27 src/Ormolu/Printer.hs+27−18 src/Ormolu/Printer/Combinators.hs+206−217 src/Ormolu/Printer/Comments.hs+198−125 src/Ormolu/Printer/Internal.hs+450−246 src/Ormolu/Printer/Meat/Common.hs+121−56 src/Ormolu/Printer/Meat/Declaration.hs+283−77 src/Ormolu/Printer/Meat/Declaration.hs-boot+5−5 src/Ormolu/Printer/Meat/Declaration/Annotation.hs+5−6 src/Ormolu/Printer/Meat/Declaration/Class.hs+67−79 src/Ormolu/Printer/Meat/Declaration/Data.hs+192−98 src/Ormolu/Printer/Meat/Declaration/Default.hs+6−7 src/Ormolu/Printer/Meat/Declaration/Foreign.hs+18−16 src/Ormolu/Printer/Meat/Declaration/Instance.hs+57−58 src/Ormolu/Printer/Meat/Declaration/RoleAnnotation.hs+7−13 src/Ormolu/Printer/Meat/Declaration/Rule.hs+61 src/Ormolu/Printer/Meat/Declaration/Signature.hs+162−113 src/Ormolu/Printer/Meat/Declaration/Splice.hs+3−4 src/Ormolu/Printer/Meat/Declaration/Type.hs+28−19 src/Ormolu/Printer/Meat/Declaration/TypeFamily.hs+62−54 src/Ormolu/Printer/Meat/Declaration/Value.hs+1096−409 src/Ormolu/Printer/Meat/Declaration/Value.hs-boot+17 src/Ormolu/Printer/Meat/Declaration/Warning.hs+49 src/Ormolu/Printer/Meat/ImportExport.hs+100−54 src/Ormolu/Printer/Meat/Module.hs+57−55 src/Ormolu/Printer/Meat/Pragma.hs+91 src/Ormolu/Printer/Meat/Type.hs+213−93 src/Ormolu/Printer/Operators.hs+177 src/Ormolu/SpanStream.hs → src/Ormolu/Printer/SpanStream.hs+19−21 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+142−14 tests/Ormolu/Parser/PragmaSpec.hs+26 tests/Ormolu/Printer/CombinatorsSpec.hs−110 tests/Ormolu/PrinterSpec.hs+32−22
.buildkite/pipeline.ymlnew file+18
@@ -0,0 +1,18 @@
1+steps:
2+ - label: Build and test with GHC 8.6.5
3+ command: |
4+ nix-build --keep-going --no-out-link --argstr ormoluCompiler ghc865
5+ timeout: 100
6+ - label: Build and test with GHC 8.8.4
7+ command: |
8+ nix-build --keep-going --no-out-link --argstr ormoluCompiler ghc884
9+ timeout: 100
10+ - label: Build and test with GHC 8.10.1
11+ command: |
12+ nix-build --keep-going --no-out-link --argstr ormoluCompiler ghc8101
13+ timeout: 100
14+ - wait
15+ - label: Check formatting
16+ command: |
17+ ./format.sh
18+ git diff --exit-code --color=always
.circleci/config.ymldeleted−44
@@ -1,44 +0,0 @@
1−version: 2
2−
3−jobs:
4− build_ghc864:
5− docker:
6− - image: nixos/nix:2.1.3
7− steps:
8− - checkout
9− - run:
10− name: Add ca-certificates
11− command: |
12− apk --no-progress update
13− apk --no-progress add ca-certificates
14− - run:
15− name: Setup Cachix
16− command: |
17− nix-env -f nix/nixpkgs/ -iA cachix
18− USER=dummy cachix use tweag
19− - run:
20− name: Build environment
21− command: |
22− nix-shell --pure --run :
23− - run:
24− name: Push Cachix
25− command: |
26− if [ -n "$CACHIX_SIGNING_KEY" ];
27− then nix-store -qR --include-outputs $(nix-instantiate default.nix) | cachix push tweag;
28− fi
29− - run:
30− name: Build the package (includes running the tests)
31− command: nix-build
32− - run:
33− name: Generate Haddocks
34− command: nix-build --attr ormolu.doc
35− - store_artifacts:
36− path: result-doc/share/doc
37− destination: haddock
38−
39−workflows:
40− version: 2
41− build:
42− jobs:
43− - build_ghc864:
44− context: org-global
.github/workflows/binaries.ymlnew file+39
@@ -0,0 +1,39 @@
1+name: Build binaries
2+on:
3+ release:
4+ types: [published]
5+jobs:
6+ build:
7+ strategy:
8+ fail-fast: false
9+ matrix:
10+ os: [ubuntu-latest, macOS-latest, windows-latest]
11+ runs-on: ${{ matrix.os }}
12+ steps:
13+ - uses: actions/checkout@v2
14+ - uses: actions/setup-haskell@v1
15+ if: runner.os != 'Linux'
16+ with:
17+ ghc-version: '8.10.1'
18+ cabal-version: '3.2'
19+ - name: Build Linux binary
20+ if: runner.os == 'Linux'
21+ run: |
22+ docker run \
23+ -v $(pwd):/mnt -w /mnt \
24+ utdemir/ghc-musl:v14-ghc8101 \
25+ bash .github/workflows/build.sh
26+ - name: Build ${{ runner.os }} binary
27+ if: runner.os != 'Linux'
28+ shell: bash
29+ run: |
30+ cabal build exe:ormolu
31+ cp $(find dist-newstyle \( -name ormolu -o -name ormolu.exe \) -type f) ormolu
32+ - uses: actions/upload-release-asset@v1
33+ env:
34+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35+ with:
36+ upload_url: ${{ github.event.release.upload_url }}
37+ asset_path: ormolu
38+ asset_name: ormolu-${{ runner.os }}
39+ asset_content_type: application/octet-stream
.github/workflows/build.shnew file+7
@@ -0,0 +1,7 @@
1+set -e
2+
3+cabal update
4+cabal build exe:ormolu --enable-executable-static --ghc-options="-split-sections"
5+
6+cp $(find dist-newstyle -name ormolu -type f) .
7+strip -s ormolu
.gitignore+1
@@ -26,4 +26,5 @@ cabal.sandbox.config
2626dist-*/
2727dist/
2828stack.yaml
29+stack.yaml.lock
2930result*
CHANGELOG.md+231
@@ -1,3 +1,234 @@
1+## Unreleased
2+
3+* Ormolu no longer overwrites already formatted files. [PR
4+ 649](https://github.com/tweag/ormolu/pull/649).
5+
6+## Ormolu 0.1.2.0
7+
8+* Fixed the bug when comments in different styles got glued together after
9+ formatting. [Issue 589](https://github.com/tweag/ormolu/issues/589).
10+
11+* Added `-i` as a shortcut for `--mode inplace`. [Issue
12+ 467](https://github.com/tweag/ormolu/issues/467).
13+
14+* Improved grouping of top-level declarations. [Issue
15+ 466](https://github.com/tweag/ormolu/issues/466).
16+
17+## Ormolu 0.1.1.0
18+
19+* Imports in a import lists are now normalized: duplicate imports are
20+ combined/eliminated intelligently.
21+
22+* Import declarations that can be merged are now automatically merged.
23+ [Issue 414](https://github.com/tweag/ormolu/issues/414).
24+
25+* The magic comments for disabling and enabling Ormolu now can encompass any
26+ fragment of code provided that the remaining code after exclusion of the
27+ disabled part is still syntactically correct. [Issue
28+ 601](https://github.com/tweag/ormolu/issues/601).
29+
30+* Improved sorting of operators in imports. [Issue
31+ 602](https://github.com/tweag/ormolu/issues/602).
32+
33+* Fixed a bug related to trailing space in multiline comments in certain
34+ cases. [Issue 603](https://github.com/tweag/ormolu/issues/602).
35+
36+* Added support for formatting linked lists with `(:)` as line terminator.
37+ [Issue 478](https://github.com/tweag/ormolu/issues/478).
38+
39+* Fixed rendering of function arguments in multiline layout. [Issue
40+ 609](https://github.com/tweag/ormolu/issues/609).
41+
42+* Blank lines between definitions in `let` and `while` bindings are now
43+ preserved. [Issue 554](https://github.com/tweag/ormolu/issues/554).
44+
45+* Fixed the bug when type applications stuck to the `$` of TH splices that
46+ followed them. [Issue 613](https://github.com/tweag/ormolu/issues/613).
47+
48+* Improved region formatting so that indented fragments—such as definitions
49+ inside of `where` clauses—can be formatted. [Issue
50+ 572](https://github.com/tweag/ormolu/issues/572).
51+
52+* Fixed the bug related to the de-association of pragma comments. [Issue
53+ 619](https://github.com/tweag/ormolu/issues/619).
54+
55+## Ormolu 0.1.0.0
56+
57+* Fixed rendering of type signatures concerning several identifiers. [Issue
58+ 566](https://github.com/tweag/ormolu/issues/566).
59+
60+* Fixed an idempotence issue with inline comments in tuples and parentheses.
61+ [Issue 450](https://github.com/tweag/ormolu/issues/450).
62+
63+* Fixed an idempotence issue when certain comments were picked up as
64+ “continuation” of a series of comments [Issue
65+ 449](https://github.com/tweag/ormolu/issues/449).
66+
67+* Fixed an idempotence issue related to different indentation levels in a
68+ comment series. [Issue 512](https://github.com/tweag/ormolu/issues/512).
69+
70+* Fixed an idempotence issue related to comments which may happen to be
71+ separated from the elements they are attached to by the equality sign.
72+ [Issue 340](https://github.com/tweag/ormolu/issues/340).
73+
74+* Fixed an idempotence issue with type synonym and data declarations where
75+ the type has a Haddock. [Issue
76+ 578](https://github.com/tweag/ormolu/issues/578).
77+
78+* Fix the false positive about AST differences in presence of comments with
79+ multiple blank lines in a row. [Issue
80+ 518](https://github.com/tweag/ormolu/issues/518).
81+
82+* Fixed rendering of comments around if expressions. [Issue
83+ 458](https://github.com/tweag/ormolu/issues/458).
84+
85+* Unnamed fields of data constructors are now documented using the `-- ^`
86+ syntax. [Issue 445](https://github.com/tweag/ormolu/issues/445) and [Issue
87+ 428](https://github.com/tweag/ormolu/issues/428).
88+
89+* Fixed non-idempotent transformation of partly documented data definition.
90+ [Issue 590](https://github.com/tweag/ormolu/issues/590).
91+
92+* Fixed an idempotence issue related to operators. [Issue
93+ 522](https://github.com/tweag/ormolu/issues/522).
94+
95+* Renamed the `--check-idempotency` flag to `--check-idempotence`.
96+ Apparently only the latter is correct.
97+
98+## Ormolu 0.0.5.0
99+
100+* Grouping of statements in `do`-blocks is now preserved. [Issue
101+ 74](https://github.com/tweag/ormolu/issues/74).
102+
103+* Grouping of TH splices is now preserved. [Issue
104+ 507](https://github.com/tweag/ormolu/issues/507).
105+
106+* Comments on pragmas are now preserved. [Issue
107+ 216](https://github.com/tweag/ormolu/issues/216).
108+
109+* Ormolu can now be enabled and disabled via special comments. [Issue
110+ 435](https://github.com/tweag/ormolu/issues/435).
111+
112+* Added experimental support for simple CPP. [Issue
113+ 415](https://github.com/tweag/ormolu/issues/415).
114+
115+* Added two new options `--start-line` and `--end-line` that allow us to
116+ select a region to format. [Issue
117+ 516](https://github.com/tweag/ormolu/issues/516).
118+
119+* Fixed rendering of module headers in the presence of preceding comments or
120+ Haddocks. [Issue 561](https://github.com/tweag/ormolu/issues/561).
121+
122+## Ormolu 0.0.4.0
123+
124+* When given several files to format, Ormolu does not stop on the first
125+ failure, but tries to format all the files. [Issue
126+ 502](https://github.com/tweag/ormolu/issues/502).
127+
128+* Made rendering of pattern matches involving operators consistent with
129+ other cases of rendering of operators. [Issue
130+ 500](https://github.com/tweag/ormolu/issues/500).
131+
132+* More compact rendering of type family injectivity constraints. [Issue
133+ 482](https://github.com/tweag/ormolu/issues/482).
134+
135+* Improved rendering of the keyword `where` in class, data, and type family
136+ declarations. When headers of these declarations are multi-line `where` is
137+ now put on its own line. [Issue
138+ 509](https://github.com/tweag/ormolu/issues/509).
139+
140+* Fixed the bug pertaining to rendering of arrow notation with multiline
141+ expressions. [Issue 513](https://github.com/tweag/ormolu/issues/513).
142+
143+* Made rendering of data type definitions, value-level applications, and
144+ application of types use the same style. Moreover, existential now doesn't
145+ cause the data constructor be unconditionally rendered in multiline
146+ layout. [Issue 427](https://github.com/tweag/ormolu/issues/427).
147+
148+* Records with a single data constructor are now formatted more compactly.
149+ [Issue 425](https://github.com/tweag/ormolu/issues/425).
150+
151+* Switched to `ghc-lib-parser-8.10.1`.
152+
153+* Implemented support for the new language extensions `ImportQualifiedPost`
154+ and `StandaloneKindSignatures`.
155+
156+## Ormolu 0.0.3.1
157+
158+* Fixed rendering of record updates with the record dot preprocessor syntax
159+ [Issue 498](https://github.com/tweag/ormolu/issues/498).
160+
161+## Ormolu 0.0.3.0
162+
163+* Fixed an issue related to unnecessary use of curly braces. [Issue
164+ 473](https://github.com/tweag/ormolu/issues/473).
165+
166+* Fixed the issue with formatting multi-way if when it happens to be a
167+ function applied to arguments [Issue
168+ 488](https://github.com/tweag/ormolu/issues/488). This changed the way
169+ multi-line if is formatted in general.
170+
171+* Added support for record dot pre-processor when used via the plugin.
172+ [Issue 486](https://github.com/tweag/ormolu/issues/486).
173+
174+* Stopped hanging record constructors and improved placing
175+ potentially-hanging consturctions in the presence of comments. [Issue
176+ 447](https://github.com/tweag/ormolu/issues/447).
177+
178+* Fixed indentation in presence of type applications. [Issue
179+ 493](https://github.com/tweag/ormolu/issues/493).
180+
181+* Class and instance declarations now do not have a blank line after
182+ `where`. Grouping of methods from the original input is also preserved
183+ with some normalizations. [Issue
184+ 431](https://github.com/tweag/ormolu/issues/431).
185+
186+## Ormolu 0.0.2.0
187+
188+* Switched to `ghc-lib-parser` instead of depending on the `ghc` package
189+ directly. This should allow us to use newest features of GHC while not
190+ necessarily depending on the newest version of the compiler. In addition
191+ to that Ormolu is now GHCJS-compatible.
192+
193+* Now unrecognized GHC options passed with `--ghc-opt` cause Ormolu to fail
194+ (exit code 7).
195+
196+* Fixed formatting of result type in closed type families. See [issue
197+ 420](https://github.com/tweag/ormolu/issues/420).
198+
199+* Fixed a minor inconsistency between formatting of normal and foreign type
200+ signatures. See [issue 408](https://github.com/tweag/ormolu/issues/408).
201+
202+* Fixed a bug when comment before module header with Haddock was moved
203+ inside the export list. See [issue
204+ 430](https://github.com/tweag/ormolu/issues/430).
205+
206+* Empty `forall`s are now correctly preserved. See [issue
207+ 429](https://github.com/tweag/ormolu/issues/429).
208+
209+* Fixed [issue 446](https://github.com/tweag/ormolu/issues/446), which
210+ involved braces and operators.
211+
212+* When there are comments between preceding Haddock (pipe-style) and its
213+ corresponding declaration they are preserved like this in the output
214+ instead of being shifted. To be clear, this is not a very good idea to
215+ have comments in that position because the Haddock will end up not being
216+ associated with the declarations. Issues
217+ [440](https://github.com/tweag/ormolu/issues/440) and
218+ [448](https://github.com/tweag/ormolu/issues/448).
219+
220+* Implemented correct handling of shebangs. [Issue
221+ 377](https://github.com/tweag/ormolu/issues/377).
222+
223+* Implemented correct handling of stack headers. [Issue
224+ 393](https://github.com/tweag/ormolu/issues/393).
225+
226+* Sorting language pragmas cannot not change meaning of the input program
227+ anymore. [Issue 404](https://github.com/tweag/ormolu/issues/404).
228+
229+* Fixed formatting of applications where function is a complex expression.
230+ [Issue 444](https://github.com/tweag/ormolu/issues/444).
231+
1232## Ormolu 0.0.1.0
2233
3234* Initial release.
CONTRIBUTING.md+28−34
@@ -1,8 +1,7 @@
11# Contributing
22
33Issues (bugs, feature requests or otherwise feedback) may be reported in
4−[the GitHub issue tracker for this
5−project](https://github.com/tweag/ormolu/issues). Pull requests are also
4+[the GitHub issue tracker for this project][issues]. Pull requests are also
65welcome.
76
87When contributing to this repository, please first discuss the change you
@@ -16,36 +15,7 @@ messages and PR descriptions.
1615
1716## What to hack on?
1817
19−Right now there are two options for people who want to contribute:
20−
21−* [Implementing rendering of AST][cover-ast]. This is the main focus right
22− now because we want to have a MVP which can render all syntactical
23− constructions found in Haskell source code. Once that is achieved we'll
24− polish the tool iteratively.
25−* [Fixing bugs][bugs]. If this seems more interesting than implementing
26− rendering of AST, you are welcome to do this as well.
27−
28−## Implementing rendering of AST
29−
30−The `Ormolu.Printer.Combinators` module provides a DSL for rendering of GHC
31−AST. You'll probably only need this one module for writing new rendering
32−functions. The module documents how to use the printing combinators it
33−provides. Consult the Haddocks to learn more about them.
34−
35−Create new modules corresponding to the things you want to render under
36−`Ormolu.Printer.Meat`. For example, there are `Ormolu.Printer.Meat.Type` and
37−`Ormolu.Printer.Meat.Declaration.Data`.
38−
39−Concrete rendering functions get their names by appending `p_` to the name
40−of the type which describes a particular part of AST. For example, the
41−function for rendering types is correspondingly:
42−
43−```haskell
44−p_hsType :: HsType GhcPs -> R ()
45−```
46−
47−In general rendering functions like this take 1 or more arguments and
48−produce `R ()` which is a rendering action.
18+* [Fixing bugs][bugs]. This is the main focus right now.
4919
5020### Testing
5121
@@ -60,11 +30,35 @@ Testing is performed as following:
6030* The result of printing is parsed back again and the AST is compared to the
6131 AST obtained from the original file. They should match.
6232* The output of printer is checked against the expected output.
63−* Idempotency property is verified: formatting already formatted code
33+* Idempotence property is verified: formatting already formatted code
6434 results in exactly the same output.
6535
6636Examples can be organized in sub-directories, see the existing ones for
6737inspiration.
6838
69−[cover-ast]: https://github.com/tweag/ormolu/issues?q=is%3Aissue+is%3Aopen+label%3Acovering-ghc-ast
39+Please note that we try to keep individual files at most 25 lines long
40+because otherwise it's hard to figure out want went wrong when a test fails.
41+
42+## CI
43+
44+We use Circle CI. Some outside contributors may have problems, as in, CI
45+won't run for PRs opened from forks with “unauthorized” errors. In that case
46+the best we can do is to add you as a contributor or to restart your build
47+manually.
48+
49+If you have been added as a contributor but the builds still do not start,
50+try clicking
51+
52+```
53+User settings -> Account integrations -> Refresh permissions
54+```
55+
56+in Circle CI app.
57+
58+## Formatting
59+
60+Use `format.sh` script to format Ormolu with current version of Ormolu. If
61+Ormolu is not formatted like this, the CI will fail.
62+
63+[issues]: https://github.com/tweag/ormolu/issues
7064[bugs]: https://github.com/tweag/ormolu/issues?q=is%3Aissue+is%3Aopen+label%3Abug
DESIGN.md+26−50
@@ -1,5 +1,8 @@
11# Ormolu
22
3+*This document represents our discussions and plans at early stages of
4+development, it is no longer being updated.*
5+
36* [Analysis of the existing solutions](#analysis-of-the-existing-solutions)
47 * [Brittany](#brittany)
58 * [Hindent](#hindent)
@@ -14,14 +17,14 @@
1417 * [Testing](#testing)
1518 * [Functionality of executable](#functionality-of-executable)
1619 * [Why not contribute to/fork Hindent or Brittany?](#why-not-contribute-tofork-hindent-or-brittany)
17−* [Roadmap](#roadmap)
20+* [Examples](#examples)
1821
1922This document describes design of a new formatter for Haskell source code.
2023It also includes recommendations for future implementers.
2124
2225We set for the following goals (mostly taken from
2326[brittany](https://github.com/lspitzner/brittany)):
24−* Preserve the meaning of the formatted functions;
27+* Preserve the meaning of the formatted functions when no CPP is used;
2528* Make reasonable use of screen space;
2629* Use linear space and computation time on the size of the input;
2730* Preserve comments;
@@ -137,8 +140,10 @@ impossible to guess what they'll be called on.
137140
138141### CPP
139142
140−Formatting a module which uses CPP directives won't be supported. Instead,
141−we hope for a solution to replace CPP to do conditional compilation.
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.
142147
143148There are the following challenges when formatting a module with CPP:
144149
@@ -177,14 +182,15 @@ True
177182```
178183
179184At the time of this writing, formatting this program with Hindent
180−produces the same output we would get if the CPP directives were
181−considered comments:
185+or Ormolu produces the same output we would get if the CPP directives
186+were considered comments:
182187
183188```
184−$ hindent --version
185−hindent 5.2.7
189+$ ormolu --version
190+ormolu 0.0.5.0 HEAD fc64eada5c4da7a5b07d2872e253671b48aec115
191+using ghc-lib-parser 8.10.1.20200412
186192
187−$ hindent test.hs
193+$ ormolu --mode inplace test.hs
188194
189195$ cat test.hs
190196{-# LANGUAGE CPP #-}
@@ -224,9 +230,6 @@ to parse Haskell modules. If CPP is replaced with some language
224230extension or mechanism to do conditional compilation, all tools
225231will benefit from it.
226232
227−Therefore, CPP won't be supported. If the CPP extension
228−is enabled, we should signal an error right away.
229−
230233### Printing
231234
232235Just pretty-printing code (following the approach of Hindent) seems sane. It
@@ -282,22 +285,22 @@ map :: (a -> b) -> [a] -> [b]
282285foldr :: (a -> b -> b) ->
283286 b -> [a] -> [b]
284287-- Is reformatted to:
285−foldr
286− :: (a -> b -> b)
287− -> b
288− -> [a]
289− -> [b]
288+foldr ::
289+ (a -> b -> b) ->
290+ b ->
291+ [a] ->
292+ [b]
290293
291294t = let x = foo bar
292295 baz
293296 in foo bar baz
294297-- Is reformatted to:
295298t =
296− let x =
297− foo
298− bar
299− baz
300− in foo far baz
299+ let x =
300+ foo
301+ bar
302+ baz
303+ in foo far baz
301304```
302305
303306Crucially, no effort is made to fit within reasonable line lengths. That's
@@ -388,34 +391,7 @@ also possible that we'll find a nicer way to write pretty-printer.
388391
389392## Examples
390393
391−A list of formatting examples can be found [here](EXAMPLES.md).
392−
393−## Roadmap
394−
395−Proposed roadmap (for a single person, about 39 full-time work days):
396−
397−* ~~Create and setup a repo, setup CI (less than 1 day).~~
398−* ~~Implement parsing (2 days).~~
399−* ~~Implement basis for pretty-printing of code. We could take
400− [this][hindent-printer] as inspiration, although AST from the `ghc`
401− package may be slightly different. Also, don't forget about annotations
402− and comments (1 week).~~
403−* Implement executable program so we can easier fool around. Try it on
404− simple code samples (2 days).
405−* Implement location and reading of configuration file in YAML format (2
406− days).
407−* Continue writing the pretty-printing code till we cover everything. Start
408− adding tests, see [the section about testing](#testing). Fix bugs. At this
409− point just repeat this till we cover everything that Brittany and Hindent
410− can do maybe by stealing their tests (at least 2 weeks).
411−* Start checking how our formatter works on real-world code from Hackage.
412− Fix bugs that we find that way (2 weeks).
413−* Write a good readme explaining why the project was created and how it is
414− better, etc (2 days).
415−* Switch CI to Travis and test with multiple GHC versions (1 day).
416−* Make and announce the first public release on Twitter/Reddit (1 day).
417−* Figure out how to use the formatter application with major text editors
418− and add the info to the readme (no estimate).
394+A list of formatting examples can be found [here](data/examples).
419395
420396[brittany]: https://hackage.haskell.org/package/brittany
421397[hindent]: https://hackage.haskell.org/package/hindent
EXAMPLES.mddeleted−296
@@ -1,296 +0,0 @@
1−We aim for a format of Haskell code that minimizes the amount of changes
2−necessary when modifying a line. For instance the indentation of any
3−given fragment of code should not depend on the length of identifiers.
4−
5−```Haskell
6−longFunctionName :: a
7− -> b
8− -> c
9− -> d
10− -> (a, b, c, d)
11−```
12−
13−Renaming the function requires changing all the lines to
14−```Haskell
15−f :: a
16− -> b
17− -> c
18− -> d
19− -> (a, b, c, d)
20−```
21−
22−A preferred alternative is to format like
23−```Haskell
24−longFunctionName
25− :: a
26− -> b
27− -> c
28− -> d
29− -> (a, b, c, d)
30−```
31−
32−We are grabbing some inspiration from
33−[Elm](https://elm-lang.org/docs/style-guide)
34−and
35−[Tweag's](https://github.com/tweag/guides/blob/master/style/Haskell.md)
36−style guides.
37−
38−The following examples show how a program is formatted in
39−multiple lines when the user introduces linebreaks. Otherwise,
40−the programs would be written in one line.
41−
42−### Function types
43−
44−```Haskell
45−functionName
46− :: (C1, C2, C3)
47− => a
48− -> b
49− -> c
50− -> d
51− -> (a, b, c, d)
52−```
53−
54−Context
55−```Haskell
56−functionName
57− :: ( C1
58− , C2
59− , C3
60− , C4
61− , C5
62− )
63− => a
64− -> b
65− -> c
66− -> d
67− -> (a, b, c, d)
68−```
69−
70−Arguments
71−```Haskell
72−functionName
73− :: (C1, C2, C3, C4, C5)
74− => a
75− -> b
76− -> (forall a.
77− (C6, C7)
78− => LongDataTypeName
79− -> a
80− -> AnotherLongDataTypeName
81− -> b
82− -> c
83− )
84− -> (c -> d)
85− -> (a, b, c, d)
86−```
87−
88−```Haskell
89−functionName
90− :: (C1, C2, C3, C4, C5)
91− => a
92− -> b
93− -> ( LongDataTypeName
94− AnotherLongDataTypeName
95− AnotherLongDataTypeName2
96− AnotherLongDataTypeName3
97− -> a
98− -> AnotherLongDataTypeName4
99− -> b
100− -> c
101− )
102− -> (c -> d)
103− -> (a, b, c, d)
104−```
105−
106−### Expressions
107−
108−```Haskell
109−f x y z =
110− if x then longFunctionName y else anotherLongFunctionName z
111−```
112−
113−A lambda
114−```Haskell
115−f =
116− \(LongPattern x) ->
117− longFunctionName x
118−```
119−
120−Multiple lambdas
121−```Haskell
122−f =
123− \(LongPattern x) ->
124− \(LongPattern2 y) ->
125− longFunctionName x
126−```
127−
128−Lambda arguments
129−```Haskell
130−f xs =
131− forM xs $
132− \( LongPattern x
133− , LongPattern2 y
134− ) ->
135− longFunctionName x
136−```
137−
138−There is a do block. Note the change of indentation in the
139−body of `forM`.
140−```Haskell
141−f xs = do
142− forM xs $
143− \( LongPattern x
144− , LongPattern2 y
145− ) ->
146− longFunctionName x
147−```
148−
149−`if` expression
150−```Haskell
151−f x y z =
152− if x then
153− longFunctionName x y
154− else
155− anotherLongFunctionName x z
156−```
157−
158−`if` expression with monadic blocks
159−```Haskell
160−f x y z =
161− if x then do
162− longFunctionName1 x y
163− longFunctionName2 x y
164− else do
165− anotherLongFunctionName1 x z
166− anotherLongFunctionName2 x z
167−```
168−
169−Monadic blocks
170−```Haskell
171−f x y z = do
172− functionName1 x y
173− functionName2 x z
174−```
175−
176−`case` expression
177−```Haskell
178−f x y z = case
179− Just w -> functionName x y w
180− Nothing -> functionName x y z
181−```
182−
183−Branches of `case` expression
184−```Haskell
185−f x y z = case
186− Just w ->
187− longFunctionName x y w
188− Nothing ->
189− anotherLongFunctionName x y z
190−```
191−
192−A list of arguments
193−```Haskell
194−f
195− (LongPattern x)
196− (AnotherLongPattern y)
197− =
198− functionName x y
199−```
200−
201−Guards
202−```Haskell
203−f x y
204− | x > y = True
205− | otherwise = False
206−```
207−
208−The right-hand side of guards
209−```Haskell
210−f x y
211− | x > y =
212− longFunctionName y
213− | otherwise =
214− anotherLongFunctionName x
215−```
216−
217−Long guards
218−```Haskell
219−function x y z w y
220− | x > y
221− , y > z
222− , z > w
223− , w > z
224− =
225− longFunctionName y
226− | otherwise =
227− anotherLongFunctionName x
228−```
229−
230−### Data type declarations
231−
232−Declaration
233−```Haskell
234−data A
235− = B
236− | C
237− | D
238− | E
239− | F
240− | G
241−```
242−
243−TODO: GADTs, record syntax, type families
244−
245−### Comments
246−
247−```Haskell
248−{- When a comment is not preceded with elements on the same line,
249− they are indented as the elements in the enclosing AST node or
250− braces/parenthesis/brackets.
251− If it is between AST nodes, it is indented as the following
252− node.
253− If the end-of-file follows, then indent to column 0.
254−-}
255−
256−f = g {- When there are preceding elements, keep single-line comments in the same line. -}
257−
258−h = g
259−{- Multi-line comments can't be kept on the same line as @h = g@.
260− Otherwise, changing h or g would change the indentation of all
261− the comment lines.
262− -}
263−
264−data R = R
265− {- This comment always follows the R constructor -}
266− { f1 :: T1
267− {- A comment not preceded by other elements -}
268− {- Another comment -}
269− , f2 :: T2
270− , f3 :: T3
271− }
272−```
273−
274−```Haskell
275−{- a comment line -}
276−f = h
277− where
278− h = g
279− -- indented the same as g
280− g = False
281−```
282−
283−This example
284−```Haskell
285−data R = R {- This comment always follows the R constructor -}
286− { f1 :: T1, {- An inner comment -} {- Another inner comment -} f2 :: T2, f3 :: T3}
287−```
288−is reformatted to
289−```Haskell
290−data R = R
291− {- This comment always follows the R constructor -}
292− { f1 :: T1 {- An inner comment -} {- Another inner comment -}
293− , f2 :: T2
294− , f3 :: T3
295− }
296−```
LICENSE.md+1−1
@@ -1,4 +1,4 @@
1−Copyright © 2018–2019 Tweag I/O
1+Copyright © 2018–present Tweag I/O
22
33All rights reserved.
44
README.md+119−28
@@ -1,26 +1,29 @@
11# Ormolu
22
3−[![CircleCI](https://circleci.com/gh/tweag/ormolu/tree/master.svg?style=svg&circle-token=cfd37a39265561eb44e608f97cf953cb2a394c03)](https://circleci.com/gh/tweag/ormolu/tree/master)
3+[![License BSD3](https://img.shields.io/badge/license-BSD3-brightgreen.svg)](http://opensource.org/licenses/BSD-3-Clause)
4+[![Hackage](https://img.shields.io/hackage/v/ormolu.svg?style=flat)](https://hackage.haskell.org/package/ormolu)
5+[![Stackage Nightly](http://stackage.org/package/ormolu/badge/nightly)](http://stackage.org/nightly/package/ormolu)
6+[![Stackage LTS](http://stackage.org/package/ormolu/badge/lts)](http://stackage.org/lts/package/ormolu)
7+[![Build status](https://badge.buildkite.com/8e3b0951f3652b77e1c422b361904136a539b0522029156354.svg?branch=master)](https://buildkite.com/tweag-1/ormolu)
48
5−Ormolu is a formatter for Haskell source code. The projects was created with
6−the following features in mind:
9+Ormolu is a formatter for Haskell source code. The project was created with
10+the following goals in mind:
711
812* Using GHC's own parser to avoid parsing problems caused by
913 [`haskell-src-exts`][haskell-src-exts].
10−* Let some whitespace be programmable. The layout of the input
11− influence the layout choices in the output. This means that the
12− choices between single-line/multi-line layouts in each particular
13− situation are made by the user, not by an algorithm. This makes the
14− implementation simpler and leaves some control to the user while
15− still guaranteeing that the formatted code is stylistically
16− consistent.
17−* Writing code in such a way so it's easy to modify and maintain. Roughly,
18− it means that the project follows the path of [`hindent`][hindent] and is
19− very much about printing AST in a particular way.
14+* Let some whitespace be programmable. The layout of the input influences
15+ the layout choices in the output. This means that the choices between
16+ single-line/multi-line layouts in each particular situation are made by
17+ the user, not by an algorithm. This makes the implementation simpler and
18+ leaves some control to the user while still guaranteeing that the
19+ formatted code is stylistically consistent.
20+* Writing code in such a way so it's easy to modify and maintain.
2021* Implementing one “true” formatting style which admits no configuration.
2122* That formatting style aims to result in minimal diffs while still
2223 remaining very close to “conventional” Haskell formatting people use.
23−* Idempotency: formatting already formatted code doesn't change it.
24+* Choose a style compatible with modern dialects of Haskell. As new Haskell
25+ extensions enter broad use, we may change the style to accommodate them.
26+* Idempotence: formatting already formatted code doesn't change it.
2427* Be well-tested and robust to the point that it can be used in large
2528 projects without exposing unfortunate, disappointing bugs here and there.
2629
@@ -29,7 +32,7 @@ the following features in mind:
2932The easiest way to build the project is with Nix:
3033
3134```console
32−$ nix-build
35+$ nix-build -A ormolu
3336```
3437
3538Or with `cabal-install` from the Nix shell:
@@ -42,11 +45,36 @@ Alternatively, `stack` could be used with a `stack.yaml` file as follows.
4245
4346```console
4447$ cat stack.yaml
45−resolver: lts-13.19
48+resolver: lts-16.0
4649packages:
4750- '.'
4851
49−$ stack build
52+$ stack build # to build
53+$ stack install # to install
54+```
55+
56+To use Ormolu directly from GitHub with Nix, this snippet may come in handy:
57+
58+```nix
59+# This overlay adds Ormolu straight from GitHub.
60+self: super:
61+
62+let source = super.fetchFromGitHub {
63+ owner = "tweag";
64+ repo = "ormolu";
65+ rev = "de279d80122b287374d4ed87c7b630db1f157642"; # update as necessary
66+ sha256 = "0qrxfk62ww6b60ha9sqcgl4nb2n5fhf66a65wszjngwkybwlzmrv"; # as well
67+ };
68+ ormolu = import source { pkgs = self; };
69+in {
70+ haskell = super.haskell // {
71+ packages = super.haskell.packages // {
72+ "${ormolu.ormoluCompiler}" = super.haskell.packages.${ormolu.ormoluCompiler}.override {
73+ overrides = ormolu.ormoluOverlay;
74+ };
75+ };
76+ };
77+}
5078```
5179
5280## Usage
@@ -64,27 +92,90 @@ formatted output.
6492$ ormolu --mode inplace Module.hs
6593```
6694
67−A configuration file can specify the language extensions to use by default.
95+Use `find` to format a tree recursively:
6896
6997```console
70−$ cat ormolu.yaml
71−ghc-opts:
72− - -XLambdaCase
73−unsafe: False
74−debug: False
98+$ ormolu --mode inplace $(find . -name '*.hs')
99+```
100+
101+## Magic comments
102+
103+Ormolu understands two magic comments:
104+
105+```haskell
106+{- ORMOLU_DISABLE -}
107+```
108+
109+and
110+
111+```haskell
112+{- ORMOLU_ENABLE -}
113+```
114+
115+This allows us to disable formatting selectively for code between these
116+markers or disable it for the entire file. To achieve the latter, just put
117+`{- ORMOLU_DISABLE -}` at the very top. Note that the source code should
118+still be parseable even without the “excluded” part. Because of that the
119+magic comments cannot be placed arbitrary, but should rather enclose
120+independent top-level definitions.
121+
122+## Current limitations
123+
124+* CPP support is experimental. CPP is virtually impossible to handle
125+ correctly, so we process them as a sort of unchangeable snippets. This
126+ works only in simple cases when CPP conditionals surround top-level
127+ declarations. See the [CPP][design-cpp] section in the design notes for
128+ a discussion of the dangers.
129+* Input modules should be parsable by Haddock, which is a bit stricter
130+ criterion than just being valid Haskell modules.
131+* Various minor idempotence issues, most of them are related to comments.
75132
76−$ ormolu -c ormolu.yaml Module.hs
133+## Running on Hackage
134+
135+It's possible to try Ormolu on arbitrary packages from Hackage. For that
136+execute (from the root of the cloned repo):
137+
138+```console
139+$ nix-build -A hackage.<package>
140+```
141+
142+Then inspect `result/log.txt` for possible problems. The derivation will
143+also contain formatted `.hs` files for inspection and original inputs with
144+`.hs-original` extension (those are with CPP dropped, exactly what is fed
145+into Ormolu).
146+
147+## Editor integration
148+
149+We know of the following editor integrations:
150+
151+* [Emacs][emacs-package]
152+* [VS Code][vs-code-plugin]
153+* vim: [neoformat][neoformat], [vim-ormolu][vim-ormolu]
154+
155+## Arch Linux
156+
157+To install Ormolu on Arch Linux, one can use [the package on AUR][aur]:
158+
159+```console
160+yay -S ormolu
77161```
78162
79163## Contributing
80164
81−See [CONTRIBUTING.md](./CONTRIBUTING.md).
165+See [CONTRIBUTING.md][contributing].
82166
83167## License
84168
85−See [LICENSE.md](./LICENSE.md).
169+See [LICENSE.md][license].
86170
87−Copyright © 2018–2019 Tweag I/O
171+Copyright © 2018–present Tweag I/O
88172
173+[design-cpp]: https://github.com/tweag/ormolu/blob/master/DESIGN.md#cpp
174+[contributing]: https://github.com/tweag/ormolu/blob/master/CONTRIBUTING.md
175+[license]: https://github.com/tweag/ormolu/blob/master/LICENSE.md
89176[haskell-src-exts]: https://hackage.haskell.org/package/haskell-src-exts
90−[hindent]: https://hackage.haskell.org/package/hindent
177+[emacs-package]: https://github.com/vyorkin/ormolu.el
178+[vs-code-plugin]: https://marketplace.visualstudio.com/items?itemName=sjurmillidahl.ormolu-vscode
179+[vim-ormolu]: https://github.com/sdiehl/vim-ormolu
180+[neoformat]: https://github.com/sbdchd/neoformat
181+[aur]: https://aur.archlinux.org/packages/ormolu
app/Main.hs+160−92
@@ -1,135 +1,203 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE LambdaCase #-}
33{-# LANGUAGE RecordWildCards #-}
44{-# LANGUAGE TemplateHaskell #-}
5+{-# LANGUAGE TypeApplications #-}
56
67module Main (main) where
78
9+import Control.Exception (SomeException, displayException, try)
810import Control.Monad
9−import Data.List (intercalate)
11+import Data.Bool (bool)
12+import Data.Either (lefts)
13+import Data.List (intercalate, sort)
14+import qualified Data.Text.IO as TIO
1015import Data.Version (showVersion)
1116import Development.GitRev
1217import Options.Applicative
1318import Ormolu
19+import Ormolu.Parser (manualExts)
20+import Ormolu.Utils (showOutputable)
1421import Paths_ormolu (version)
1522import System.Exit (ExitCode (..), exitWith)
16−import qualified Data.Text.IO as TIO
17−import qualified Data.Yaml as Yaml
23+import System.IO (hPutStrLn, stderr)
1824
1925-- | Entry point of the program.
20−
2126main :: IO ()
2227main = withPrettyOrmoluExceptions $ do
2328 Opts {..} <- execParser optsParserInfo
24− config <- case optConfigFile of
25− Nothing -> return optConfig
26− Just path -> do
27− config <- Yaml.decodeFileThrow path
28− return (config <> optConfig)
29− r <- ormoluFile config optInputFile
30− case optMode of
31− Stdout ->
32− TIO.putStr r
33− InPlace ->
34− TIO.writeFile optInputFile r
35− Check -> do
36− r' <- TIO.readFile optInputFile
37− when (r /= r') . exitWith $
38− ExitFailure 100 -- 100 is different to all the other exit code that
39− -- are emitted either from an 'OrmoluException' or
40− -- from 'error' and 'notImplemented'.
29+ let formatOne' = formatOne optMode optConfig
30+ case optInputFiles of
31+ [] -> formatOne' Nothing
32+ ["-"] -> formatOne' Nothing
33+ [x] -> formatOne' (Just x)
34+ xs -> do
35+ -- It is possible to get IOException, error's and 'OrmoluException's
36+ -- from 'formatOne', so we just catch everything.
37+ errs <-
38+ lefts <$> mapM (try @SomeException . formatOne' . Just) (sort xs)
39+ unless (null errs) $ do
40+ mapM_ (hPutStrLn stderr . displayException) errs
41+ exitWith (ExitFailure 102)
42+
43+-- | Format a single input.
44+formatOne ::
45+ -- | Mode of operation
46+ Mode ->
47+ -- | Configuration
48+ Config RegionIndices ->
49+ -- | File to format or stdin as 'Nothing'
50+ Maybe FilePath ->
51+ IO ()
52+formatOne mode config = \case
53+ Nothing -> do
54+ r <- ormoluStdin config
55+ case mode of
56+ Stdout -> TIO.putStr r
57+ _ -> do
58+ hPutStrLn
59+ stderr
60+ "This feature is not supported when input comes from stdin."
61+ -- 101 is different from all the other exit codes we already use.
62+ exitWith (ExitFailure 101)
63+ Just inputFile -> do
64+ originalInput <- TIO.readFile inputFile
65+ formattedInput <- ormoluFile config inputFile
66+ case mode of
67+ 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
75+ Check -> do
76+ when (formattedInput /= originalInput) $
77+ -- 100 is different to all the other exit code that are emitted
78+ -- either from an 'OrmoluException' or from 'error' and
79+ -- 'notImplemented'.
80+ exitWith (ExitFailure 100)
4181
4282----------------------------------------------------------------------------
4383-- Command line options parsing.
4484
4585data Opts = Opts
46− { optMode :: !Mode
47− -- ^ Mode of operation
48− , optConfigFile :: !(Maybe FilePath)
49− -- ^ Location of configuration file (optional)
50− , optConfig :: !Config
51− -- ^ Ormolu 'Config'
52− , optInputFile :: !FilePath
53− -- ^ Input source file
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]
5492 }
5593
5694-- | Mode of operation.
57−
5895data Mode
59− = Stdout -- ^ Output formatted source code to stdout
60− | InPlace -- ^ Overwrite original file
61− | Check -- ^ Exit with non-zero status code if
62− -- source is not already formatted
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
63103 deriving (Eq, Show)
64104
65105optsParserInfo :: ParserInfo Opts
66−optsParserInfo = info (helper <*> ver <*> optsParser) . mconcat $
67− [ fullDesc
68− , progDesc ""
69− , header ""
70− ]
106+optsParserInfo =
107+ info (helper <*> ver <*> exts <*> optsParser) . mconcat $
108+ [ fullDesc,
109+ progDesc "",
110+ header ""
111+ ]
71112 where
72113 ver :: Parser (a -> a)
73− ver = infoOption verStr . mconcat $
74− [ long "version"
75− , short 'v'
76− , help "Print version of the program"
77− ]
78− verStr = intercalate "\n"
79− [ unwords
80− [ "ormolu"
81− , showVersion version
82− , $gitBranch
83− , $gitHash
114+ ver =
115+ infoOption verStr . mconcat $
116+ [ long "version",
117+ short 'v',
118+ help "Print version of the program"
84119 ]
85− , "using ghc " ++ VERSION_ghc
86− ]
120+ verStr =
121+ intercalate
122+ "\n"
123+ [ unwords
124+ [ "ormolu",
125+ showVersion version,
126+ $gitBranch,
127+ $gitHash
128+ ],
129+ "using ghc-lib-parser " ++ VERSION_ghc_lib_parser
130+ ]
131+ exts :: Parser (a -> a)
132+ exts =
133+ infoOption displayExts . mconcat $
134+ [ long "manual-exts",
135+ help "Display extensions that need to be enabled manually"
136+ ]
137+ displayExts = unlines $ sort (showOutputable <$> manualExts)
87138
88139optsParser :: Parser Opts
89−optsParser = Opts
90− <$> (option parseMode . mconcat)
91− [ long "mode"
92− , short 'm'
93− , metavar "MODE"
94− , value Stdout
95− , help "Mode of operation: 'stdout', 'inplace', or 'check'"
96− ]
97− <*> (optional . strOption . mconcat)
98− [ long "config"
99− , short 'c'
100− , metavar "CONFIG"
101− , help "Location of configuration file"
102− ]
103− <*> configParser
104− <*> (strArgument . mconcat)
105− [ metavar "FILE"
106− , help "Haskell source file to format"
107− ]
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+ ]
108159
109−configParser :: Parser Config
110−configParser = Config
111− <$> (fmap (fmap DynOption) . many . strOption . mconcat)
112− [ long "ghc-opt"
113− , short 'o'
114− , metavar "OPT"
115− , help "GHC options to enable (e.g. language extensions)"
116− ]
117− <*> (switch . mconcat)
118− [ long "unsafe"
119− , short 'u'
120− , help "Do formatting faster but without automatic detection of defects"
121− ]
122− <*> (switch . mconcat)
123− [ long "debug"
124− , short 'd'
125− , help "Output information useful for debugging"
126− ]
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+ )
127196
128197----------------------------------------------------------------------------
129198-- Helpers
130199
131200-- | Parse 'Mode'.
132−
133201parseMode :: ReadM Mode
134202parseMode = eitherReader $ \case
135203 "stdout" -> Right Stdout
data/examples/declaration/annotation/annotation-out.hs+13−3
@@ -1,12 +1,22 @@
11{-# ANN module (5 :: Int) #-}
2+
23{-# ANN
34 module
4− ( 5
5− :: Int
5+ ( 5 ::
6+ Int
67 )
78 #-}
9+
810{-# ANN foo "hey" #-}
11+foo :: Int
12+foo = 5
13+
914{-# ANN
1015 Char
1116 (Just 42)
12− #-}{- Comment -}
17+ #-}
18+
19+data Foo = Foo Int
20+{-# ANN type Foo ("HLint: ignore") #-}
21+
22+{- Comment -}
data/examples/declaration/annotation/annotation.hs+8−2
@@ -5,10 +5,16 @@
55
66{-# ANN foo "hey" #-}
77
8−{-# ANN
9− Char
8+foo :: Int
9+foo = 5
1010
11+{-# ANN
12+ Char
1113
1214 (Just 42)#-}
1315
16+data Foo = Foo Int
17+
18+{-# ANN type Foo ("HLint: ignore") #-}
19+
1420{- Comment -}
data/examples/declaration/class/associated-data1-out.hsnew file+13
@@ -0,0 +1,13 @@
1+{-# LANGUAGE TypeFamilies #-}
2+
3+class Foo a where data FooBar a
4+
5+-- | Something.
6+class Bar a where
7+ -- | Bar bar
8+ data BarBar a
9+
10+ -- | Bar baz
11+ data
12+ BarBaz
13+ a
data/examples/declaration/class/associated-data1.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE TypeFamilies #-}
2+
3+class Foo a where data FooBar a
4+
5+-- | Something.
6+class Bar a
7+ where
8+ -- | Bar bar
9+ data BarBar a
10+ -- | Bar baz
11+ data family BarBaz
12+ a
data/examples/declaration/class/associated-data-out.hs → data/examples/declaration/class/associated-data2-out.hsrenamed+2−10
@@ -1,15 +1,6 @@
11{-# LANGUAGE TypeFamilies #-}
2−class Foo a where
3− data FooBar a
42
5−-- | Something.
6−class Bar a where
7− -- | Bar bar
8− data BarBar a
9− -- | Bar baz
10− data
11− BarBaz
12− a
3+module Main where
134
145-- | Something more.
156class Baz a where
@@ -19,6 +10,7 @@ class Baz a where
1910 a
2011 b
2112 c
13+
2214 -- | Baz baz
2315 data
2416 BazBaz
data/examples/declaration/class/associated-data.hs → data/examples/declaration/class/associated-data2.hsrenamed+2−11
@@ -1,15 +1,6 @@
1−{-# LANGUAGE TypeFamilies #-}
2−
3−class Foo a where data FooBar a
1+module Main where
42
5−-- | Something.
6−class Bar a
7− where
8− -- | Bar bar
9− data BarBar a
10− -- | Bar baz
11− data family BarBaz
12− a
3+{-# LANGUAGE TypeFamilies #-}
134
145-- | Something more.
156class Baz a where
data/examples/declaration/class/associated-type-defaults-out.hs+4−2
@@ -1,6 +1,6 @@
11{-# LANGUAGE TypeFamilies #-}
2−class Foo a where
3− type FooBar a = Int
2+
3+class Foo a where type FooBar a = Int
44
55-- | Something.
66class Bar a where
@@ -8,6 +8,7 @@ class Bar a where
88 type
99 BarBar a =
1010 BarBaz a
11+
1112 -- Define baz
1213 type
1314 BarBaz
@@ -19,6 +20,7 @@ class Baz a where
1920 type
2021 BazBar
2122 a
23+
2224 type
2325 BazBar a =
2426 Bar a
data/examples/declaration/class/associated-types1-out.hsnew file+13
@@ -0,0 +1,13 @@
1+{-# LANGUAGE TypeFamilies #-}
2+
3+class Foo a where type FooBar a
4+
5+-- | Something.
6+class Bar a where
7+ -- | Bar bar
8+ type BarBar a
9+
10+ -- | Bar baz
11+ type
12+ BarBaz
13+ a
data/examples/declaration/class/associated-types1.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE TypeFamilies #-}
2+
3+class Foo a where type FooBar a
4+
5+-- | Something.
6+class Bar a
7+ where
8+ -- | Bar bar
9+ type BarBar a
10+ -- | Bar baz
11+ type BarBaz
12+ a
data/examples/declaration/class/associated-types-out.hs → data/examples/declaration/class/associated-types2-out.hsrenamed+2−10
@@ -1,15 +1,6 @@
11{-# LANGUAGE TypeFamilies #-}
2−class Foo a where
3− type FooBar a
42
5−-- | Something.
6−class Bar a where
7− -- | Bar bar
8− type BarBar a
9− -- | Bar baz
10− type
11− BarBaz
12− a
3+module Main where
134
145-- | Something more.
156class Baz a where
@@ -19,6 +10,7 @@ class Baz a where
1910 a -- Foo
2011 b -- Bar
2112 c
13+
2214 -- | Baz baz
2315 type
2416 -- After type
data/examples/declaration/class/associated-types.hs → data/examples/declaration/class/associated-types2.hsrenamed+2−11
@@ -1,15 +1,6 @@
1−{-# LANGUAGE TypeFamilies #-}
2−
3−class Foo a where type FooBar a
1+module Main where
42
5−-- | Something.
6−class Bar a
7− where
8− -- | Bar bar
9− type BarBar a
10− -- | Bar baz
11− type BarBaz
12− a
3+{-# LANGUAGE TypeFamilies #-}
134
145-- | Something more.
156class Baz a where
data/examples/declaration/class/default-implementations-comments-out.hsnew file+26
@@ -0,0 +1,26 @@
1+module Main where
2+
3+-- | Baz
4+class Baz a where
5+ foobar :: a -> a
6+ foobar a =
7+ barbaz (bazbar a)
8+
9+ -- | Bar baz
10+ barbaz ::
11+ a -> a
12+
13+ -- | Baz bar
14+ bazbar ::
15+ a ->
16+ a
17+
18+ -- First comment
19+ barbaz a =
20+ bazbar -- Middle comment
21+ a
22+
23+ -- Last comment
24+ bazbar a =
25+ barbaz
26+ a
data/examples/declaration/class/default-implementations-comments.hsnew file+22
@@ -0,0 +1,22 @@
1+module Main where
2+
3+-- | Baz
4+class Baz a where
5+ foobar :: a -> a
6+ foobar a =
7+ barbaz (bazbar a)
8+ -- | Bar baz
9+ barbaz ::
10+ a -> a
11+ -- | Baz bar
12+ bazbar ::
13+ a ->
14+ a
15+ -- First comment
16+ barbaz a
17+ = bazbar -- Middle comment
18+ a
19+ -- Last comment
20+ bazbar a
21+ = barbaz
22+ a
data/examples/declaration/class/default-implementations-out.hs+5−24
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Foo
24class Foo a where
35 foo :: a -> a
@@ -5,28 +7,7 @@ class Foo a where
57
68-- | Bar
79class Bar a where
8− bar
9− :: a
10− -> Int
10+ bar ::
11+ a ->
12+ Int
1113 bar = const 0
12−
13−-- | Baz
14−class Baz a where
15− foobar :: a -> a
16− foobar a =
17− barbaz (bazbar a)
18− -- | Bar baz
19− barbaz
20− :: a -> a
21− -- | Baz bar
22− bazbar
23− :: a
24− -> a
25− -- First comment
26− barbaz a =
27− bazbar -- Middle comment
28− a
29− -- Last comment
30− bazbar a =
31− barbaz
32− a
data/examples/declaration/class/default-implementations.hs+2−21
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Foo
24class Foo a where
35 foo :: a -> a
@@ -9,24 +11,3 @@ class Bar a where
911 a
1012 -> Int
1113 bar = const 0
12−
13−-- | Baz
14−class Baz a where
15− foobar :: a -> a
16− foobar a =
17− barbaz (bazbar a)
18− -- | Bar baz
19− barbaz ::
20− a -> a
21− -- | Baz bar
22− bazbar ::
23− a ->
24− a
25− -- First comment
26− barbaz a
27− = bazbar -- Middle comment
28− a
29− -- Last comment
30− bazbar a
31− = barbaz
32− a
data/examples/declaration/class/default-signatures-out.hs+12−17
@@ -1,27 +1,22 @@
11{-# LANGUAGE DefaultSignatures #-}
22
3−-- | Something.
4−class Foo a where
5− -- | Foo
6− foo :: a -> String
7− default foo :: Show a => a -> String
8− foo = show
3+module Main where
94
105-- | Something else.
116class Bar a where
127 -- | Bar
13− bar
14− :: String
15− -> String
16− -> a
8+ bar ::
9+ String ->
10+ String ->
11+ a
1712 -- Pointless comment
18− default bar
19− :: ( Read a
20− , Semigroup a
21− )
22− => a
23− -> a
24− -> a
13+ default bar ::
14+ ( Read a,
15+ Semigroup a
16+ ) =>
17+ a ->
18+ a ->
19+ a
2520 -- Even more pointless comment
2621 bar
2722 a
data/examples/declaration/class/default-signatures-simple-out.hsnew file+8
@@ -0,0 +1,8 @@
1+module Main where
2+
3+-- | Something.
4+class Foo a where
5+ -- | Foo
6+ foo :: a -> String
7+ default foo :: Show a => a -> String
8+ foo = show
data/examples/declaration/class/default-signatures-simple.hsnew file+8
@@ -0,0 +1,8 @@
1+module Main where
2+
3+-- | Something.
4+class Foo a where
5+ -- | Foo
6+ foo :: a -> String
7+ default foo :: Show a => a -> String
8+ foo = show
data/examples/declaration/class/default-signatures.hs+2−7
@@ -1,11 +1,6 @@
1−{-# LANGUAGE DefaultSignatures #-}
1+module Main where
22
3−-- | Something.
4−class Foo a where
5− -- | Foo
6− foo :: a -> String
7− default foo :: Show a => a -> String
8− foo = show
3+{-# LANGUAGE DefaultSignatures #-}
94
105-- | Something else.
116class Bar a
data/examples/declaration/class/dependency-super-classes-out.hs+15−10
@@ -1,20 +1,25 @@
11{-# LANGUAGE FunctionalDependencies #-}
22
3+module Main where
4+
35-- | Something.
46class (MonadReader r s, MonadWriter w m) => MonadState s m | m -> s where
57 get :: m s
68 put :: s -> m ()
79
810-- | 'MonadParsec'
9−class ( Stream s -- Token streams
10− , MonadPlus m -- Potential for failure
11− )
12− => MonadParsec e s m
13− | m -> e s where
11+class
12+ ( Stream s, -- Token streams
13+ MonadPlus m -- Potential for failure
14+ ) =>
15+ MonadParsec e s m
16+ | m -> e s
17+ where
1418 -- | 'getState' returns state
15− getState
16− :: m s
19+ getState ::
20+ m s
21+
1722 -- | 'putState' sets state
18− putState
19− :: s
20− -> m ()
23+ putState ::
24+ s ->
25+ m ()
data/examples/declaration/class/dependency-super-classes.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13{-# LANGUAGE FunctionalDependencies #-}
24
35-- | Something.
data/examples/declaration/class/empty-classes-out.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Foo!
24class Foo a
35
data/examples/declaration/class/empty-classes.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Foo!
24class Foo a where
35-- | Bar!
data/examples/declaration/class/functional-dependencies-out.hs+11−8
@@ -1,16 +1,19 @@
11{-# LANGUAGE FunctionalDependencies #-}
22
3+module Main where
4+
35-- | Something.
46class Foo a b | a -> b
57
6−class Bar a b | a -> b, b -> a where
7− bar :: a
8+class Bar a b | a -> b, b -> a where bar :: a
89
910-- | Something else.
10−class Baz a b c d
11− | a b -> c d -- Foo
12− , b c -> a d -- Bar
13− , a c -> b d -- Baz
14− , a c d -> b
15− , a b d -> a b c d where
11+class
12+ Baz a b c d
13+ | a b -> c d, -- Foo
14+ b c -> a d, -- Bar
15+ a c -> b d, -- Baz
16+ a c d -> b,
17+ a b d -> a b c d
18+ where
1619 baz :: a -> b
data/examples/declaration/class/functional-dependencies.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13{-# LANGUAGE FunctionalDependencies #-}
24
35-- | Something.
data/examples/declaration/class/multi-parameters-out.hsdeleted−29
@@ -1,29 +0,0 @@
1−{-# LANGUAGE MultiParamTypeClasses #-}
2−class Foo a b where
3− foo :: a -> b
4−
5−-- | Something.
6−class Bar a b c d where
7− bar
8− :: a
9− -> b
10− -> c
11− -> d
12−
13−class -- Before name
14− Baz where
15− baz :: Int
16−
17−-- | Something else.
18−class BarBaz
19− a -- Foo
20− b -- Bar
21− c -- Baz bar
22− d -- Baz baz
23− e -- Rest
24− f where
25− barbaz
26− :: a -> f
27− bazbar
28− :: e
29− -> f
data/examples/declaration/class/multi-parameters1-out.hsnew file+15
@@ -0,0 +1,15 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+
3+class Foo a b where foo :: a -> b
4+
5+-- | Something.
6+class Bar a b c d where
7+ bar ::
8+ a ->
9+ b ->
10+ c ->
11+ d
12+
13+class -- Before name
14+ Baz where
15+ baz :: Int
data/examples/declaration/class/multi-parameters1.hsnew file+18
@@ -0,0 +1,18 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+
3+class Foo a b where foo :: a -> b
4+
5+-- | Something.
6+class Bar a b c d
7+ where
8+ bar ::
9+ a
10+ -> b
11+ -> c
12+ -> d
13+
14+class -- Before name
15+ Baz
16+ where
17+ baz :: Int
18+
data/examples/declaration/class/multi-parameters2-out.hsnew file+19
@@ -0,0 +1,19 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+
3+module Main where
4+
5+-- | Something else.
6+class
7+ BarBaz
8+ a -- Foo
9+ b -- Bar
10+ c -- Baz bar
11+ d -- Baz baz
12+ e -- Rest
13+ f
14+ where
15+ barbaz ::
16+ a -> f
17+ bazbar ::
18+ e ->
19+ f
data/examples/declaration/class/multi-parameters.hs → data/examples/declaration/class/multi-parameters2.hsrenamed+2−16
@@ -1,20 +1,6 @@
1−{-# LANGUAGE MultiParamTypeClasses #-}
2−
3−class Foo a b where foo :: a -> b
1+module Main where
42
5−-- | Something.
6−class Bar a b c d
7− where
8− bar ::
9− a
10− -> b
11− -> c
12− -> d
13−
14−class -- Before name
15− Baz
16− where
17− baz :: Int
3+{-# LANGUAGE MultiParamTypeClasses #-}
184
195-- | Something else.
206class
data/examples/declaration/class/newlines-after-where-out.hsnew file+5
@@ -0,0 +1,5 @@
1+class Num a where
2+ (+) :: a -> a -> a
3+
4+class Num a where
5+ (+) :: a -> a -> a
data/examples/declaration/class/newlines-after-where.hsnew file+7
@@ -0,0 +1,7 @@
1+class Num a where
2+ (+) :: a -> a -> a
3+
4+class Num a where
5+
6+
7+ (+) :: a -> a -> a
data/examples/declaration/class/newlines-and-default-decls-out.hsnew file+11
@@ -0,0 +1,11 @@
1+class Foo a where
2+ foo :: a
3+ default foo :: ()
4+ foo = ()
5+ bar :: a
6+ default bar :: ()
7+ bar = ()
8+
9+ qux :: a
10+ default qux :: ()
11+ qux = ()
data/examples/declaration/class/newlines-and-default-decls.hsnew file+13
@@ -0,0 +1,13 @@
1+class Foo a where
2+ foo :: a
3+ default foo :: ()
4+ foo = ()
5+ bar :: a
6+ default bar :: ()
7+ bar = ()
8+
9+ qux :: a
10+
11+ default qux :: ()
12+
13+ qux = ()
data/examples/declaration/class/newlines-and-haddocks-out.hsnew file+23
@@ -0,0 +1,23 @@
1+class Foo a where
2+ -- | Haddock
3+ foo :: a
4+
5+ -- | Another Haddock
6+ bar :: a
7+
8+ baz :: a
9+ -- ^ Post-Haddock
10+
11+ raz :: a
12+ -- ^ Another Post-Haddock
13+
14+ -- | One more Haddock
15+ qux :: a
16+
17+ -- Comment before a Haddock
18+
19+ -- | And one more Haddock
20+ xyz :: a
21+
22+ -- | Haddock followed by a blank line
23+ abc :: a
data/examples/declaration/class/newlines-and-haddocks.hsnew file+19
@@ -0,0 +1,19 @@
1+class Foo a where
2+ -- | Haddock
3+ foo :: a
4+ -- | Another Haddock
5+ bar :: a
6+ baz :: a
7+ -- ^ Post-Haddock
8+ raz :: a
9+ -- ^ Another Post-Haddock
10+
11+ -- | One more Haddock
12+ qux :: a
13+ -- Comment before a Haddock
14+ -- | And one more Haddock
15+ xyz :: a
16+
17+ -- | Haddock followed by a blank line
18+
19+ abc :: a
data/examples/declaration/class/newlines-between-methods-out.hsnew file+17
@@ -0,0 +1,17 @@
1+class Num a where
2+ (+) :: a -> a -> a
3+ (-) :: a -> a -> a
4+ (*) :: a -> a -> a
5+
6+ -- Comment before definition
7+ negate :: a -> a
8+
9+ -- Comment after definition
10+
11+ -- Separator
12+
13+ abs :: a -> a
14+ signum :: a -> a
15+
16+ -- Comment between unrelated definitions
17+ fromInteger :: Integer -> a
data/examples/declaration/class/newlines-between-methods.hsnew file+15
@@ -0,0 +1,15 @@
1+class Num a where
2+ (+) :: a -> a -> a
3+ (-) :: a -> a -> a
4+ (*) :: a -> a -> a
5+
6+ -- Comment before definition
7+ negate :: a -> a
8+ -- Comment after definition
9+
10+ -- Separator
11+
12+ abs :: a -> a
13+ signum :: a -> a
14+ -- Comment between unrelated definitions
15+ fromInteger :: Integer -> a
data/examples/declaration/class/poly-kinded-classes-out.hs+6−4
@@ -1,7 +1,9 @@
11{-# LANGUAGE PolyKinds #-}
2+
23class Foo (a :: k)
34
4−class Bar
5− ( a -- Variable
6− :: * -- Star
7− )
5+class
6+ Bar
7+ ( a :: -- Variable
8+ * -- Star
9+ )
data/examples/declaration/class/single-parameters-out.hs+14−10
@@ -1,6 +1,7 @@
1+module Main where
2+
13-- | Something.
2−class Foo a where
3− foo :: a
4+class Foo a where foo :: a
45
56-- | Something more.
67class Bar a where
@@ -9,14 +10,17 @@ class Bar a where
910
1011class Baz a where
1112 -- | Baz
12− baz
13− :: ( a
14− , a -- ^ First argument
15− )
16− -> a -- ^ Second argument
17− -> a -- ^ Return value
13+ baz ::
14+ -- | First argument
15+ ( a,
16+ a
17+ ) ->
18+ -- | Second argument
19+ a ->
20+ -- | Return value
21+ a
1822
1923class BarBaz a where
20− barbaz
21− :: a -> b
24+ barbaz ::
25+ a -> b
2226 bazbar :: b -> a
data/examples/declaration/class/single-parameters.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Something.
24class Foo a where foo :: a
35
data/examples/declaration/class/super-classes-out.hs+9−7
@@ -2,11 +2,13 @@ class Foo a
22
33class Foo a => Bar a
44
5−class (Foo a, Bar a)
6− => Baz a
5+class
6+ (Foo a, Bar a) =>
7+ Baz a
78
8−class ( Foo a -- Foo?
9− , Bar a -- Bar?
10− , Baz a -- Baz
11− )
12− => BarBar a
9+class
10+ ( Foo a, -- Foo?
11+ Bar a, -- Bar?
12+ Baz a -- Baz
13+ ) =>
14+ BarBar a
data/examples/declaration/class/type-operators-out.hsdeleted−29
@@ -1,29 +0,0 @@
1−{-# LANGUAGE MultiParamTypeClasses #-}
2−{-# LANGUAGE TypeOperators #-}
3−class (:$) a b
4−
5−class (:&)
6− a
7− b
8−
9−class a :* b
10−
11−class a :+ -- Before operator
12− b -- After operator
13−
14−class ( f :.
15− g
16− )
17− a
18−
19−class a `Pair` b
20−
21−class a `Sum`
22− b
23−
24−class (f `Product` g) a
25−
26−class ( f `Sum`
27− g
28− )
29− a
data/examples/declaration/class/type-operators1-out.hsnew file+21
@@ -0,0 +1,21 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+{-# LANGUAGE TypeOperators #-}
3+
4+class (:$) a b
5+
6+class
7+ (:&)
8+ a
9+ b
10+
11+class a :* b
12+
13+class
14+ a -- Before operator
15+ :+ b -- After operator
16+
17+class
18+ ( f
19+ :. g
20+ )
21+ a
data/examples/declaration/class/type-operators.hs → data/examples/declaration/class/type-operators1.hsrenamed−13
@@ -17,16 +17,3 @@ class
1717class (
1818 f :. g
1919 ) a
20−
21−class
22− a`Pair`b
23−
24−class
25− a
26− `Sum` b
27−
28−class (f`Product`g)a
29−
30−class (
31− f `Sum` g
32− ) a
data/examples/declaration/class/type-operators2-out.hsnew file+16
@@ -0,0 +1,16 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+{-# LANGUAGE TypeOperators #-}
3+
4+class a `Pair` b
5+
6+class
7+ a
8+ `Sum` b
9+
10+class (f `Product` g) a
11+
12+class
13+ ( f
14+ `Sum` g
15+ )
16+ a
data/examples/declaration/class/type-operators2.hsnew file+16
@@ -0,0 +1,16 @@
1+{-# LANGUAGE MultiParamTypeClasses #-}
2+{-# LANGUAGE TypeOperators #-}
3+
4+class
5+ a`Pair`b
6+
7+class
8+ a
9+ `Sum` b
10+
11+class (f`Product`g)a
12+
13+class (
14+ f `Sum` g
15+ ) a
16+
data/examples/declaration/class/type-operators3-out.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE PolyKinds #-}
2+{-# LANGUAGE TypeFamilies #-}
3+{-# LANGUAGE TypeOperators #-}
4+{-# LANGUAGE NoStarIsType #-}
5+
6+class PNum x where
7+ type (a :: x) * (b :: x)
8+
9+instance PNum Nat where
10+ type a * b = ()
data/examples/declaration/class/type-operators3.hsnew file+7
@@ -0,0 +1,7 @@
1+{-# LANGUAGE TypeFamilies, TypeOperators, NoStarIsType, PolyKinds #-}
2+
3+class PNum x where
4+ type (a :: x) * (b :: x)
5+
6+instance PNum Nat where
7+ type a * b = ()
data/examples/declaration/data/deriving-out.hsnew file+2
@@ -0,0 +1,2 @@
1+newtype R r a = R (ReaderT r IO a)
2+ deriving (MonadReader r)
data/examples/declaration/data/deriving-strategies-out.hs+7−5
@@ -1,12 +1,14 @@
1+module Main where
2+
13-- | Something.
24newtype Foo = Foo Int
35 deriving stock (Eq, Show, Generic)
46 deriving anyclass
5− ( ToJSON
6− , FromJSON
7+ ( ToJSON,
8+ FromJSON
79 )
8− deriving newtype Num
9− deriving Monoid via (Sum Int)
10+ deriving newtype (Num)
11+ deriving (Monoid) via (Sum Int)
1012 deriving
11− Semigroup
13+ (Semigroup)
1214 via (Sum Int)
data/examples/declaration/data/deriving-strategies.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Something.
24
35newtype Foo = Foo Int
data/examples/declaration/data/deriving.hsnew file+2
@@ -0,0 +1,2 @@
1+newtype R r a = R (ReaderT r IO a)
2+ deriving (MonadReader r)
data/examples/declaration/data/empty-out.hs+1
@@ -1,2 +1,3 @@
11{-# LANGUAGE EmptyDataDecls #-}
2+
23data Foo
data/examples/declaration/data/existential-multiline-out.hs+13
@@ -1,4 +1,17 @@
11{-# LANGUAGE ExistentialQuantification #-}
2+
23data Foo
34 = forall a. MkFoo a (a -> Bool)
45 | forall a. Eq a => MkBar a
6+
7+data Bar
8+ = forall x y.
9+ Bar x y x y
10+
11+data Baz
12+ = forall x y.
13+ Baz
14+ x
15+ y
16+ x
17+ y
data/examples/declaration/data/existential-multiline.hs+7
@@ -3,3 +3,10 @@
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/existential-out.hs+3
@@ -1,2 +1,5 @@
11{-# LANGUAGE ExistentialQuantification #-}
2+
23data Foo = forall a. MkFoo a (a -> Bool)
4+
5+data Bar = forall a b. a + b => Bar a b
data/examples/declaration/data/existential.hs+2
@@ -1,3 +1,5 @@
11{-# LANGUAGE ExistentialQuantification #-}
22
33data Foo = forall a. MkFoo a (a -> Bool)
4+
5+data Bar = forall a b. a + b => Bar a b
data/examples/declaration/data/fat-multiline-out.hs+6−4
@@ -1,10 +1,12 @@
1+module Main where
2+
13-- | Something.
24data Foo
3− = Foo
5+ = -- | Foo
6+ Foo
47 Int
58 Int
6− -- ^ Foo
7− | Bar
9+ | -- | Bar
10+ Bar
811 Bool
912 Bool
10− -- ^ Bar
data/examples/declaration/data/fat-multiline.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Something.
24
35data Foo
data/examples/declaration/data/field-layout/gadt-out.hsnew file+11
@@ -0,0 +1,11 @@
1+module Main where
2+
3+-- | Foo.
4+data Foo a b where
5+ -- | Something
6+ Foo :: Foo Int Int
7+ -- | Something else
8+ Bar ::
9+ Foo
10+ Char
11+ Char
data/examples/declaration/data/field-layout/gadt.hsnew file+10
@@ -0,0 +1,10 @@
1+module Main where
2+
3+-- | Foo.
4+
5+data Foo a b where
6+ -- | Something
7+ Foo :: Foo Int Int
8+ -- | Something else
9+ Bar :: Foo Char
10+ Char
data/examples/declaration/data/field-layout/record-out.hsnew file+12
@@ -0,0 +1,12 @@
1+module Main where
2+
3+-- | Foo.
4+data Foo = Foo
5+ { -- | Something
6+ foo :: Foo Int Int,
7+ -- | Something else
8+ bar ::
9+ Bar
10+ Char
11+ Char
12+ }
data/examples/declaration/data/field-layout/record.hsnew file+11
@@ -0,0 +1,11 @@
1+module Main where
2+
3+-- | Foo.
4+
5+data Foo = Foo
6+ { foo :: Foo Int Int
7+ -- ^ Something
8+ , bar :: Bar Char
9+ Char
10+ -- ^ Something else
11+ }
data/examples/declaration/data/field-layout/variants-out.hsnew file+10
@@ -0,0 +1,10 @@
1+module Main where
2+
3+-- | Foo.
4+data Foo
5+ = -- | Something
6+ Foo Int Int
7+ | -- | Something else
8+ Bar
9+ Char
10+ Char
data/examples/declaration/data/field-layout/variants.hsnew file+10
@@ -0,0 +1,10 @@
1+module Main where
2+
3+-- | Foo.
4+
5+data Foo =
6+ Foo Int Int
7+ -- ^ Something
8+ | Bar Char
9+ Char
10+ -- ^ Something else
data/examples/declaration/data/gadt-syntax-out.hs+3−3
@@ -1,3 +1,3 @@
1−{-# LANUGAGE GADTSyntax #-}
2−data Foo where
3− MKFoo :: a -> (a -> Bool) -> Foo
1+{-# LANGUAGE GADTSyntax #-}
2+
3+data Foo where MKFoo :: a -> (a -> Bool) -> Foo
data/examples/declaration/data/gadt-syntax.hs+1−1
@@ -1,3 +1,3 @@
1−{-# LANUGAGE GADTSyntax #-}
1+{-# LANGUAGE GADTSyntax #-}
22
33data Foo where { MKFoo :: a -> (a->Bool) -> Foo }
data/examples/declaration/data/gadt/multiline-out.hs+17−13
@@ -1,21 +1,25 @@
11{-# LANGUAGE ExplicitForAll #-}
22
3+module Main where
4+
35-- | Here goes a comment.
46data Foo a where
57 -- | 'Foo' is wonderful.
6− Foo
7− :: forall a b. (Show a, Eq b) -- foo
8− -- bar
9− => a
10− -> b
11− -> Foo 'Int
8+ Foo ::
9+ forall a b.
10+ (Show a, Eq b) => -- foo
11+ -- bar
12+ a ->
13+ b ->
14+ Foo 'Int
1215 -- | But 'Bar' is also not too bad.
13− Bar
14− :: Int
15− -> Maybe Text
16− -> Foo 'Bool
16+ Bar ::
17+ Int ->
18+ Maybe Text ->
19+ Foo 'Bool
1720 -- | So is 'Baz'.
18− Baz
19− :: forall a. a
20− -> Foo 'String
21+ Baz ::
22+ forall a.
23+ a ->
24+ Foo 'String
2125 (:~>) :: Foo a -> Foo a -> Foo a
data/examples/declaration/data/gadt/multiline-where-out.hsnew file+7
@@ -0,0 +1,7 @@
1+data
2+ Foo
3+ a
4+ b
5+ c
6+ where
7+ Foo :: a -> b -> c -> Foo a b c
data/examples/declaration/data/gadt/multiline-where.hsnew file+6
@@ -0,0 +1,6 @@
1+data
2+ Foo
3+ a
4+ b
5+ c where
6+ Foo :: a -> b -> c -> Foo a b c
data/examples/declaration/data/gadt/multiline.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13{-# LANGUAGE ExplicitForAll #-}
24
35-- | Here goes a comment.
data/examples/declaration/data/gadt/multiple-declaration-out.hsnew file+15
@@ -0,0 +1,15 @@
1+data GADT0 a where
2+ GADT01, GADT02 :: Int -> GADT0 a
3+
4+data GADT1 a where
5+ GADT11,
6+ GADT12 ::
7+ Int ->
8+ GADT1 a
9+
10+data GADT2 a where
11+ GADT21,
12+ GADT21,
13+ GADT22 ::
14+ Int ->
15+ GADT2 a
data/examples/declaration/data/gadt/multiple-declaration.hsnew file+11
@@ -0,0 +1,11 @@
1+data GADT0 a where
2+ GADT01, GADT02 :: Int -> GADT0 a
3+
4+data GADT1 a where
5+ GADT11
6+ , GADT12 :: Int -> GADT1 a
7+
8+data GADT2 a where
9+ GADT21
10+ , GADT21
11+ , GADT22 :: Int -> GADT2 a
data/examples/declaration/data/gadt/record-out.hs+11−8
@@ -1,11 +1,14 @@
1+module Main where
2+
13-- | Something.
24data Foo where
35 Foo :: {fooX :: Int} -> Foo
4− Bar
5− :: { fooY :: Int
6− , fooBar, fooBaz :: Bool
7− , fooFoo
8− , barBar
9− :: Int
10− }
11− -> Foo
6+ Bar ::
7+ { fooY :: Int,
8+ fooBar, fooBaz :: Bool,
9+ fooFoo,
10+ barBar,
11+ bazBaz ::
12+ Int
13+ } ->
14+ Foo
data/examples/declaration/data/gadt/record.hs+4−1
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Something.
24
35data Foo where
@@ -5,5 +7,6 @@ data Foo where
57 Bar :: { fooY :: Int
68 , fooBar, fooBaz :: Bool
79 , fooFoo
8− , barBar :: Int
10+ , barBar
11+ , bazBaz :: Int
912 } -> Foo
data/examples/declaration/data/gadt/simple-out.hs+12−2
@@ -1,8 +1,18 @@
11{-# LANGUAGE ExplicitForAll #-}
22
3+module Main where
4+
35-- | Here goes a comment.
46data Foo a where
57 -- | 'Foo' is wonderful.
68 Foo :: forall a b. (Show a, Eq b) => a -> b -> Foo 'Int
7− Bar :: Int -> Text -> Foo 'Bool -- ^ But 'Bar' is also not too bad.
8− Baz :: forall a. a -> Foo 'String -- ^ So is 'Baz'.
9+ Bar ::
10+ Int ->
11+ Text ->
12+ -- | But 'Bar' is also not too bad.
13+ Foo 'Bool
14+ Baz ::
15+ forall a.
16+ a ->
17+ -- | So is 'Baz'.
18+ Foo 'String
data/examples/declaration/data/gadt/simple.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13{-# LANGUAGE ExplicitForAll #-}
24
35-- | Here goes a comment.
data/examples/declaration/data/gadt/strictness-out.hs+2−1
@@ -1,2 +1,3 @@
11data Foo a where
2− Foo :: !Int -> {-# UNPACK #-} !Bool -> Foo Int
2+ Foo1 :: !Int -> {-# UNPACK #-} !Bool -> Foo Int
3+ Foo2 :: {-# UNPACK #-} Maybe Int && Bool -> Foo Int
data/examples/declaration/data/gadt/strictness.hs+2−1
@@ -1,2 +1,3 @@
11data Foo a where
2− Foo :: !Int -> {-# UNPACK #-} !Bool -> Foo Int
2+ Foo1 :: !Int -> {-# UNPACK #-} !Bool -> Foo Int
3+ Foo2 :: {-# UNPACK #-} Maybe Int && Bool -> Foo Int
data/examples/declaration/data/kind-annotations-out.hsnew file+11
@@ -0,0 +1,11 @@
1+data Something (n :: Nat) = Something
2+
3+data Format (k :: *) (k' :: *) (k'' :: *)
4+
5+type Parens1 = Proxy '(a :: A, b :: (B :: *))
6+
7+type Parens2 = Proxy '((a :: A), (b :: B))
8+
9+type family Foo a where
10+ Foo '(a :: Int, b :: Bool) = Int
11+ Foo '((a :: Int), (b :: Bool)) = Int
data/examples/declaration/data/kind-annotations.hsnew file+10
@@ -0,0 +1,10 @@
1+data Something (n :: Nat) = Something
2+
3+data Format (k :: *) (k' :: *) (k'' :: *)
4+
5+type Parens1 = Proxy '(a :: A, b :: (B :: *))
6+type Parens2 = Proxy '((a :: A), (b :: B))
7+
8+type family Foo a where
9+ Foo '(a :: Int, b :: Bool) = Int
10+ Foo '((a :: Int), (b :: Bool)) = Int
data/examples/declaration/data/multiline-arg-parens-out.hs+4−2
@@ -1,8 +1,10 @@
1+module Main where
2+
13-- | Something.
24data Foo
35 = Foo
46 Bar
57 (Set Baz) -- and here we go
6− -- and that's it
8+ -- and that's it
79 Text
8− deriving Eq
10+ deriving (Eq)
data/examples/declaration/data/multiline-arg-parens.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Something.
24
35data Foo
data/examples/declaration/data/multiline-names-out.hsnew file+29
@@ -0,0 +1,29 @@
1+data
2+ Foo
3+ a
4+ b
5+ = Foo a b
6+
7+data a :-> b = Arrow (a -> b)
8+
9+data (f :* g) a = f a :* g a
10+
11+data
12+ ( f
13+ :+ g
14+ )
15+ a
16+ = L (f a)
17+ | R (g a)
18+
19+data a `Arrow` b = Arrow' (a -> b)
20+
21+data (f `Product` g) a = f a `Product` g a
22+
23+data
24+ ( f
25+ `Sum` g
26+ )
27+ a
28+ = L' (f a)
29+ | R' (g a)
data/examples/declaration/data/multiline-names.hsnew file+23
@@ -0,0 +1,23 @@
1+data Foo a
2+ b
3+ = Foo a b
4+
5+data a :-> b = Arrow (a -> b)
6+
7+data (f :* g) a = f a :* g a
8+
9+data (f
10+ :+
11+ g)
12+ a = L (f a)
13+ | R (g a)
14+
15+data a `Arrow` b = Arrow' (a -> b)
16+
17+data (f `Product` g) a = f a `Product` g a
18+
19+data (f
20+ `Sum`
21+ g)
22+ a = L' (f a)
23+ | R' (g a)
data/examples/declaration/data/multiline-out.hs+8−3
@@ -1,7 +1,12 @@
1+module Main where
2+
13-- | Here we have 'Foo'.
24data Foo
3− = Foo -- ^ One
4− | Bar Int -- ^ Two
5− | Baz -- ^ Three
5+ = -- | One
6+ Foo
7+ | -- | Two
8+ Bar Int
9+ | -- | Three
10+ Baz
611 deriving
712 (Eq, Show)
data/examples/declaration/data/multiline.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Here we have 'Foo'.
24
35data Foo
data/examples/declaration/data/newtype-out.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Something.
24newtype Foo = Foo Int
35 deriving (Eq, Show)
data/examples/declaration/data/newtype.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Something.
24
35newtype Foo = Foo Int
data/examples/declaration/data/operators-out.hsnew file+12
@@ -0,0 +1,12 @@
1+data ErrorMessage' s
2+ = -- | Show the text as is.
3+ Text s
4+ | -- | Pretty print the type.
5+ -- @ShowType :: k -> ErrorMessage@
6+ forall t. ShowType t
7+ | -- | Put two pieces of error message next
8+ -- to each other.
9+ ErrorMessage' s :<>: ErrorMessage' s
10+ | -- | Stack two pieces of error message on top
11+ -- of each other.
12+ ErrorMessage' s :$$: ErrorMessage' s
data/examples/declaration/data/operators.hsnew file+12
@@ -0,0 +1,12 @@
1+data ErrorMessage' s
2+ = -- | Show the text as is.
3+ Text s
4+ | -- | Pretty print the type.
5+ -- @ShowType :: k -> ErrorMessage@
6+ forall t. ShowType t
7+ | -- | Put two pieces of error message next
8+ -- to each other.
9+ ErrorMessage' s :<>: ErrorMessage' s
10+ | -- | Stack two pieces of error message on top
11+ -- of each other.
12+ ErrorMessage' s :$$: ErrorMessage' s
data/examples/declaration/data/partly-documented-out.hsnew file+5
@@ -0,0 +1,5 @@
1+data Optimisation
2+ = PETransform
3+ | -- | partial eval and associated transforms
4+ GeneralisedNatHack
5+ deriving (Show, Eq, Generic)
data/examples/declaration/data/partly-documented.hsnew file+2
@@ -0,0 +1,2 @@
1+data Optimisation = PETransform | GeneralisedNatHack -- ^ partial eval and associated transforms
2+ deriving (Show, Eq, Generic)
data/examples/declaration/data/record-multi-const-out.hsnew file+17
@@ -0,0 +1,17 @@
1+module Main where
2+
3+-- | Something.
4+data Foo
5+ = Foo
6+ { -- | X
7+ fooX :: Int,
8+ -- | Y
9+ fooY :: Int
10+ }
11+ | Bar
12+ { -- | X
13+ barX :: Int,
14+ -- | Y
15+ barY :: Int
16+ }
17+ deriving (Eq, Show)
data/examples/declaration/data/record-multi-const.hsnew file+13
@@ -0,0 +1,13 @@
1+module Main where
2+
3+-- | Something.
4+
5+data Foo = Foo
6+ { fooX :: Int -- ^ X
7+ , fooY :: Int -- ^ Y
8+ } |
9+ Bar
10+ { barX :: Int -- ^ X
11+ , barY :: Int -- ^ Y
12+ }
13+ deriving (Eq, Show)
data/examples/declaration/data/record-out.hs+21−16
@@ -1,18 +1,23 @@
1+module Main where
2+
13-- | Something.
2−data Foo
3− = Foo
4− { fooX :: Int -- ^ X
5− , fooY :: Int -- ^ Y
6− , fooBar, fooBaz :: NonEmpty (Identity Bool) -- ^ BarBaz
7− , fooGag
8− , fooGog
9− :: NonEmpty
10− ( Indentity
11− Bool
12− )
13− -- ^ GagGog
14− , fooFoo
15− , barBar
16− :: Int -- ^ Huh!
17− }
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+ }
1823 deriving (Eq, Show)
data/examples/declaration/data/record-singleline-out.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Something.
24data Foo = Foo {fooX :: Int, fooY :: Int}
35 deriving (Eq, Show)
data/examples/declaration/data/record-singleline.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Something.
24
35data Foo = Foo { fooX :: Int , fooY :: Int }
data/examples/declaration/data/record.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Something.
24
35data Foo = Foo
data/examples/declaration/data/simple-broken-out.hs+5−4
@@ -1,8 +1,9 @@
1+module Main where
2+
13-- | Here we go.
2−data Foo
3− = Foo {unFoo :: Int}
4− deriving Eq
4+data Foo = Foo {unFoo :: Int}
5+ deriving (Eq)
56
67-- | And once again.
78data Bar = Bar {unBar :: Int}
8− deriving Eq
9+ deriving (Eq)
data/examples/declaration/data/simple-broken.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Here we go.
24
35data Foo
data/examples/declaration/data/simple-out.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | And here we have 'Foo'.
24data Foo = Foo | Bar Int | Baz
35 deriving (Eq, Show)
data/examples/declaration/data/simple.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | And here we have 'Foo'.
24
35data Foo = Foo | Bar Int | Baz
data/examples/declaration/data/strictness-out.hs+5−1
@@ -1,2 +1,6 @@
1+module Main where
2+
13-- | Something.
2−data Foo = Foo !Int {-# UNPACK #-} !Bool {-# NOUNPACK #-} !String
4+data Foo
5+ = Foo1 !Int {-# UNPACK #-} !Bool {-# NOUNPACK #-} !String
6+ | Foo2 {a :: {-# UNPACK #-} Maybe Int && Bool}
data/examples/declaration/data/strictness.hs+5−1
@@ -1,3 +1,7 @@
1+module Main where
2+
13-- | Something.
24
3−data Foo = Foo !Int {-# UNPACK #-} !Bool {-# NOUNPACK #-} !String
5+data Foo
6+ = Foo1 !Int {-# UNPACK #-} !Bool {-# NOUNPACK #-} !String
7+ | Foo2 { a :: {-# UNPACK #-} Maybe Int && Bool }
data/examples/declaration/data/unnamed-field-comment-0-out.hsnew file+7
@@ -0,0 +1,7 @@
1+data Foo
2+ = -- | Bar
3+ Bar
4+ Field1
5+ -- ^ Field 1
6+ Field2
7+ -- ^ Field 2
data/examples/declaration/data/unnamed-field-comment-0.hsnew file+5
@@ -0,0 +1,5 @@
1+data Foo
2+ = -- | Bar
3+ Bar
4+ Field1 -- ^ Field 1
5+ Field2 -- ^ Field 2
data/examples/declaration/data/unnamed-field-comment-1-out.hsnew file+5
@@ -0,0 +1,5 @@
1+data X
2+ = B
3+ !Int
4+ -- ^ y
5+ C
data/examples/declaration/data/unnamed-field-comment-1.hsnew file+4
@@ -0,0 +1,4 @@
1+data X
2+ = B
3+ !Int -- ^ y
4+ C
data/examples/declaration/data/with-comment-out.hsnew file+4
@@ -0,0 +1,4 @@
1+data A
2+ = B -- C
3+ | -- D
4+ E
data/examples/declaration/data/with-comment.hsnew file+5
@@ -0,0 +1,5 @@
1+data A =
2+ B -- C
3+
4+ -- D
5+ | E
data/examples/declaration/data/with-weird-haddock-out.hsnew file+4
@@ -0,0 +1,4 @@
1+data PlusLevel' t
2+ = -- | @n + ℓ@.
3+ Plus Integer (LevelAtom' t)
4+ deriving (Show, Data)
data/examples/declaration/data/with-weird-haddock.hsnew file+2
@@ -0,0 +1,2 @@
1+data PlusLevel' t = Plus Integer (LevelAtom' t) -- ^ @n + ℓ@.
2+ deriving (Show, Data)
data/examples/declaration/default/default-out.hs+3−3
@@ -1,7 +1,7 @@
11default (Int, Foo, Bar)
22
33default
4− ( Int
5− , Foo
6− , Bar
4+ ( Int,
5+ Foo,
6+ Bar
77 )
data/examples/declaration/deriving/multiline-out.hs−20
@@ -14,26 +14,6 @@ deriving newtype instance
1414 Data
1515 Foo
1616
17−deriving instance
18− {-# OVERLAPPABLE #-}
19− Ord
20− Foo
21−
22−deriving instance
23− {-# OVERLAPPING #-}
24− Num
25− Foo
26−
27−deriving instance
28− {-# OVERLAPS #-}
29− Read
30− Foo
31−
32−deriving instance
33− {-# INCOHERENT #-}
34− Show
35− Foo
36−
3717deriving via
3818 Foo
3919 Int
data/examples/declaration/deriving/multiline.hs−17
@@ -11,23 +11,6 @@ deriving newtype instance
1111 Data
1212 Foo
1313
14−deriving instance
15− {-# OVERLAPPABLE #-}
16− Ord
17− Foo
18−deriving instance
19− {-# OVERLAPPING #-}
20− Num
21− Foo
22−deriving instance
23− {-# OVERLAPS #-}
24− Read
25− Foo
26−deriving instance
27− {-# INCOHERENT #-}
28− Show
29− Foo
30−
3114deriving via Foo
3215 Int
3316 instance Triple
data/examples/declaration/deriving/overlapping-out.hsnew file+19
@@ -0,0 +1,19 @@
1+deriving instance
2+ {-# OVERLAPPABLE #-}
3+ Ord
4+ Foo
5+
6+deriving instance
7+ {-# OVERLAPPING #-}
8+ Num
9+ Foo
10+
11+deriving instance
12+ {-# OVERLAPS #-}
13+ Read
14+ Foo
15+
16+deriving instance
17+ {-# INCOHERENT #-}
18+ Show
19+ Foo
data/examples/declaration/deriving/overlapping.hsnew file+17
@@ -0,0 +1,17 @@
1+deriving instance
2+ {-# OVERLAPPABLE #-}
3+ Ord
4+ Foo
5+deriving instance
6+ {-# OVERLAPPING #-}
7+ Num
8+ Foo
9+deriving instance
10+ {-# OVERLAPS #-}
11+ Read
12+ Foo
13+deriving instance
14+ {-# INCOHERENT #-}
15+ Show
16+ Foo
17+
data/examples/declaration/foreign/foreign-export-out.hs+2−1
@@ -2,7 +2,8 @@ foreign export ccall foo :: Int -> IO Int
22
33-- | 'foreignTomFun' is a very important thing
44foreign export ccall "tomography"
5− foreignTomFun :: StablePtr Storage -> TomForegin {- Storage is bad -}
5+ foreignTomFun ::
6+ StablePtr Storage {- Storage is bad -} -> TomForegin
67
78foreign export {- We can't use capi here -} ccall "dynamic"
89 export_nullaryMeth :: (IO HRESULT) -> IO (Ptr ())
data/examples/declaration/foreign/foreign-import-out.hs+11−10
@@ -1,4 +1,5 @@
11{-# LANGUAGE CApiFFI #-}
2+
23foreign import ccall safe foo :: Int -> IO Int
34
45-- | 'bar' is a very important thing
@@ -9,16 +10,16 @@ foreign import stdcall unsafe "boo"
910 boo :: Int -> Text -> IO Array
1011
1112foreign import javascript
12− baz
13− :: String
14− -> Int
15− -> IO Foo
13+ baz ::
14+ String ->
15+ Int ->
16+ IO Foo
1617
1718foreign import {- We use capi here -} capi "pi.h value pi" c_pi :: CDouble
1819
19−foreign import stdcall "dynamic" {- This is a bad place for a comment -}
20− dyn_gluBeginSurface
21− :: FunPtr (Ptr GLUnurbs -> IO ())
22− -- ^ This 'FunPtr' is extremely dangerous, beware
23− -> Ptr GLUnurbs
24− -> IO ()
20+foreign import stdcall {- This is a bad place for a comment -} "dynamic"
21+ dyn_gluBeginSurface ::
22+ -- | This 'FunPtr' is extremely dangerous, beware
23+ FunPtr (Ptr GLUnurbs -> IO ()) ->
24+ Ptr GLUnurbs ->
25+ IO ()
data/examples/declaration/instance/associated-data-out.hs+5−3
@@ -1,9 +1,11 @@
11{-# LANGUAGE TypeFamilies #-}
2−instance Foo Int where
3− data Bar Int = IntBar Int Int
2+
3+instance Foo Int where data Bar Int = IntBar Int Int
44
55instance Foo Double where
6− newtype Bar Double
6+ newtype
7+ Bar
8+ Double
79 = DoubleBar
810 Double
911 Double
data/examples/declaration/instance/associated-data.hs+1
@@ -13,6 +13,7 @@ instance Foo Double where
1313
1414instance Foo [a]
1515 where
16+
1617 data Bar [a] =
1718 ListBar [Bar a]
1819 data Baz [a] =
data/examples/declaration/instance/associated-types-out.hs+3−2
@@ -1,12 +1,13 @@
11{-# LANGUAGE TypeFamilies #-}
2−instance Foo Int where
3− type Bar Int = Double
2+
3+instance Foo Int where type Bar Int = Double
44
55instance Foo Double where
66 type
77 Bar
88 Double =
99 [Double]
10+
1011 type
1112 Baz Double =
1213 [Double]
data/examples/declaration/instance/associated-types.hs+2
@@ -9,5 +9,7 @@ instance Foo Double
99 Double
1010 =
1111 [Double]
12+
13+
1214 type instance Baz Double
1315 = [Double]
data/examples/declaration/instance/contexts-comments-out.hsnew file+17
@@ -0,0 +1,17 @@
1+instance
2+ ( Read a, -- Foo
3+ Read b,
4+ Read
5+ ( c, -- Bar
6+ d
7+ )
8+ ) =>
9+ Read
10+ ( a, -- Baz
11+ b,
12+ ( c, -- Quux
13+ d
14+ )
15+ )
16+ where
17+ readsPrec = undefined
data/examples/declaration/instance/contexts-comments.hsnew file+18
@@ -0,0 +1,18 @@
1+instance (
2+ Read a, -- Foo
3+ Read b
4+ , Read (
5+ c, -- Bar
6+ d
7+ )
8+ )
9+ =>
10+ Read (
11+ a, -- Baz
12+ b
13+ ,(
14+ c, -- Quux
15+ d
16+ )
17+ ) where
18+ readsPrec = undefined
data/examples/declaration/instance/contexts-out.hs+16−7
@@ -1,9 +1,18 @@
1−instance Eq a => Eq [a] where
2− (==) _ _ = False
1+instance Eq a => Eq [a] where (==) _ _ = False
32
4−instance ( Ord a
5− , Ord b
6− )
7− => Ord
8− (a, b) where
3+instance
4+ ( Ord a,
5+ Ord b
6+ ) =>
7+ Ord (a, b)
8+ where
99 compare _ _ = GT
10+
11+instance
12+ (Show a, Show b) =>
13+ Show
14+ ( a,
15+ b
16+ )
17+ where
18+ showsPrec _ _ = showString ""
data/examples/declaration/instance/contexts.hs+7
@@ -5,3 +5,10 @@ instance (
55 Ord b
66 ) => Ord (a,b) where
77 compare _ _ = GT
8+
9+instance (Show a, Show b) =>
10+ Show (
11+ a,
12+ b
13+ ) where
14+ showsPrec _ _ = showString ""
data/examples/declaration/instance/data-family-instances-gadt-out.hsnew file+13
@@ -0,0 +1,13 @@
1+{-# LANGUAGE GADTSyntax #-}
2+{-# LANGUAGE TypeFamilies #-}
3+
4+data instance Bar Int a where
5+ SameBar ::
6+ Bar
7+ Int
8+ Int
9+ CloseBar :: Bar Int Double
10+ OtherBar ::
11+ Bar
12+ Int
13+ a
data/examples/declaration/instance/data-family-instances-gadt.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE GADTSyntax #-}
2+{-# LANGUAGE TypeFamilies #-}
3+data instance Bar Int a where
4+ SameBar
5+ :: Bar Int
6+ Int
7+ CloseBar :: Bar Int Double
8+ OtherBar
9+ :: Bar Int
10+ a
data/examples/declaration/instance/data-family-instances-newtype-out.hsnew file+6
@@ -0,0 +1,6 @@
1+{-# LANGUAGE GADTSyntax #-}
2+{-# LANGUAGE TypeFamilies #-}
3+
4+newtype instance Foo [Double] = DoubleListFoo
5+ { unDoubleListFoo :: Double
6+ }
data/examples/declaration/instance/data-family-instances-newtype.hsnew file+6
@@ -0,0 +1,6 @@
1+{-# LANGUAGE GADTSyntax #-}
2+{-# LANGUAGE TypeFamilies #-}
3+newtype instance Foo [Double] = DoubleListFoo {
4+ unDoubleListFoo :: Double
5+}
6+
data/examples/declaration/instance/data-family-instances-out.hs+8−19
@@ -1,31 +1,20 @@
11{-# LANGUAGE GADTSyntax #-}
22{-# LANGUAGE TypeFamilies #-}
3+
34data instance Foo Int = FooInt Int
45
5−data instance Foo [Int]
6+data instance
7+ Foo
8+ [Int]
69 = IntListFoo
7− ( Int
8− , Int
10+ ( Int,
11+ Int
912 )
10− ( Double
11− , Double
13+ ( Double,
14+ Double
1215 )
1316
14−newtype instance Foo [Double]
15− = DoubleListFoo
16− { unDoubleListFoo :: Double
17− }
18−
1917data instance Bar Double a
2018 = DoubleBar
2119 Double
2220 (Bar a)
23−
24−data instance Bar Int a where
25− SameBar
26− :: Bar Int
27− Int
28− CloseBar :: Bar Int Double
29− OtherBar
30− :: Bar Int
31− a
data/examples/declaration/instance/data-family-instances.hs−12
@@ -13,20 +13,8 @@ data instance
1313 Double
1414 )
1515
16−newtype instance Foo [Double] = DoubleListFoo {
17− unDoubleListFoo :: Double
18−}
19−
2016data instance Bar Double a =
2117 DoubleBar
2218 Double
2319 (Bar a)
2420
25−data instance Bar Int a where
26− SameBar
27− :: Bar Int
28− Int
29− CloseBar :: Bar Int Double
30− OtherBar
31− :: Bar Int
32− a
data/examples/declaration/instance/instance-sigs-multiple-out.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE InstanceSigs #-}
2+
3+instance Applicative [] where
4+ pure ::
5+ a ->
6+ [a]
7+ pure a = [a]
8+ (<*>) ::
9+ [a] -> [a] -> [a]
10+ (<*>) _ _ = []
data/examples/declaration/instance/instance-sigs-multiple.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE InstanceSigs #-}
2+
3+instance Applicative [] where
4+ pure ::
5+ a
6+ -> [a]
7+ pure a = [a]
8+ (<*>)
9+ :: [ a ] -> [ a ] -> [ a ]
10+ (<*>) _ _ = []
data/examples/declaration/instance/instance-sigs-out.hs+5−13
@@ -1,23 +1,15 @@
11{-# LANGUAGE InstanceSigs #-}
2+
23instance Eq Int where
34 (==) :: Int -> Int -> Bool
45 (==) _ _ = False
56
67instance Ord Int where
7− compare
8− :: Int
9− -> Int
10− -> Ordering
8+ compare ::
9+ Int ->
10+ Int ->
11+ Ordering
1112 compare
1213 _
1314 _ =
1415 GT
15−
16−instance Applicative [] where
17− pure
18− :: a
19− -> [a]
20− pure a = [a]
21− (<*>)
22− :: [a] -> [a] -> [a]
23− (<*>) _ _ = []
data/examples/declaration/instance/instance-sigs.hs−9
@@ -14,12 +14,3 @@ instance Ord Int where
1414 _
1515 _
1616 = GT
17−
18−instance Applicative [] where
19− pure ::
20− a
21− -> [a]
22− pure a = [a]
23− (<*>)
24− :: [ a ] -> [ a ] -> [ a ]
25− (<*>) _ _ = []
data/examples/declaration/instance/multi-parameter-out.hs+1−2
@@ -1,5 +1,4 @@
1−instance MonadReader a ((->) a) where
2− ask = id
1+instance MonadReader a ((->) a) where ask = id
32
43instance MonadState s (State s) where
54 get = State.get
data/examples/declaration/instance/newlines-after-where-out.hsnew file+5
@@ -0,0 +1,5 @@
1+instance Num X where
2+ (+) = undefined
3+
4+instance Num Y where
5+ (+) = undefined
data/examples/declaration/instance/newlines-after-where.hsnew file+7
@@ -0,0 +1,7 @@
1+instance Num X where
2+ (+) = undefined
3+
4+instance Num Y where
5+
6+
7+ (+) = undefined
data/examples/declaration/instance/newlines-between-methods-out.hsnew file+18
@@ -0,0 +1,18 @@
1+instance Num a => Num (Diff a) where
2+ D u dudx + D v dvdx = D (u + v) (dudx + dvdx)
3+ D u dudx - D v dvdx = D (u - v) (dudx - dvdx)
4+ D u dudx * D v dvdx = D (u * v) (u * dvdx + v * dudx)
5+
6+ -- Comment before definition
7+ negate (D u dudx) = D (- u) (- dudx)
8+ negate (Z u dudx) = undefined
9+
10+ -- Comment after definition
11+
12+ -- Separator
13+
14+ abs (D u _) = D (abs u) (signum u)
15+ signum (D u _) = D (signum u) 0
16+
17+ -- Comment between unrelated definitions
18+ fromInteger n = D (fromInteger n) 0
data/examples/declaration/instance/newlines-between-methods.hsnew file+16
@@ -0,0 +1,16 @@
1+instance Num a => Num (Diff a) where
2+ D u dudx + D v dvdx = D (u + v) (dudx + dvdx)
3+ D u dudx - D v dvdx = D (u - v) (dudx - dvdx)
4+ D u dudx * D v dvdx = D (u * v) (u * dvdx + v * dudx)
5+
6+ -- Comment before definition
7+ negate (D u dudx) = D (-u) (-dudx)
8+ negate (Z u dudx) = undefined
9+ -- Comment after definition
10+
11+ -- Separator
12+
13+ abs (D u _) = D (abs u) (signum u)
14+ signum (D u _) = D (signum u) 0
15+ -- Comment between unrelated definitions
16+ fromInteger n = D (fromInteger n) 0
data/examples/declaration/instance/overlappable-instances-out.hs+6−3
@@ -1,5 +1,4 @@
1−instance {-# OVERLAPPABLE #-} Eq Int where
2− (==) _ _ = False
1+instance {-# OVERLAPPABLE #-} Eq Int where (==) _ _ = False
32
43instance {-# OVERLAPPING #-} Ord Int where
54 compare _ _ = GT
@@ -7,5 +6,9 @@ instance {-# OVERLAPPING #-} Ord Int where
76instance {-# OVERLAPS #-} Eq Double where
87 (==) _ _ = False
98
10−instance {-# INCOHERENT #-} Ord Double where
9+instance
10+ {-# INCOHERENT #-}
11+ Ord
12+ Double
13+ where
1114 compare _ _ = GT
data/examples/declaration/instance/overlappable-instances.hs+3−1
@@ -7,5 +7,7 @@ instance {-# OVERLAPS #-} Eq Double where
77 (==) _ _ = False
88
99instance
10− {-# INCOHERENT #-} Ord Double where
10+ {-# INCOHERENT #-}
11+ Ord
12+ Double where
1113 compare _ _ = GT
data/examples/declaration/instance/single-parameter-out.hs+6−4
@@ -1,7 +1,9 @@
1−instance Monoid Int where
2− (<>) x y = x + y
1+instance Monoid Int where (<>) x y = x + y
32
43instance Enum Int where
54 fromEnum x = x
6− toEnum = \x ->
7− x
5+ toEnum =
6+ \x ->
7+ x
8+
9+instance Foo Int where foo x = x; bar y = y
data/examples/declaration/instance/single-parameter.hs+2
@@ -6,3 +6,5 @@ instance Enum Int
66 toEnum
77 = \x ->
88 x
9+
10+instance Foo Int where { foo x = x; bar y = y }
data/examples/declaration/instance/type-family-instances-out.hs+5−4
@@ -1,11 +1,12 @@
11{-# LANGUAGE TypeFamilies #-}
2+
23type instance Foo Int = Int
34
45type instance
56 Foo
67 [Int] =
7− ( Int
8− , Int
8+ ( Int,
9+ Int
910 )
1011
1112type instance Bar Int [Int] Double = (Int, Double)
@@ -15,6 +16,6 @@ type instance
1516 [Int]
1617 [Int]
1718 Double =
18− ( Int
19− , Double
19+ ( Int,
20+ Double
2021 )
data/examples/declaration/rewrite-rule/basic1-out.hsnew file+19
@@ -0,0 +1,19 @@
1+{-# RULES
2+"fold/build" foldr k z (build g) = g k z
3+ #-}
4+
5+{-# RULES
6+"fusable/aux"
7+ fusable x (aux y) =
8+ faux x y
9+ #-}
10+
11+{-# RULES
12+"map/map"
13+ map
14+ f
15+ (map g xs) =
16+ map
17+ (f . g)
18+ xs
19+ #-}
data/examples/declaration/rewrite-rule/basic1.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# RULES
2+"fold/build" foldr k z (build g) = g k z
3+ #-}
4+
5+{-# RULES
6+"fusable/aux"
7+ fusable x (aux y) = faux x y
8+ #-}
9+
10+{-# RULES
11+"map/map"
12+ map f
13+ (map g xs) = map
14+ (f . g)
15+ xs
16+ #-}
17+
data/examples/declaration/rewrite-rule/basic2-out.hsnew file+16
@@ -0,0 +1,16 @@
1+{-# RULES
2+"++" xs ++ ys = augment (\c n -> foldr c n xs) ys
3+"concat" xs `concat` ys = augment (\c n -> foldr c n xs) ys
4+ #-}
5+
6+{-# RULES
7+"++" xs ++ ys = augment (\c n -> foldr c n xs) ys
8+"concat" xs `concat` ys = augment (\c n -> foldr c n xs) ys
9+"map/Double" fmap f xs = foldr (++) f xs
10+ #-}
11+
12+{-# RULES
13+"fb' >\\ (Request b' fb )" forall fb' b' fb.
14+ fb' >\\ (Request b' fb) =
15+ fb' b' >>= \b -> fb' >\\ fb b
16+ #-}
data/examples/declaration/rewrite-rule/basic2.hsnew file+16
@@ -0,0 +1,16 @@
1+{-# RULES
2+"++" xs ++ ys = augment (\c n -> foldr c n xs) ys
3+"concat" xs `concat` ys = augment (\c n -> foldr c n xs) ys
4+ #-}
5+
6+{-# RULES
7+"++" xs ++ ys = augment (\c n -> foldr c n xs) ys;
8+"concat" xs `concat` ys = augment (\c n -> foldr c n xs) ys;
9+"map/Double" fmap f xs = foldr (++) f xs
10+ #-}
11+
12+{-# RULES
13+ "fb' >\\ (Request b' fb )" forall fb' b' fb .
14+ fb' >\\ (Request b' fb ) = fb' b' >>= \b -> fb' >\\ fb b;
15+#-}
16+
data/examples/declaration/rewrite-rule/empty-out.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# RULES
2+
3+ #-}
data/examples/declaration/rewrite-rule/empty.hsnew file+2
@@ -0,0 +1,2 @@
1+{-# RULES
2+ #-}
data/examples/declaration/rewrite-rule/forall-0-out.hsnew file+9
@@ -0,0 +1,9 @@
1+{-# RULES
2+"fold/build" forall k z. foldr k z (build g) = g k z
3+ #-}
4+
5+{-# RULES
6+"fusable/aux" forall x y.
7+ fusable x (aux y) =
8+ faux x y
9+ #-}
data/examples/declaration/rewrite-rule/forall-0.hsnew file+8
@@ -0,0 +1,8 @@
1+{-# RULES
2+"fold/build" forall k z . foldr k z (build g) = g k z
3+ #-}
4+
5+{-# RULES
6+"fusable/aux" forall x y.
7+ fusable x (aux y) = faux x y
8+ #-}
data/examples/declaration/rewrite-rule/forall-1-out.hsnew file+23
@@ -0,0 +1,23 @@
1+{-# RULES "rd_tyvs" forall a. forall (x :: a). id x = x #-}
2+
3+{-# RULES "rd_tyvs'" forall f a. forall (x :: f a). id x = x #-}
4+
5+{-# RULES "rd_tyvs''" forall (a :: *). forall (x :: a). id x = x #-}
6+
7+{-# RULES
8+"rd_tyvs_multiline1" forall (a :: *). forall (x :: a).
9+ id x =
10+ x
11+ #-}
12+
13+{-# RULES
14+"rd_tyvs_multiline2" forall
15+ ( a ::
16+ *
17+ ). forall
18+ ( x ::
19+ a
20+ ).
21+ id x =
22+ x
23+ #-}
data/examples/declaration/rewrite-rule/forall-1.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# RULES "rd_tyvs" forall a. forall (x :: a). id x = x #-}
2+
3+{-# RULES "rd_tyvs'" forall f a. forall (x :: f a). id x = x #-}
4+
5+{-# RULES "rd_tyvs''" forall (a :: *). forall (x :: a). id x = x #-}
6+
7+{-# RULES "rd_tyvs_multiline1"
8+ forall (a :: *).
9+ forall (x :: a).
10+ id x = x #-}
11+
12+{-# RULES "rd_tyvs_multiline2"
13+ forall (a ::
14+ *).
15+ forall (x ::
16+ a).
17+ id x = x #-}
data/examples/declaration/rewrite-rule/phase-out.hsnew file+23
@@ -0,0 +1,23 @@
1+{-# RULES
2+"map/map" [2]
3+ map
4+ f
5+ (map g xs) =
6+ map
7+ (f . g)
8+ xs
9+ #-}
10+
11+{-# RULES
12+"map/map" [1] forall x y z.
13+ map
14+ f
15+ (map g xs) =
16+ map
17+ (f . g)
18+ xs
19+ #-}
20+
21+{-# RULES
22+"++" [~1] forall xs ys. xs ++ ys = augment (\c n -> foldr c n xs) ys
23+ #-}
data/examples/declaration/rewrite-rule/phase.hsnew file+19
@@ -0,0 +1,19 @@
1+{-# RULES
2+"map/map" [2]
3+ map f
4+ (map g xs) = map
5+ (f . g)
6+ xs
7+ #-}
8+
9+{-# RULES
10+"map/map" [1] forall x y z.
11+ map f
12+ (map g xs) = map
13+ (f . g)
14+ xs
15+ #-}
16+
17+{-# RULES
18+"++" [~1] forall xs ys. xs ++ ys = augment (\c n -> foldr c n xs) ys
19+ #-}
data/examples/declaration/rewrite-rule/prelude1-out.hsnew file+18
@@ -0,0 +1,18 @@
1+{-# RULES
2+"map/map" forall f g xs. map f (map g xs) = map (f . g) xs
3+"map/append" forall f xs ys. map f (xs ++ ys) = map f xs ++ map f ys
4+ #-}
5+
6+{-# RULES
7+"map" [~1] forall f xs. map f xs = build (\c n -> foldr (mapFB c f) n xs)
8+"mapList" [1] forall f. foldr (mapFB (:) f) [] = map f
9+"mapFB" forall c f g. mapFB (mapFB c f) g = mapFB c (f . g)
10+ #-}
11+
12+{-# RULES
13+"map/map" [~2] forall f g xs.
14+ map f (map g xs) =
15+ map (f . g) xs
16+"f" op True y = False
17+"g" op True y = False
18+ #-}
data/examples/declaration/rewrite-rule/prelude1.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# RULES
2+"map/map" forall f g xs. map f (map g xs) = map (f.g) xs
3+"map/append" forall f xs ys. map f (xs ++ ys) = map f xs ++ map f ys
4+ #-}
5+
6+{-# RULES
7+"map" [~1] forall f xs. map f xs = build (\c n -> foldr (mapFB c f) n xs)
8+"mapList" [1] forall f. foldr (mapFB (:) f) [] = map f
9+"mapFB" forall c f g. mapFB (mapFB c f) g = mapFB c (f.g)
10+ #-}
11+
12+{-# RULES
13+ "map/map" [~2] forall f g xs.
14+ map f (map g xs) = map (f.g) xs; "f" op True y = False;
15+ "g" op True y = False
16+#-}
17+
data/examples/declaration/rewrite-rule/prelude2-out.hsnew file+31
@@ -0,0 +1,31 @@
1+{-# RULES
2+"fold/build" forall k z (g :: forall b. (a -> b -> b) -> b -> b).
3+ foldr k z (build g) =
4+ g k z
5+"foldr/augment" forall k z xs (g :: forall b. (a -> b -> b) -> b -> b).
6+ foldr k z (augment g xs) =
7+ g k (foldr k z xs)
8+"foldr/id" foldr (:) [] = \x -> x
9+"foldr/app" [1] forall ys. foldr (:) ys = \xs -> xs ++ ys
10+-- Only activate this from phase 1, because that's
11+-- when we disable the rule that expands (++) into foldr
12+
13+-- The foldr/cons rule looks nice, but it can give disastrously
14+-- bloated code when commpiling
15+-- array (a,b) [(1,2), (2,2), (3,2), ...very long list... ]
16+-- i.e. when there are very very long literal lists
17+-- So I've disabled it for now. We could have special cases
18+-- for short lists, I suppose.
19+-- "foldr/cons" forall k z x xs. foldr k z (x:xs) = k x (foldr k z xs)
20+
21+"foldr/single" forall k z x. foldr k z [x] = k x z
22+"foldr/nil" forall k z. foldr k z [] = z
23+"augment/build" forall
24+ (g :: forall b. (a -> b -> b) -> b -> b)
25+ (h :: forall b. (a -> b -> b) -> b -> b).
26+ augment g (build h) =
27+ build (\c n -> g c (h c n))
28+"augment/nil" forall (g :: forall b. (a -> b -> b) -> b -> b).
29+ augment g [] =
30+ build g
31+ #-}
data/examples/declaration/rewrite-rule/prelude2.hsnew file+29
@@ -0,0 +1,29 @@
1+{-# RULES
2+"fold/build" forall k z (g::forall b. (a->b->b) -> b -> b) .
3+ foldr k z (build g) = g k z
4+
5+"foldr/augment" forall k z xs (g::forall b. (a->b->b) -> b -> b) .
6+ foldr k z (augment g xs) = g k (foldr k z xs)
7+
8+"foldr/id" foldr (:) [] = \x -> x
9+"foldr/app" [1] forall ys. foldr (:) ys = \xs -> xs ++ ys
10+ -- Only activate this from phase 1, because that's
11+ -- when we disable the rule that expands (++) into foldr
12+
13+-- The foldr/cons rule looks nice, but it can give disastrously
14+-- bloated code when commpiling
15+-- array (a,b) [(1,2), (2,2), (3,2), ...very long list... ]
16+-- i.e. when there are very very long literal lists
17+-- So I've disabled it for now. We could have special cases
18+-- for short lists, I suppose.
19+-- "foldr/cons" forall k z x xs. foldr k z (x:xs) = k x (foldr k z xs)
20+
21+"foldr/single" forall k z x. foldr k z [x] = k x z
22+"foldr/nil" forall k z. foldr k z [] = z
23+
24+"augment/build" forall (g::forall b. (a->b->b) -> b -> b)
25+ (h::forall b. (a->b->b) -> b -> b) .
26+ augment g (build h) = build (\c n -> g c (h c n))
27+"augment/nil" forall (g::forall b. (a->b->b) -> b -> b) .
28+ augment g [] = build g
29+ #-}
data/examples/declaration/rewrite-rule/prelude3-out.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE MagicHash #-}
2+
3+{-# RULES
4+"x# `eqChar#` x#" forall x#. x# `eqChar#` x# = True
5+"x# `neChar#` x#" forall x#. x# `neChar#` x# = False
6+"x# `gtChar#` x#" forall x#. x# `gtChar#` x# = False
7+"x# `geChar#` x#" forall x#. x# `geChar#` x# = True
8+"x# `leChar#` x#" forall x#. x# `leChar#` x# = True
9+"x# `ltChar#` x#" forall x#. x# `ltChar#` x# = False
10+ #-}
data/examples/declaration/rewrite-rule/prelude3.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE MagicHash #-}
2+
3+{-# RULES
4+"x# `eqChar#` x#" forall x#. x# `eqChar#` x# = True
5+"x# `neChar#` x#" forall x#. x# `neChar#` x# = False
6+"x# `gtChar#` x#" forall x#. x# `gtChar#` x# = False
7+"x# `geChar#` x#" forall x#. x# `geChar#` x# = True
8+"x# `leChar#` x#" forall x#. x# `leChar#` x# = True
9+"x# `ltChar#` x#" forall x#. x# `ltChar#` x# = False
10+ #-}
data/examples/declaration/rewrite-rule/prelude4-out.hsnew file+7
@@ -0,0 +1,7 @@
1+{-# RULES
2+"unpack" [~1] forall a. unpackCString # a = build (unpackFoldrCString # a)
3+"unpack-list" [1] forall a. unpackFoldrCString # a (:) [] = unpackCString # a
4+"unpack-append" forall a n. unpackFoldrCString # a (:) n = unpackAppendCString # a n
5+-- There's a built-in rule (in PrelRules.lhs) for
6+-- unpackFoldr "foo" c (unpackFoldr "baz" c n) = unpackFoldr "foobaz" c n
7+ #-}
data/examples/declaration/rewrite-rule/prelude4.hsnew file+9
@@ -0,0 +1,9 @@
1+{-# RULES
2+"unpack" [~1] forall a . unpackCString# a = build (unpackFoldrCString# a)
3+"unpack-list" [1] forall a . unpackFoldrCString# a (:) [] = unpackCString# a
4+"unpack-append" forall a n . unpackFoldrCString# a (:) n = unpackAppendCString# a n
5+
6+-- There's a built-in rule (in PrelRules.lhs) for
7+-- unpackFoldr "foo" c (unpackFoldr "baz" c n) = unpackFoldr "foobaz" c n
8+
9+ #-}
data/examples/declaration/rewrite-rule/type-signature-out.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# RULES
2+"fold/build" forall k z (g :: forall b. (a -> b -> b) -> b -> b). foldr k z (build g) = g k z
3+ #-}
4+
5+{-# RULES
6+"fold/build" forall
7+ k
8+ z
9+ ( g ::
10+ forall b.
11+ (a -> b -> b) ->
12+ b ->
13+ b
14+ ).
15+ foldr k z (build g) =
16+ g k z
17+ #-}
data/examples/declaration/rewrite-rule/type-signature.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# RULES
2+"fold/build" forall k z (g :: forall b. (a -> b -> b) -> b -> b). foldr k z (build g) = g k z
3+ #-}
4+
5+{-# RULES
6+"fold/build"
7+ forall k z
8+ (g :: forall b.
9+ (a -> b -> b) -> b -> b).
10+ foldr k z (build g) =
11+ g k z
12+ #-}
data/examples/declaration/role-annotation/multi-line-out.hsnew file+15
@@ -0,0 +1,15 @@
1+type role
2+ D
3+ phantom
4+ nominal
5+
6+type role
7+ E
8+ _
9+ nominal
10+
11+type role
12+ E
13+ _
14+ nominal
15+ phantom
data/examples/declaration/role-annotation/multi-line.hsnew file+15
@@ -0,0 +1,15 @@
1+type role
2+ D phantom nominal
3+
4+type
5+ role
6+ E
7+ _
8+ nominal
9+
10+type
11+ role
12+ E
13+ _
14+ nominal
15+ phantom
data/examples/declaration/role-annotation/simple-out.hs → data/examples/declaration/role-annotation/single-line-out.hsrenamed+2−17
@@ -1,5 +1,6 @@
1−{-# LANGUAGE RoleAnnotations #-}
21{-# LANGUAGE MagicHash #-}
2+{-# LANGUAGE RoleAnnotations #-}
3+
34type role Ptr representational
45
56type role A nominal nominal
@@ -7,19 +8,3 @@ type role A nominal nominal
78type role B _ phantom
89
910type role C _ _
10−
11−type role
12− D
13− phantom
14− nominal
15−
16−type role
17− E
18− _
19− nominal
20−
21−type role
22− E
23− _
24− nominal
25− phantom
data/examples/declaration/role-annotation/simple.hs → data/examples/declaration/role-annotation/single-line.hsrenamed−16
@@ -7,19 +7,3 @@ type role A nominal nominal
77
88type role B _ phantom
99type role C _ _
10−
11−type role
12− D phantom nominal
13−
14−type
15− role
16− E
17− _
18− nominal
19−
20−type
21− role
22− E
23− _
24− nominal
25− phantom
data/examples/declaration/signature/complete/complete-out.hs+4−4
@@ -3,8 +3,8 @@
33{-# COMPLETE A, B #-}
44
55{-# COMPLETE
6− A
7− , B
8− , C
9− :: Foo
6+ A,
7+ B,
8+ C ::
9+ Foo
1010 #-}
data/examples/declaration/signature/inline/conlike-out.hsnew file+7
@@ -0,0 +1,7 @@
1+foo :: Int
2+foo = 5
3+{-# INLINE CONLIKE foo #-}
4+
5+bar :: Int
6+bar = 6
7+{-# INLINE CONLIKE bar #-}
data/examples/declaration/signature/inline/conlike.hsnew file+7
@@ -0,0 +1,7 @@
1+foo :: Int
2+foo = 5
3+{-# INLINE CONLIKE foo #-}
4+
5+bar :: Int
6+bar = 6
7+{-# INLINE CONLIKE bar #-}
data/examples/declaration/signature/inline/inline-out.hs+4
@@ -9,3 +9,7 @@ bar = id
99baz :: Int -> Int
1010baz = id
1111{-# INLINE [~2] baz #-}
12+
13+reVector :: Bundle u a -> Bundle v a
14+{-# INLINE reVector #-}
15+reVector = M.reVector
data/examples/declaration/signature/inline/inline.hs+5
@@ -11,3 +11,8 @@ bar = id
1111baz :: Int -> Int
1212baz = id
1313{-# INLINE [~2] baz #-}
14+
15+reVector :: Bundle u a -> Bundle v a
16+
17+{-# INLINE reVector #-}
18+reVector = M.reVector
data/examples/declaration/signature/minimal/minimal-out.hs+5−3
@@ -1,12 +1,14 @@
11class Foo a where
22 {-# MINIMAL (==) | ((/=), foo) #-}
3+
34 {-# MINIMAL
45 a
56 | ( b, c, d
6− | e
7− , f
7+ | e,
8+ f
89 )
9− | g
10+ | g
1011 #-}
12+
1113 (==) :: a -> a -> Bool
1214 (/=) :: a -> a -> Bool
data/examples/declaration/signature/pattern/multiline-out.hs+18−4
@@ -1,5 +1,19 @@
11{-# LANGUAGE PatternSynonyms #-}
2−pattern Arrow
3− :: Type
4− -> Type
5− -> Type
2+
3+pattern Arrow ::
4+ Type ->
5+ Type ->
6+ Type
7+
8+pattern
9+ Foo,
10+ Bar ::
11+ Type -> Type -> Type
12+
13+pattern
14+ TypeSignature,
15+ FunctionBody,
16+ PatternSignature,
17+ WarningPragma ::
18+ [RdrName] ->
19+ HsDecl GhcPs
data/examples/declaration/signature/pattern/multiline.hs+10
@@ -1,3 +1,13 @@
11{-# LANGUAGE PatternSynonyms #-}
2+
23pattern Arrow :: Type
34 -> Type -> Type
5+
6+pattern Foo, Bar ::
7+ Type -> Type -> Type
8+
9+pattern TypeSignature
10+ , FunctionBody
11+ , PatternSignature
12+ , WarningPragma :: [RdrName]
13+ -> HsDecl GhcPs
data/examples/declaration/signature/pattern/single-line-out.hs+3
@@ -1,2 +1,5 @@
11{-# LANGUAGE PatternSynonyms #-}
2+
23pattern Arrow :: Type -> Type -> Type
4+
5+pattern Foo, Bar :: Type -> Type -> Type
data/examples/declaration/signature/pattern/single-line.hs+2
@@ -1,3 +1,5 @@
11{-# LANGUAGE PatternSynonyms #-}
22
33pattern Arrow :: Type -> Type -> Type
4+
5+pattern Foo, Bar :: Type -> Type -> Type
data/examples/declaration/signature/specialize/specialize-out.hs+14−5
@@ -1,15 +1,24 @@
11foo :: Num a => a -> a
22foo = id
33{-# SPECIALIZE foo :: Int -> Int #-}
4−{-# SPECIALIZE foo :: Float -> Float #-}
4+{-# SPECIALIZE INLINE foo :: Float -> Float #-}
55
6−{-# SPECIALIZE [2] bar :: Int -> Int #-}
6+{-# SPECIALIZE NOINLINE [2] bar :: Int -> Int #-}
77bar :: Num a => a -> a
88bar = id
99
1010baz :: Num a => a -> a
1111baz = id
12−{-# SPECIALIZE [~2] baz
13− :: Int
14− -> Int
12+{-# SPECIALIZE [~2] baz ::
13+ Int ->
14+ Int
1515 #-}
16+
17+{-# SPECIALIZE fits13Bits :: Int -> Bool, Integer -> Bool #-}
18+{-# SPECIALIZE fits13Bits ::
19+ Int ->
20+ Bool,
21+ Integer -> Bool
22+ #-}
23+fits13Bits :: Integral a => a -> Bool
24+fits13Bits x = x >= -4096 && x < 4096
data/examples/declaration/signature/specialize/specialize.hs+10−2
@@ -2,9 +2,9 @@ foo :: Num a => a -> a
22foo = id
33
44{-# SPECIALIZE foo :: Int -> Int #-}
5−{-# SPECIALIZE foo :: Float -> Float #-}
5+{-# SPECIALIZE INLINE foo :: Float -> Float #-}
66
7−{-# SPECIALIZE [2] bar :: Int -> Int #-}
7+{-# SPECIALIZE NOINLINE [2] bar :: Int -> Int #-}
88
99bar :: Num a => a -> a
1010bar = id
@@ -14,3 +14,11 @@ baz = id
1414{-# SPECIALIZE [~2] baz
1515 :: Int
1616 -> Int #-}
17+
18+{-# SPECIALIZE fits13Bits :: Int -> Bool, Integer -> Bool #-}
19+{-# SPECIALIZE fits13Bits
20+ :: Int
21+ -> Bool
22+ , Integer -> Bool #-}
23+fits13Bits :: Integral a => a -> Bool
24+fits13Bits x = x >= -4096 && x < 4096
data/examples/declaration/signature/standalone-kind-out.hsnew file+13
@@ -0,0 +1,13 @@
1+{-# LANGUAGE StandaloneKindSignatures #-}
2+
3+type T ::
4+ (k -> Type) ->
5+ k ->
6+ Type
7+data T m a = MkT (m a) (T Maybe (m a))
8+
9+type C1 :: Type -> Constraint
10+class C1 a
11+
12+type F :: Type -> Type
13+type family F
data/examples/declaration/signature/standalone-kind.hsnew file+13
@@ -0,0 +1,13 @@
1+{-# LANGUAGE StandaloneKindSignatures #-}
2+
3+type T :: (k -> Type)
4+ -> k
5+ -> Type
6+
7+data T m a = MkT (m a) (T Maybe (m a))
8+
9+type C1 :: Type -> Constraint
10+class C1 a
11+
12+type F :: Type -> Type
13+type family F
data/examples/declaration/signature/type/arguments-out.hs+15−13
@@ -1,14 +1,16 @@
11{-# LANGUAGE RankNTypes #-}
2−functionName
3− :: (C1, C2, C3, C4, C5)
4− => a
5− -> b
6− -> ( forall a. (C6, C7)
7− => LongDataTypeName
8− -> a
9− -> AnotherLongDataTypeName
10− -> b
11− -> c
12− )
13− -> (c -> d)
14− -> (a, b, c, d)
2+
3+functionName ::
4+ (C1, C2, C3, C4, C5) =>
5+ a ->
6+ b ->
7+ ( forall a.
8+ (C6, C7) =>
9+ LongDataTypeName ->
10+ a ->
11+ AnotherLongDataTypeName ->
12+ b ->
13+ c
14+ ) ->
15+ (c -> d) ->
16+ (a, b, c, d)
data/examples/declaration/signature/type/context-multi-line-out.hs+10−10
@@ -1,10 +1,10 @@
1−functionName
2− :: ( C1
3− , C2
4− , C3
5− )
6− => a
7− -> b
8− -> c
9− -> d
10− -> (a, b, c, d)
1+functionName ::
2+ ( C1,
3+ C2,
4+ C3
5+ ) =>
6+ a ->
7+ b ->
8+ c ->
9+ d ->
10+ (a, b, c, d)
data/examples/declaration/signature/type/context-single-line-out.hs+7−7
@@ -1,7 +1,7 @@
1−functionName
2− :: (C1, C2, C3)
3− => a
4− -> b
5− -> c
6− -> d
7− -> (a, b, c, d)
1+functionName ::
2+ (C1, C2, C3) =>
3+ a ->
4+ b ->
5+ c ->
6+ d ->
7+ (a, b, c, d)
data/examples/declaration/signature/type/infix-promoted-type-constructor-out.hs+2−3
@@ -1,3 +1,2 @@
1−fun1 :: Def ('[Ref s (Stored Uint32), IBool] T.:-> IBool)
2−
3−fun2 :: Def ('[Ref s (Stored Uint32), IBool] :-> IBool)
1+fun1 :: Def ('[Ref s (Stored Uint32), IBool] 'T.:-> IBool)
2+fun2 :: Def ('[Ref s (Stored Uint32), IBool] ':-> IBool)
data/examples/declaration/signature/type/long-function-name-out.hs+6−6
@@ -1,6 +1,6 @@
1−longFunctionName
2− :: a
3− -> b
4− -> c
5− -> d
6− -> (a, b, c, d)
1+longFunctionName ::
2+ a ->
3+ b ->
4+ c ->
5+ d ->
6+ (a, b, c, d)
data/examples/declaration/signature/type/long-multiline-applications-out.hs+16−15
@@ -1,15 +1,16 @@
1−functionName
2− :: (C1, C2, C3, C4, C5)
3− => a
4− -> b
5− -> ( LongDataTypeName
6− AnotherLongDataTypeName
7− AnotherLongDataTypeName2
8− AnotherLongDataTypeName3
9− -> a
10− -> AnotherLongDataTypeName4
11− -> b
12− -> c
13− )
14− -> (c -> d)
15− -> (a, b, c, d)
1+functionName ::
2+ (C1, C2, C3, C4, C5) =>
3+ forall a b c.
4+ a ->
5+ b ->
6+ ( LongDataTypeName
7+ AnotherLongDataTypeName
8+ AnotherLongDataTypeName2
9+ AnotherLongDataTypeName3 ->
10+ a ->
11+ AnotherLongDataTypeName4 ->
12+ b ->
13+ c
14+ ) ->
15+ (c -> d) ->
16+ (a, b, c, d)
data/examples/declaration/signature/type/long-multiline-applications.hs+2−1
@@ -1,6 +1,7 @@
11functionName
22 :: (C1, C2, C3, C4, C5)
3− => a
3+ => forall a b c
4+ . a
45 -> b
56 -> ( LongDataTypeName
67 AnotherLongDataTypeName
data/examples/declaration/signature/type/multi-value-out.hs+13−4
@@ -1,6 +1,15 @@
11foo, bar :: Int
2+foo = 1
3+bar = 2
24
3−foo
4− , bar
5− , baz
6− :: Int
5+a, b, c :: Int
6+a = 1
7+b = 2
8+c = 3
9+
10+foo,
11+ bar,
12+ baz ::
13+ Int
14+bar = 2
15+baz = 3
data/examples/declaration/signature/type/multi-value.hs+9
@@ -1,5 +1,14 @@
11foo, bar :: Int
2+foo = 1
3+bar = 2
4+
5+a, b, c :: Int
6+a = 1
7+b = 2
8+c = 3
29
310foo,
411 bar,
512 baz :: Int
13+bar = 2
14+baz = 3
data/examples/declaration/signature/type/unicode-out.hsnew file+4
@@ -0,0 +1,4 @@
1+{-# LANGUAGE UnicodeSyntax #-}
2+
3+foo :: forall a. Show a => a -> String
4+foo = const ()
data/examples/declaration/signature/type/unicode.hsnew file+4
@@ -0,0 +1,4 @@
1+{-# LANGUAGE UnicodeSyntax #-}
2+
3+foo ∷ ∀a. Show a ⇒ a → String
4+foo = const ()
data/examples/declaration/signature/type/unrelated-out.hsnew file+4
@@ -0,0 +1,4 @@
1+clientFunc1 :: SomeType1
2+clientFunc2 :: SomeType2
3+clientFunc3 :: SomeType3
4+clientFunc1 :<|> clientFunc2 :<|> clientFunc3 = hoistClient foo bar baz
data/examples/declaration/signature/type/unrelated.hsnew file+4
@@ -0,0 +1,4 @@
1+clientFunc1 :: SomeType1
2+clientFunc2 :: SomeType2
3+clientFunc3 :: SomeType3
4+clientFunc1 :<|> clientFunc2 :<|> clientFunc3 = hoistClient foo bar baz
data/examples/declaration/splice/bracket-declaration-out.hsnew file+26
@@ -0,0 +1,26 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+
3+[d|data T a where Foo :: T ()|]
4+
5+foo =
6+ [d|
7+ foo :: Int -> Char
8+
9+ bar = 42
10+ |]
11+
12+[d|
13+ data T = T
14+ deriving (Eq, Ord, Enum, Bounded, Show)
15+ |]
16+
17+$(do [d|baz = baz|])
18+
19+$(singletons [d|data T = T deriving (Eq, Ord, Enum, Bounded, Show)|])
20+
21+$( singletons
22+ [d|
23+ data T = T
24+ deriving (Eq, Ord, Enum, Bounded, Show)
25+ |]
26+ )
data/examples/declaration/splice/bracket-declaration.hsnew file+22
@@ -0,0 +1,22 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+
3+[d| data T a where Foo :: T () |]
4+
5+foo = [d|
6+ foo:: Int -> Char
7+ bar = 42
8+ |]
9+
10+[d|
11+ data T = T
12+ deriving (Eq, Ord, Enum, Bounded, Show)
13+ |]
14+
15+$( do [d| baz = baz |] )
16+
17+$(singletons [d| data T = T deriving (Eq, Ord, Enum, Bounded, Show) |])
18+
19+$(singletons [d|
20+ data T = T
21+ deriving (Eq, Ord, Enum, Bounded, Show)
22+ |])
data/examples/declaration/splice/bracket-out.hs+6−13
@@ -1,24 +1,17 @@
11{-# LANGUAGE TemplateHaskell #-}
2+
23foo =
3− [e|
4− foo bar
5− |]
4+ [|
5+ foo bar
6+ |]
67
78foo =
89 [e|
9− foo bar
10− |]
10+ foo bar
11+ |]
1112
1213foo = [t|Char|]
1314
14−foo =
15− [d|
16− foo :: Int -> Char
17−
18− bar = 42
19−
20− |]
21−
2215foo =
2316 [||
2417 foo bar
data/examples/declaration/splice/bracket.hs−5
@@ -8,10 +8,5 @@ foo = [e| foo bar
88
99foo = [t| Char |]
1010
11−foo = [d|
12− foo:: Int -> Char
13− bar = 42
14− |]
15−
1611foo = [|| foo bar
1712 ||]
data/examples/declaration/splice/grouped-splices-out.hsnew file+3
@@ -0,0 +1,3 @@
1+$(deriveJSON fieldLabelMod ''A)
2+$(deriveJSON fieldLabelMod ''B)
3+$(deriveJSON fieldLabelMod ''C)
data/examples/declaration/splice/grouped-splices.hsnew file+3
@@ -0,0 +1,3 @@
1+$(deriveJSON fieldLabelMod ''A)
2+$(deriveJSON fieldLabelMod ''B)
3+$(deriveJSON fieldLabelMod ''C)
data/examples/declaration/splice/quasiquote-out.hs+1
@@ -1,4 +1,5 @@
11{-# LANGUAGE QuasiQuotes #-}
2+
23x = [foo| foo bar |]
34
45x =
data/examples/declaration/splice/quotes-out.hsnew file+17
@@ -0,0 +1,17 @@
1+foo = ''R
2+
3+bar = 'foo
4+
5+bar' = 'foo_bar
6+
7+baz = ''(:#)
8+
9+baz' = ''(Foo.Bar.:#)
10+
11+equals = ''(==)
12+
13+unit = ''()
14+
15+list = ''[]
16+
17+quolified = ''Semigroup.Option
data/examples/declaration/splice/quotes.hsnew file+17
@@ -0,0 +1,17 @@
1+foo = ''R
2+
3+bar = 'foo
4+
5+bar' = 'foo_bar
6+
7+baz = ''(:#)
8+
9+baz' = ''(Foo.Bar.:#)
10+
11+equals = ''(==)
12+
13+unit = ''()
14+
15+list = ''[]
16+
17+quolified = ''Semigroup.Option
data/examples/declaration/splice/splice-decl-out.hs+2−1
@@ -1,4 +1,5 @@
11{-# LANGUAGE TemplateHaskell #-}
2+
23$(foo bar)
34
45$foo
@@ -9,7 +10,7 @@ $$foo
910
1011foo bar
1112
12−[e|booya|]
13+[|booya|]
1314
1415-- TemplateHaskell allows Q () at the top level
1516do
data/examples/declaration/splice/typed-splice-out.hs+1
@@ -1,4 +1,5 @@
11{-# LANGUAGE TemplateHaskell #-}
2+
23x =
34 $$( foo bar
45 )
data/examples/declaration/splice/untyped-splice-out.hs+1
@@ -1,4 +1,5 @@
11{-# LANGUAGE TemplateHaskell #-}
2+
23x = $(foo bar)
34
45x =
data/examples/declaration/type-families/closed-type-family/multi-line-out.hs+9−8
@@ -1,7 +1,7 @@
11type family
2− Id a
3− = result
4− | result -> a where
2+ Id a =
3+ result | result -> a
4+ where
55 Id a =
66 a
77
@@ -9,15 +9,16 @@ type family
99 G
1010 (a :: k)
1111 b
12− c
13− = foo
14− | foo -> k b where
12+ c =
13+ foo | foo -> k b
14+ where
1515 G a b c =
1616 (a, b)
1717
1818type family
19− F a
20− :: * -> * where
19+ F a ::
20+ * -> *
21+ where
2122 F Int = Double
2223 F Bool =
2324 Char
data/examples/declaration/type-families/closed-type-family/simple-out.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Documentation.
24type family F a :: * -> * where
35 F Int = Double
data/examples/declaration/type-families/closed-type-family/simple.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Documentation.
24
35type family F a :: * -> * where
data/examples/declaration/type-families/closed-type-family/with-equal-sign-out.hsnew file+2
@@ -0,0 +1,2 @@
1+type family TF a b = result where
2+ TF a b = Int
data/examples/declaration/type-families/closed-type-family/with-equal-sign.hsnew file+2
@@ -0,0 +1,2 @@
1+type family TF a b = result where
2+ TF a b = Int
data/examples/declaration/type-families/closed-type-family/with-forall-out.hsnew file+3
@@ -0,0 +1,3 @@
1+type family G a b where
2+ forall x y. G [x] (Proxy y) = Double
3+ forall z. z `G` z = Bool
data/examples/declaration/type-families/closed-type-family/with-forall.hsnew file+3
@@ -0,0 +1,3 @@
1+type family G a b where
2+ forall x y. G [x] (Proxy y) = Double
3+ forall z. z `G` z = Bool
data/examples/declaration/type-families/data-family/no-annotation-out.hs+2
@@ -1,2 +1,4 @@
1+module Main where
2+
13-- | Documentation.
24data family Array e
data/examples/declaration/type-families/data-family/no-annotation.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Documentation.
24
35data family Array e
data/examples/declaration/type-families/data-family/simple-out.hs+2
@@ -1,2 +1,4 @@
1+module Main where
2+
13-- | Documentation.
24data family GMap k :: Type -> Type
data/examples/declaration/type-families/data-family/simple.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Documentation.
24
35data family GMap k :: Type -> Type
data/examples/declaration/type-families/type-family/no-annotation-out.hs+2
@@ -1,2 +1,4 @@
1+module Main where
2+
13-- | Documentation.
24type family F a b :: Type -> Type
data/examples/declaration/type-families/type-family/no-annotation.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Documentation.
24
35type family F a b :: Type -> Type
data/examples/declaration/type-families/type-family/operator-out.hsnew file+3
@@ -0,0 +1,3 @@
1+type family a ! b
2+
3+type family a . b
data/examples/declaration/type-families/type-family/operator.hsnew file+2
@@ -0,0 +1,2 @@
1+type family a ! b
2+type family a . b
data/examples/declaration/type-families/type-family/simple-out.hs+2
@@ -1,2 +1,4 @@
1+module Main where
2+
13-- | Documentation.
24type family Elem c :: Type
data/examples/declaration/type-families/type-family/simple.hs+2
@@ -1,3 +1,5 @@
1+module Main where
2+
13-- | Documentation.
24
35type family Elem c :: Type
data/examples/declaration/type-synonyms/multi-line-out.hs+16−5
@@ -1,7 +1,18 @@
1−type Foo a b c
2− = Bar c a b
1+type Foo a b c =
2+ Bar c a b
33
44type Foo
5− = Bar
6− Baz
7− Quux
5+ a
6+ b
7+ c =
8+ Bar c a b
9+
10+type Foo =
11+ Bar
12+ Baz
13+ Quux
14+
15+type API =
16+ "route1" :> ApiRoute1
17+ :<|> "route2" :> ApiRoute2 -- comment here
18+ :<|> OmitDocs :> "i" :> ASomething API
data/examples/declaration/type-synonyms/multi-line.hs+10
@@ -1,7 +1,17 @@
11type Foo a b c
22 = Bar c a b
33
4+type Foo
5+ a
6+ b c
7+ = Bar c a b
8+
49type Foo =
510 Bar
611 Baz
712 Quux
13+
14+type API
15+ = "route1" :> ApiRoute1
16+ :<|> "route2" :> ApiRoute2 -- comment here
17+ :<|> OmitDocs :> "i" :> ASomething API
data/examples/declaration/type-synonyms/simple-out.hs+6
@@ -1,2 +1,8 @@
1+module Main where
2+
13-- | Documentation.
24type Foo a b c = Bar c a b
5+
6+type a ~> b = TyFun a b -> Type
7+
8+type (a :+: b) c d e = ()
data/examples/declaration/type-synonyms/simple.hs+6
@@ -1,3 +1,9 @@
1+module Main where
2+
13-- | Documentation.
24
35type Foo a b c = Bar c a b
6+
7+type a ~> b = TyFun a b -> Type
8+
9+type (a :+: b) c d e = ()
data/examples/declaration/type-synonyms/with-weird-haddock-out.hsnew file+3
@@ -0,0 +1,3 @@
1+type Elims =
2+ -- | eliminations ordered left-to-right.
3+ [Elim]
data/examples/declaration/type-synonyms/with-weird-haddock.hsnew file+1
@@ -0,0 +1 @@
1+type Elims = [Elim] -- ^ eliminations ordered left-to-right.
data/examples/declaration/type/forall-out.hsnew file+4
@@ -0,0 +1,4 @@
1+type CoerceLocalSig m m' =
2+ forall r a.
3+ LocalSig m r a ->
4+ LocalSig m' r a
data/examples/declaration/type/forall.hsnew file+4
@@ -0,0 +1,4 @@
1+type CoerceLocalSig m m' =
2+ forall r a.
3+ LocalSig m r a ->
4+ LocalSig m' r a
data/examples/declaration/type/lits-out.hsnew file+6
@@ -0,0 +1,6 @@
1+type A = "foo"
2+
3+type B =
4+ "foo\
5+ \bar" ->
6+ ()
data/examples/declaration/type/lits.hsnew file+4
@@ -0,0 +1,4 @@
1+type A = "foo"
2+
3+type B = "foo\
4+ \bar" -> ()
data/examples/declaration/type/misc-kind-signatures-out.hsnew file+5
@@ -0,0 +1,5 @@
1+instance DemoteNodeTypes ('[] :: [NodeType]) where
2+ demoteNodeTypes _ = []
3+
4+b :: (Bool :: *)
5+b = True
data/examples/declaration/type/misc-kind-signatures.hsnew file+5
@@ -0,0 +1,5 @@
1+instance DemoteNodeTypes ('[] :: [NodeType]) where
2+ demoteNodeTypes _ = []
3+
4+b :: (Bool :: *)
5+b = True
data/examples/declaration/type/promotion-out.hsnew file+19
@@ -0,0 +1,19 @@
1+type Foo = Cluster '[ 'NodeCore, 'NodeRelay', 'NodeEdge]
2+
3+data T = T' | T'T
4+
5+type S0 = ' T'
6+
7+type S1 = ' T'T
8+
9+type S2 = Proxy ('[ '[], '[]])
10+
11+type S4 = Proxy ('( 'Just, ' T'T))
12+
13+type S5 = Proxy ('[ 'Just, 'TT'T])
14+
15+type S6 = Proxy ('( '(), '()))
16+
17+type S7 = Proxy ('( 'a, 'b))
18+
19+type S8 = Proxy ('[Int, Bool])
data/examples/declaration/type/promotion.hsnew file+15
@@ -0,0 +1,15 @@
1+type Foo = Cluster '[ 'NodeCore, 'NodeRelay', 'NodeEdge ]
2+
3+data T = T' | T'T
4+
5+type S0 = ' T'
6+
7+type S1 = ' T'T
8+
9+type S2 = Proxy ( '[ '[], '[] ])
10+type S4 = Proxy ( '( 'Just, ' T'T))
11+type S5 = Proxy ( '[ 'Just, ' TT'T])
12+type S6 = Proxy ( '( '(), '() ))
13+type S7 = Proxy ( '( 'a, 'b ))
14+type S8 = Proxy ( '[ Int, Bool ])
15+
data/examples/declaration/type/splice-out.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+
3+type Foo = $(bar [t|Int|])
data/examples/declaration/type/splice.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+
3+type Foo = $( bar [t|Int|] )
data/examples/declaration/type/type-applications-out.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# LANGUAGE TypeApplications #-}
2+
3+type P = K @Bool @(Bool :: *) 'True 'False
data/examples/declaration/type/type-applications.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# LANGUAGE TypeApplications #-}
2+
3+type P = K @Bool @(Bool :: *) 'True 'False
data/examples/declaration/type/visible-forall-out.hsnew file+2
@@ -0,0 +1,2 @@
1+-- source: https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0081-forall-arrow.rst
2+data T :: forall k -> k -> Type
data/examples/declaration/type/visible-forall.hsnew file+2
@@ -0,0 +1,2 @@
1+-- source: https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0081-forall-arrow.rst
2+data T :: forall k -> k -> Type
data/examples/declaration/value/function/application-0-out.hsnew file+17
@@ -0,0 +1,17 @@
1+foo =
2+ f1
3+ p1
4+ p2
5+ p3
6+
7+foo' =
8+ f2
9+ p1
10+ p2
11+ p3
12+
13+foo'' =
14+ f3
15+ p1
16+ p2
17+ p3
data/examples/declaration/value/function/application-0.hsnew file+12
@@ -0,0 +1,12 @@
1+foo =
2+ f1
3+ p1
4+ p2 p3
5+
6+foo' = f2 p1
7+ p2
8+ p3
9+
10+foo'' =
11+ f3 p1 p2
12+ p3
data/examples/declaration/value/function/application-1-out.hsnew file+19
@@ -0,0 +1,19 @@
1+main =
2+ do
3+ x
4+ y
5+ z
6+
7+main =
8+ case foo of
9+ x -> a
10+ foo
11+ a
12+ b
13+
14+main =
15+ do
16+ if x then y else z
17+ foo
18+ a
19+ b
data/examples/declaration/value/function/application-1.hsnew file+14
@@ -0,0 +1,14 @@
1+main =
2+ do
3+ x
4+ y
5+ z
6+
7+main =
8+ case foo of
9+ x -> a
10+ foo a b
11+
12+main = do
13+ if x then y else z
14+ foo a b
data/examples/declaration/value/function/arg-breakpoints-out.hsnew file+3
@@ -0,0 +1,3 @@
1+foo
2+ bar =
3+ body
data/examples/declaration/value/function/arg-breakpoints.hsnew file+3
@@ -0,0 +1,3 @@
1+foo
2+ bar =
3+ body
data/examples/declaration/value/function/arithmetic-sequences-out.hs+16−6
@@ -1,14 +1,24 @@
1−foo = [0..]
1+foo = [0 ..]
2+
3+foo' = [0 .. 5]
24
35bar x =
46 [ 0
5− .. x
7+ .. x
68 ]
79
810baz x =
9− [ 1
10− , 3
11− .. x
11+ [ 1,
12+ 3
13+ .. x
1214 ]
1315
14−barbaz x = [0, 1..]
16+barbaz x = [0, 1 ..]
17+
18+arst = [0 :: Int ..]
19+
20+brst = [0, 1 :: Int ..]
21+
22+crst = [0 :: Int .. 10]
23+
24+drst = [0, 1 :: Int .. 10]
data/examples/declaration/value/function/arithmetic-sequences.hs+5
@@ -1,4 +1,5 @@
11foo = [0..]
2+foo' = [0..5]
23bar x = [
34 0..x
45 ]
@@ -8,3 +9,7 @@ baz x = [
89 x
910 ]
1011barbaz x = [ 0, 1.. ]
12+arst = [0 :: Int ..]
13+brst = [0, 1 :: Int ..]
14+crst = [0 :: Int .. 10]
15+drst = [0, 1 :: Int .. 10]
data/examples/declaration/value/function/arrow/multiline-case-out.hsnew file+8
@@ -0,0 +1,8 @@
1+{-# LANGUAGE Arrows #-}
2+
3+f = proc x -> do
4+ x <-
5+ case x of X -> x
6+ -<
7+ y
8+ a -< b
data/examples/declaration/value/function/arrow/multiline-case.hsnew file+7
@@ -0,0 +1,7 @@
1+{-# LANGUAGE Arrows #-}
2+
3+f = proc x -> do
4+ x
5+ <- case x of X -> x
6+ -< y
7+ a -< b
data/examples/declaration/value/function/arrow/proc-applications-out.hsnew file+19
@@ -0,0 +1,19 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo x = proc a -> a -< x
4+
5+bar f x =
6+ proc
7+ ( y,
8+ z,
9+ w
10+ )
11+ ->
12+ f -- The value
13+ -<
14+ ( x, -- Foo
15+ w, -- Bar
16+ z -- Baz
17+ )
18+
19+baz x = proc a -> a -<< x
data/examples/declaration/value/function/arrow/proc-applications.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo x = proc a -> a -< x
4+
5+bar f x =
6+ proc (
7+ y,
8+ z,
9+ w
10+ ) -> f -- The value
11+ -< (
12+ x, -- Foo
13+ w, -- Bar
14+ z -- Baz
15+ )
16+
17+baz x = proc a -> a -<< x
data/examples/declaration/value/function/arrow/proc-cases-out.hsnew file+16
@@ -0,0 +1,16 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo f = proc a -> case a of Left b -> f -< b
4+
5+bar f g h j =
6+ proc a -> case a of
7+ Left
8+ ( (a, b),
9+ (c, d)
10+ ) -> f (a <> c) -< b <> d
11+ Right
12+ (Left a) ->
13+ h -< a
14+ Right
15+ (Right b) ->
16+ j -< b
data/examples/declaration/value/function/arrow/proc-cases.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# LANGUAGE Arrows #-}
2+foo f =proc a -> case a of Left b -> f -<b
3+
4+bar f g h j
5+ = proc a ->
6+ case a of
7+ Left (
8+ (a, b),
9+ (c, d)
10+ ) -> f (a <> c) -< b <> d
11+
12+ Right
13+ (Left a) ->
14+ h -< a
15+ Right
16+ (Right b) ->
17+ j -< b
data/examples/declaration/value/function/arrow/proc-do-complex-out.hsnew file+62
@@ -0,0 +1,62 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo
4+ f
5+ g
6+ h
7+ ma =
8+ proc
9+ ( (a, b),
10+ (c, d),
11+ (e, f)
12+ )
13+ -> do
14+ -- Begin do
15+ (x, y) <- -- GHC parser fails if layed out over multiple lines
16+ f -- Call into f
17+ ( a,
18+ c -- Tuple together arguments
19+ )
20+ ( b,
21+ d
22+ )
23+ -<
24+ ( b + 1, -- Funnel into arrow
25+ d * b
26+ )
27+ if x `mod` y == 0 -- Basic condition
28+ then case e of -- Only left case is relevant
29+ Left
30+ ( z,
31+ w
32+ ) -> \u -> -- Procs can have lambdas
33+ let v =
34+ u -- Actually never used
35+ ^ 2
36+ in ( returnA
37+ -<
38+ -- Just do the calculation
39+ (x + y * z)
40+ )
41+ else do
42+ let u = x -- Let bindings bind expressions, not commands
43+ -- Could pattern match directly on x
44+ i <- case u of
45+ 0 -> (g . h -< u)
46+ n ->
47+ ( ( h . g
48+ -<
49+ y -- First actual use of y
50+ )
51+ )
52+ returnA -< ()
53+ -- Sometimes execute effects
54+ if i > 0
55+ then ma -< ()
56+ else returnA -< ()
57+ returnA
58+ -<
59+ ( i
60+ + x
61+ * y -- Just do the calculation
62+ )
data/examples/declaration/value/function/arrow/proc-do-complex.hsnew file+49
@@ -0,0 +1,49 @@
1+{-# LANGUAGE Arrows #-}
2+foo
3+ f
4+ g
5+ h
6+ ma = proc (
7+ (a, b),
8+ (c, d),
9+ (e, f)
10+ ) ->
11+ do -- Begin do
12+ (x,y) -- GHC parser fails if layed out over multiple lines
13+ <- f -- Call into f
14+ (a,
15+ c) -- Tuple together arguments
16+ (b,
17+ d)
18+ -< (b + 1, -- Funnel into arrow
19+ d * b)
20+ if
21+ x `mod` y == 0 -- Basic condition
22+ then case e -- Only left case is relevant
23+ of Left (z,
24+ w) -> \u -> -- Procs can have lambdas
25+ let
26+ v
27+ = u -- Actually never used
28+ ^ 2
29+ in
30+ (returnA
31+ -< -- Just do the calculation
32+ (x + y * z))
33+ else do
34+ let u = x -- Let bindings bind expressions, not commands
35+ -- Could pattern match directly on x
36+ i <- case u of
37+ 0 -> (g . h -< u)
38+ n -> (
39+ (h . g
40+ -< y) -- First actual use of y
41+ )
42+ returnA -< ()
43+ -- Sometimes execute effects
44+ if i > 0
45+ then ma -< ()
46+ else returnA -< ()
47+ returnA -< (i +
48+ x *
49+ y) -- Just do the calculation
data/examples/declaration/value/function/arrow/proc-do-simple1-out.hsnew file+18
@@ -0,0 +1,18 @@
1+{-# LANGUAGE Arrows #-}
2+
3+bar f = proc a -> do
4+ b <- f -< a
5+
6+barbar f g = proc a -> do
7+ b <- f -< a
8+ returnA -< b
9+
10+barbaz f g = proc (a, b) -> do
11+ c <- f -< a
12+ d <- g -< b
13+
14+bazbar f = proc a -> do
15+ a <-
16+ f
17+ -<
18+ a
data/examples/declaration/value/function/arrow/proc-do-simple1.hsnew file+20
@@ -0,0 +1,20 @@
1+{-# LANGUAGE Arrows #-}
2+
3+bar f = proc a ->
4+ do b <- f -< a
5+
6+barbar f g = proc a ->
7+ do b <- f -< a
8+ returnA -< b
9+
10+barbaz f g = proc (a, b) ->
11+ do c <- f -< a
12+ d <- g -< b
13+
14+bazbar f = proc a ->
15+ do a
16+ <-
17+ f
18+ -<
19+ a
20+
data/examples/declaration/value/function/arrow/proc-do-simple2-out.hsnew file+22
@@ -0,0 +1,22 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo f = proc a -> do
4+ f -< a
5+
6+bazbaz f g h = proc (a, b, c) -> do
7+ x <-
8+ f b -< a
9+ y <-
10+ g b -< b
11+ z <-
12+ h
13+ x
14+ y
15+ -<
16+ ( a,
17+ b,
18+ c
19+ )
20+ returnA
21+ -<
22+ (x, y, z)
data/examples/declaration/value/function/arrow/proc-do-simple2.hsnew file+20
@@ -0,0 +1,20 @@
1+{-# LANGUAGE Arrows #-}
2+foo f = proc a ->
3+ do f -< a
4+
5+bazbaz f g h = proc (a, b, c) ->
6+ do x
7+ <- f b -< a
8+ y <-
9+ g b -< b
10+ z <-
11+ h
12+ x
13+ y
14+ -< (
15+ a,
16+ b,
17+ c
18+ )
19+ returnA -<
20+ (x, y, z)
data/examples/declaration/value/function/arrow/proc-forms1-out.hsnew file+21
@@ -0,0 +1,21 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo0 f g x y = proc _ -> (| f (g -< (x, y)) |)
4+
5+foo1 f g h x =
6+ proc (y, z) ->
7+ (|
8+ test
9+ ( h f
10+ . h g
11+ -<
12+ y x
13+ . y z
14+ )
15+ ( h g
16+ . h f
17+ -<
18+ y z
19+ . y x
20+ )
21+ |)
data/examples/declaration/value/function/arrow/proc-forms1.hsnew file+19
@@ -0,0 +1,19 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo0 f g x y = proc _ -> (| f (g -< (x, y)) |)
4+
5+foo1 f g h x =
6+ proc (y, z) -> (|
7+ test ( h f
8+ . h g
9+ -<
10+ y x
11+ . y z
12+ )
13+ ( h g
14+ . h f
15+ -<
16+ y z
17+ . y x)
18+ |)
19+
data/examples/declaration/value/function/arrow/proc-forms2-out.hsnew file+22
@@ -0,0 +1,22 @@
1+{-# LANGUAGE Arrows #-}
2+
3+bar0 f g h x =
4+ proc (y, z) ->
5+ (| test (h f . (h g) -< (y x) . y z) ((h g) . h f -< y z . (y x)) |)
6+
7+bar1 f g x y = proc _ -> (f -< x) &&& (g -< y)
8+
9+bar2 f g h x =
10+ proc (y, z) ->
11+ (h f . (h g) -< (y x) . y z) ||| ((h g) . h f -< y z . (y x))
12+
13+bar3 f g h x =
14+ proc (y, z) ->
15+ ( (h f . h g)
16+ -<
17+ (y x) . y z
18+ ) |||
19+ ( (h g . h f)
20+ -<
21+ y z . (y x)
22+ )
data/examples/declaration/value/function/arrow/proc-forms2.hsnew file+19
@@ -0,0 +1,19 @@
1+{-# LANGUAGE Arrows #-}
2+
3+bar0 f g h x =
4+ proc (y, z) ->
5+ (| test (h f.(h g) -< (y x).y z)((h g) . h f-<y z . (y x)) |)
6+
7+bar1 f g x y = proc _ -> (f -< x)&&&(g -< y)
8+
9+bar2 f g h x =
10+ proc (y, z) ->
11+ (h f.(h g) -< (y x).y z) ||| ((h g) . h f-<y z . (y x))
12+
13+bar3 f g h x =
14+ proc (y, z) ->
15+ ((h f.h g)
16+ -< (y x).y z)
17+ |||
18+ ((h g . h f)
19+ -<y z . (y x))
data/examples/declaration/value/function/arrow/proc-ifs-out.hsnew file+15
@@ -0,0 +1,15 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo f = proc a -> if a then f -< 0 else f -< 1
4+
5+bar f g = proc a ->
6+ if f a
7+ then
8+ f
9+ . g
10+ -<
11+ a
12+ else
13+ g
14+ -<
15+ b
data/examples/declaration/value/function/arrow/proc-ifs.hsnew file+14
@@ -0,0 +1,14 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo f = proc a -> if a then f-<0 else f-<1
4+
5+bar f g = proc a ->
6+ if
7+ f a
8+ then
9+ f
10+ . g -< a
11+ else
12+ g
13+ -<
14+ b
data/examples/declaration/value/function/arrow/proc-lambdas-out.hsnew file+9
@@ -0,0 +1,9 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo = proc a -> \f b -> a -< f b -- Foo
4+
5+bar =
6+ proc x -> \f g h ->
7+ \() ->
8+ \(Left (x, y)) -> -- Tuple value
9+ f (g (h x)) -< y
data/examples/declaration/value/function/arrow/proc-lambdas.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo = proc a-> \f b->a-<f b -- Foo
4+
5+bar =
6+ proc x ->
7+ \f g h ->
8+ \() ->
9+ \( Left (x,y )) -> -- Tuple value
10+ f (g (h x)) -< y
data/examples/declaration/value/function/arrow/proc-lets-out.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo f = proc a -> let b = a in f -< b
4+
5+bar f g = proc a ->
6+ let h =
7+ f
8+ . g a
9+ j =
10+ g
11+ . h
12+ in id -< (h, j)
data/examples/declaration/value/function/arrow/proc-lets.hsnew file+14
@@ -0,0 +1,14 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo f = proc a -> let b = a in f -< b
4+
5+bar f g = proc a ->
6+ let
7+ h
8+ = f
9+ . g a
10+ j = g
11+ .
12+ h
13+ in
14+ id -< (h, j)
data/examples/declaration/value/function/arrow/proc-parentheses-out.hsnew file+19
@@ -0,0 +1,19 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo f = proc a -> (f -< a)
4+
5+bar f g = proc a ->
6+ ( ( (f)
7+ ( g
8+ )
9+ )
10+ -<
11+ ( ( ( ( ( ( g
12+ a
13+ )
14+ )
15+ )
16+ )
17+ )
18+ )
19+ )
data/examples/declaration/value/function/arrow/proc-parentheses.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE Arrows #-}
2+foo f = proc a -> ( f -< a )
3+
4+bar f g = proc a ->
5+ ( ((f) (
6+ g
7+ ))
8+ -< (((((
9+ (g
10+ a)
11+ )))))
12+ )
data/examples/declaration/value/function/arrow/recursive-procs-out.hsnew file+23
@@ -0,0 +1,23 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo f g = proc (x, y) -> do
4+ rec a <- f y -< x
5+ b <-
6+ g x
7+ -<
8+ y
9+ bar
10+ -<
11+ ( a,
12+ b
13+ )
14+ rec p <-
15+ f
16+ p
17+ -<
18+ a
19+ rec q <-
20+ g
21+ q
22+ -<
23+ b
data/examples/declaration/value/function/arrow/recursive-procs.hsnew file+18
@@ -0,0 +1,18 @@
1+{-# LANGUAGE Arrows #-}
2+
3+foo f g = proc (x, y) -> do
4+ rec
5+ a <- f y -< x
6+ b
7+ <-
8+ g x
9+ -<
10+ y
11+ bar -< (
12+ a,
13+ b
14+ )
15+ rec p <- f
16+ p -< a
17+ rec q <- g
18+ q-< b
data/examples/declaration/value/function/awkward-comment-0-out.hsnew file+6
@@ -0,0 +1,6 @@
1+mergeErrorReply :: ParseError -> Reply s u a -> Reply s u a
2+mergeErrorReply err1 reply -- XXX where to put it?
3+ =
4+ case reply of
5+ Ok x state err2 -> Ok x state (mergeError err1 err2)
6+ Error err2 -> Error (mergeError err1 err2)
data/examples/declaration/value/function/awkward-comment-0.hsnew file+5
@@ -0,0 +1,5 @@
1+mergeErrorReply :: ParseError -> Reply s u a -> Reply s u a
2+mergeErrorReply err1 reply -- XXX where to put it?
3+ = case reply of
4+ Ok x state err2 -> Ok x state (mergeError err1 err2)
5+ Error err2 -> Error (mergeError err1 err2)
data/examples/declaration/value/function/awkward-comment-1-out.hsnew file+9
@@ -0,0 +1,9 @@
1+doForeign :: Vars -> [Name] -> [Term] -> Idris LExp
2+doForeign x = x
3+ where
4+ splitArg tm | (_, [_, _, l, r]) <- unApply tm -- pair, two implicits
5+ =
6+ do
7+ let l' = toFDesc l
8+ r' <- irTerm (sMN 0 "__foreignCall") vs env r
9+ return (l', r')
data/examples/declaration/value/function/awkward-comment-1.hsnew file+7
@@ -0,0 +1,7 @@
1+doForeign :: Vars -> [Name] -> [Term] -> Idris LExp
2+doForeign x = x
3+ where
4+ splitArg tm | (_, [_,_,l,r]) <- unApply tm -- pair, two implicits
5+ = do let l' = toFDesc l
6+ r' <- irTerm (sMN 0 "__foreignCall") vs env r
7+ return (l', r')
data/examples/declaration/value/function/backticks-lhs-out.hsnew file+7
@@ -0,0 +1,7 @@
1+x `op1` (Just 0) = True
2+op1 x (Just _) = False
3+op1 x Nothing = undefined
4+
5+op2 1 y = False
6+x `op2` y =
7+ True
data/examples/declaration/value/function/backticks-lhs.hsnew file+7
@@ -0,0 +1,7 @@
1+x `op1` (Just 0) = True
2+op1 x (Just _) = False
3+op1 x Nothing = undefined
4+
5+op2 1 y = False
6+x `op2` y =
7+ True
data/examples/declaration/value/function/blank-lines-let-out.hsnew file+6
@@ -0,0 +1,6 @@
1+foo =
2+ let x = 10
3+
4+ y = 11
5+ z = 12
6+ in x + y + z
data/examples/declaration/value/function/blank-lines-let.hsnew file+9
@@ -0,0 +1,9 @@
1+foo =
2+ let
3+
4+ x = 10
5+
6+ y = 11
7+ z = 12
8+
9+ in x + y + z
data/examples/declaration/value/function/blank-lines-where-out.hsnew file+6
@@ -0,0 +1,6 @@
1+foo = x + y + z
2+ where
3+ x = 10
4+
5+ y = 11
6+ z = 12
data/examples/declaration/value/function/blank-lines-where.hsnew file+7
@@ -0,0 +1,7 @@
1+foo = x + y + z
2+ where
3+
4+ x = 10
5+
6+ y = 11
7+ z = 12
data/examples/declaration/value/function/block-arguments-out.hsnew file+34
@@ -0,0 +1,34 @@
1+f1 = foo do bar
2+
3+f2 = foo do
4+ bar
5+
6+f3 = foo case True of
7+ True -> bar
8+ False -> baz
9+
10+f4 = foo let a = 3 in b
11+
12+f5 =
13+ foo
14+ let a = 3
15+ b = a
16+ in b
17+
18+f6 =
19+ foo
20+ if bar
21+ then baz
22+ else not baz
23+
24+f7 = foo \x -> y
25+
26+f8 = foo \x ->
27+ y
28+
29+f9 = foo do { bar } baz
30+
31+f10 = foo
32+ do a
33+ do b
34+ do c
data/examples/declaration/value/function/block-arguments.hsnew file+30
@@ -0,0 +1,30 @@
1+f1 = foo do bar
2+
3+f2 = foo do
4+ bar
5+
6+f3 = foo case True of
7+ True -> bar
8+ False -> baz
9+
10+f4 = foo let a = 3 in b
11+
12+f5 = foo let a = 3
13+ b = a
14+ in b
15+
16+f6 = foo if bar
17+ then baz
18+ else not baz
19+
20+f7 = foo \x -> y
21+
22+f8 = foo \x ->
23+ y
24+
25+f9 = foo do { bar } baz
26+
27+f10 = foo
28+ do { a }
29+ do { b }
30+ do c
data/examples/declaration/value/function/case-multi-line-guards-out.hsnew file+16
@@ -0,0 +1,16 @@
1+withGuards :: Int -> Int
2+withGuards x =
3+ case x of
4+ x
5+ | x > 10 ->
6+ foo
7+ + bar
8+ x | x > 5 -> 10
9+ _ -> 20
10+
11+case x of
12+ '-' | not isUrl -> case xs of
13+ _ -> emitc '-'
14+ '*' | not isUrl ->
15+ case xs of
16+ _ -> emitc '*'
data/examples/declaration/value/function/case-multi-line-guards.hsnew file+15
@@ -0,0 +1,15 @@
1+withGuards :: Int -> Int
2+withGuards x =
3+ case x of
4+ x | x > 10 ->
5+ foo +
6+ bar
7+ x | x > 5 -> 10
8+ _ -> 20
9+
10+case x of
11+ '-' | not isUrl -> case xs of
12+ _ -> emitc '-'
13+ '*' | not isUrl ->
14+ case xs of
15+ _ -> emitc '*'
data/examples/declaration/value/function/case-multi-line-out.hs+11−14
@@ -4,12 +4,13 @@ foo x = case x of
44 _ -> 12
55
66bar :: Int -> Int
7−bar x = case x of
8− 5 ->
9− if x > 5
10− then 10
11− else 12
12− _ -> 12
7+bar x =
8+ case x of
9+ 5 ->
10+ if x > 5
11+ then 10
12+ else 12
13+ _ -> 12
1314
1415baz :: Int -> Int
1516baz x = case x of
@@ -20,11 +21,7 @@ quux :: Int -> Int
2021quux x = case x of
2122 x -> x
2223
23−withGuards :: Int -> Int
24−withGuards x = case x of
25− x
26− | x > 10 ->
27− foo +
28− bar
29− x | x > 5 -> 10
30− _ -> 20
24+funnyComment =
25+ -- comment
26+ case () of
27+ () -> ()
data/examples/declaration/value/function/case-multi-line.hs+3−8
@@ -18,11 +18,6 @@ quux :: Int -> Int
1818quux x = case x of
1919 x -> x
2020
21−withGuards :: Int -> Int
22−withGuards x =
23− case x of
24− x | x > 10 ->
25− foo +
26− bar
27− x | x > 5 -> 10
28− _ -> 20
21+funnyComment = -- comment
22+ case () of
23+ () -> ()
data/examples/declaration/value/function/case-single-line-out.hs+4
@@ -1,2 +1,6 @@
11foo :: Int -> Int
22foo x = case x of x -> x
3+
4+foo :: IO ()
5+foo = case [1] of [_] -> "singleton"; _ -> "not singleton"
6+foo = case [1] of { [] -> foo; _ -> bar } `finally` baz
data/examples/declaration/value/function/case-single-line.hs+4
@@ -1,2 +1,6 @@
11foo :: Int -> Int
22foo x = case x of x -> x
3+
4+foo :: IO ()
5+foo = case [1] of [_] -> "singleton"; _ -> "not singleton"
6+foo = case [1] of { [] -> foo; _ -> bar } `finally` baz
data/examples/declaration/value/function/complex-list-out.hsnew file+15
@@ -0,0 +1,15 @@
1+handleStuff =
2+ handle
3+ [ \ExceptionA ->
4+ something,
5+ \ExceptionB ->
6+ somethingElse
7+ ]
8+
9+handleStuff =
10+ handle
11+ [ foo
12+ bar,
13+ baz
14+ qux
15+ ]
data/examples/declaration/value/function/complex-list.hsnew file+15
@@ -0,0 +1,15 @@
1+handleStuff =
2+ handle
3+ [ \ExceptionA ->
4+ something
5+ , \ExceptionB ->
6+ somethingElse
7+ ]
8+
9+handleStuff =
10+ handle
11+ [ foo
12+ bar
13+ , baz
14+ qux
15+ ]
data/examples/declaration/value/function/comprehension/transform-multi-line1-out.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+foo' xs ys =
4+ [ ( x,
5+ y
6+ )
7+ | x <- xs,
8+ y <- ys,
9+ then
10+ -- First comment
11+ reverse -- Second comment
12+ ]
data/examples/declaration/value/function/comprehension/transform-multi-line1.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+foo' xs ys = [
4+ (x,
5+ y) |
6+ x <- xs,
7+ y <- ys,
8+ then -- First comment
9+ reverse -- Second comment
10+ ]
data/examples/declaration/value/function/comprehension/transform-multi-line2-out.hsnew file+16
@@ -0,0 +1,16 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+bar' xs ys =
4+ [ ( x,
5+ y
6+ )
7+ | x <- xs,
8+ y <- ys,
9+ then
10+ -- First comment
11+ sortWith
12+ by
13+ ( x
14+ + y -- Second comment
15+ )
16+ ]
data/examples/declaration/value/function/comprehension/transform-multi-line2.hsnew file+15
@@ -0,0 +1,15 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+bar' xs ys = [
4+ (x,
5+ y) |
6+ x <- xs,
7+ y <- ys,
8+ then -- First comment
9+ sortWith
10+ by
11+ (x
12+ + y) -- Second comment
13+ ]
14+
15+
data/examples/declaration/value/function/comprehension/transform-multi-line3-out.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+baz' xs ys =
4+ [ ( x,
5+ y
6+ )
7+ | x <- xs,
8+ y <- ys,
9+ then group using
10+ -- First comment
11+ permutations -- Second comment
12+ ]
data/examples/declaration/value/function/comprehension/transform-multi-line3.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+baz' xs ys = [
4+ (x,
5+ y) |
6+ x <- xs,
7+ y <- ys,
8+ then
9+ group
10+ using -- First comment
11+ permutations -- Second comment
12+ ]
data/examples/declaration/value/function/comprehension/transform-multi-line4-out.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+quux' xs ys =
4+ [ ( x,
5+ y
6+ )
7+ | x <- xs,
8+ y <- ys,
9+ then group by
10+ -- First comment
11+ ( x
12+ + y
13+ )
14+ using
15+ -- Second comment
16+ groupWith -- Third comment
17+ ]
data/examples/declaration/value/function/comprehension/transform-multi-line4.hsnew file+15
@@ -0,0 +1,15 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+quux' xs ys = [
4+ (x,
5+ y) |
6+ x <- xs,
7+ y <- ys,
8+ then
9+ group
10+ by -- First comment
11+ (x
12+ + y)
13+ using -- Second comment
14+ groupWith -- Third comment
15+ ]
data/examples/declaration/value/function/comprehension/transform-single-line-out.hsnew file+9
@@ -0,0 +1,9 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+foo xs ys = [(x, y) | x <- xs, y <- ys, then reverse]
4+
5+bar xs ys = [(x, y) | x <- xs, y <- ys, then sortWith by (x + y)]
6+
7+baz xs ys = [(x, y) | x <- xs, y <- ys, then group using permutations]
8+
9+quux xs ys = [(x, y) | x <- xs, y <- ys, then group by (x + y) using groupWith]
data/examples/declaration/value/function/comprehension/transform-single-line.hsnew file+9
@@ -0,0 +1,9 @@
1+{-# LANGUAGE TransformListComp #-}
2+
3+foo xs ys = [(x, y) | x <- xs, y <- ys, then reverse]
4+
5+bar xs ys = [(x, y) | x <- xs, y <- ys, then sortWith by (x + y)]
6+
7+baz xs ys = [(x, y) | x <- xs, y <- ys, then group using permutations]
8+
9+quux xs ys = [(x, y) | x <- xs, y <- ys, then group by (x + y) using groupWith]
data/examples/declaration/value/function/do-out.hsdeleted−34
@@ -1,34 +0,0 @@
1−{-# LANGUAGE RecursiveDo #-}
2−bar = do
3− foo
4− bar
5−
6−baz = mdo
7− bar a
8− a <- foo
9− b <-
10− bar
11− 1
12− 2
13− 3
14− return (a + b)
15−
16−baz = do
17− a <- foo
18− let b = a + 2
19− c = b + 3
20− bar c
21− let d = c + 2
22− return d
23−
24−quux =
25− something $ do
26− foo
27− case x of
28− 1 -> 10
29− 2 -> 20
30− bar
31− if something
32− then x
33− else y
34− baz
data/examples/declaration/value/function/do-single-multi-out.hsnew file+4
@@ -0,0 +1,4 @@
1+foo = do
2+ ( bar
3+ baz
4+ )
data/examples/declaration/value/function/do-single-multi.hsnew file+2
@@ -0,0 +1,2 @@
1+foo = do (bar
2+ baz)
data/examples/declaration/value/function/do.hsdeleted−29
@@ -1,29 +0,0 @@
1−{-# LANGUAGE RecursiveDo #-}
2−
3−bar = do { foo; bar }
4−
5−baz =
6− mdo bar a
7− a <- foo
8− b <- bar
9− 1 2 3
10− return (a + b)
11−
12−baz = do
13− a <- foo
14− let b = a + 2
15− c = b + 3
16− bar c
17− let d = c + 2
18− return d
19−
20−quux = something $ do
21− foo
22− case x of
23− 1 -> 10
24− 2 -> 20
25− bar
26− if something
27− then x
28− else y
29− baz
data/examples/declaration/value/function/do/applications-and-parens-out.hsnew file+9
@@ -0,0 +1,9 @@
1+warningFor var place = do
2+ guard $ isVariableName var
3+ guard . not $ isInArray var place || isGuarded place
4+ ( if includeGlobals || isLocal var
5+ then warningForLocals
6+ else warningForGlobals
7+ )
8+ var
9+ place
data/examples/declaration/value/function/do/applications-and-parens.hsnew file+6
@@ -0,0 +1,6 @@
1+warningFor var place = do
2+ guard $ isVariableName var
3+ guard . not $ isInArray var place || isGuarded place
4+ (if includeGlobals || isLocal var
5+ then warningForLocals
6+ else warningForGlobals) var place
data/examples/declaration/value/function/do/blocks-out.hsnew file+19
@@ -0,0 +1,19 @@
1+foo = do bar
2+
3+foo = do bar; baz
4+
5+foo = do
6+ bar
7+ baz
8+
9+foo = do do { foo; bar }; baz
10+
11+readInClause = do
12+ do
13+ lookAhead g_Do
14+ parseNote ErrorC 1063 "You need a line feed or semicolon before the 'do'."
15+ <|> do
16+ optional g_Semi
17+ void allspacing
18+
19+ return things
data/examples/declaration/value/function/do/blocks.hsnew file+17
@@ -0,0 +1,17 @@
1+foo = do bar
2+foo = do { bar; baz }
3+foo = do { bar
4+ ; baz
5+ }
6+foo = do { do {foo; bar}; baz }
7+
8+readInClause = do
9+ do {
10+ lookAhead g_Do;
11+ parseNote ErrorC 1063 "You need a line feed or semicolon before the 'do'.";
12+ } <|> do {
13+ optional g_Semi;
14+ void allspacing;
15+ }
16+
17+ return things
data/examples/declaration/value/function/do/comment-alignment-out.hsnew file+9
@@ -0,0 +1,9 @@
1+main = do
2+ case blah of
3+ Nothing -> return ()
4+ Just xs -> do
5+ forM_ xs foo
6+ bar
7+ -- and here it goes
8+ unless bobla $
9+ quux
data/examples/declaration/value/function/do/comment-alignment.hsnew file+9
@@ -0,0 +1,9 @@
1+main = do
2+ case blah of
3+ Nothing -> return ()
4+ Just xs -> do
5+ forM_ xs foo
6+ bar
7+ -- and here it goes
8+ unless bobla $
9+ quux
data/examples/declaration/value/function/do/comment-spacing-out.hsnew file+7
@@ -0,0 +1,7 @@
1+foo = do
2+ bar
3+ -- foo
4+ baz
5+
6+ -- foo
7+ quux
data/examples/declaration/value/function/do/comment-spacing.hsnew file+7
@@ -0,0 +1,7 @@
1+foo = do
2+ bar
3+ -- foo
4+ baz
5+
6+ -- foo
7+ quux
data/examples/declaration/value/function/do/expr-out.hsnew file+10
@@ -0,0 +1,10 @@
1+quux = something $ do
2+ foo
3+ case x of
4+ 1 -> 10
5+ 2 -> 20
6+ bar
7+ if something
8+ then x
9+ else y
10+ baz
data/examples/declaration/value/function/do/expr.hsnew file+10
@@ -0,0 +1,10 @@
1+quux = something $ do
2+ foo
3+ case x of
4+ 1 -> 10
5+ 2 -> 20
6+ bar
7+ if something
8+ then x
9+ else y
10+ baz
data/examples/declaration/value/function/do/hang-rhs-arrow-out.hsnew file+9
@@ -0,0 +1,9 @@
1+foo = do
2+ something <- case bar of
3+ Foo -> return 1
4+ Bar -> return 2
5+ somethingElse <-
6+ case boom of
7+ Foo -> return 1
8+ Bar -> return 2
9+ quux something somethingElse
data/examples/declaration/value/function/do/hang-rhs-arrow.hsnew file+9
@@ -0,0 +1,9 @@
1+foo = do
2+ something <- case bar of
3+ Foo -> return 1
4+ Bar -> return 2
5+ somethingElse <-
6+ case boom of
7+ Foo -> return 1
8+ Bar -> return 2
9+ quux something somethingElse
data/examples/declaration/value/function/do/let-out.hsnew file+18
@@ -0,0 +1,18 @@
1+main = do
2+ a <- bar
3+ let a = b; c = d
4+ baz d
5+ let e = f
6+ g = h
7+ return c
8+
9+-- single line let-where
10+samples n f = do
11+ gen <- newQCGen
12+ let rands g = g1 : rands g2 where (g1, g2) = split g
13+ return $ rands gen
14+
15+trickyLet = do
16+ foo
17+ let x = 5
18+ in bar x
data/examples/declaration/value/function/do/let.hsnew file+18
@@ -0,0 +1,18 @@
1+main = do
2+ a <- bar
3+ let a = b; c = d
4+ baz d
5+ let e = f
6+ g = h
7+ return c
8+
9+-- single line let-where
10+samples n f = do
11+ gen <- newQCGen
12+ let rands g = g1 : rands g2 where (g1, g2) = split g
13+ return $ rands gen
14+
15+trickyLet = do
16+ foo
17+ let x = 5
18+ in bar x
data/examples/declaration/value/function/do/operator-and-parens-out.hsnew file+7
@@ -0,0 +1,7 @@
1+scientifically :: (Scientific -> a) -> Parser a
2+scientifically h = do
3+ something
4+ ( I.satisfy (\w -> w == 'e' || w == 'E')
5+ *> fmap (h . Sci.scientific signedCoeff . (e +)) (signed decimal)
6+ )
7+ <|> return (h $ Sci.scientific signedCoeff e)
data/examples/declaration/value/function/do/operator-and-parens.hsnew file+7
@@ -0,0 +1,7 @@
1+scientifically :: (Scientific -> a) -> Parser a
2+scientifically h = do
3+ something
4+ ( I.satisfy (\w -> w == 'e' || w == 'E')
5+ *> fmap (h . Sci.scientific signedCoeff . (e +)) (signed decimal)
6+ )
7+ <|> return (h $ Sci.scientific signedCoeff e)
data/examples/declaration/value/function/do/recursive-do-mdo-out.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE RecursiveDo #-}
2+
3+baz =
4+ mdo
5+ bar a
6+ a <- foo
7+ b <-
8+ bar
9+ 1
10+ 2
11+ 3
12+ return (a + b)
data/examples/declaration/value/function/do/recursive-do-mdo.hsnew file+8
@@ -0,0 +1,8 @@
1+{-# LANGUAGE RecursiveDo #-}
2+
3+baz =
4+ mdo bar a
5+ a <- foo
6+ b <- bar
7+ 1 2 3
8+ return (a + b)
data/examples/declaration/value/function/do/recursive-do-rec-out.hsnew file+19
@@ -0,0 +1,19 @@
1+{-# LANGUAGE RecursiveDo #-}
2+
3+foo = do
4+ rec a <- b + 5
5+
6+ let d = c
7+
8+ b <- a * 5
9+
10+ something
11+
12+ c <- a + b
13+ print c
14+ rec something $ do
15+ x <- a
16+ print x
17+
18+ y <- c
19+ print y
data/examples/declaration/value/function/do/recursive-do-rec.hsnew file+20
@@ -0,0 +1,20 @@
1+{-# LANGUAGE RecursiveDo #-}
2+
3+foo = do
4+ rec
5+ a <- b + 5
6+
7+ let d = c
8+
9+ b <- a * 5
10+
11+ something
12+
13+ c <- a + b
14+ print c
15+ rec something $ do
16+ x <- a
17+ print x
18+
19+ y <- c
20+ print y
data/examples/declaration/value/function/equality-constraints-out.hsnew file+2
@@ -0,0 +1,2 @@
1+foo :: (a ~ b) => a -> b -> Int
2+foo = undefined
data/examples/declaration/value/function/equality-constraints.hsnew file+2
@@ -0,0 +1,2 @@
1+foo :: (a ~ b) => a -> b -> Int
2+foo = undefined
data/examples/declaration/value/function/explicit-type-out.hs+2−2
@@ -1,5 +1,5 @@
11foo = 5 :: Int
22
33bar =
4− 5
5− :: Int
4+ 5 ::
5+ Int
data/examples/declaration/value/function/fancy-forall-0-out.hsnew file+10
@@ -0,0 +1,10 @@
1+wrapError ::
2+ forall outertag innertag t outer inner m a.
3+ ( forall x. Coercible (t m x) (m x),
4+ forall m'.
5+ HasCatch outertag outer m' =>
6+ HasCatch innertag inner (t m'),
7+ HasCatch outertag outer m
8+ ) =>
9+ (forall m'. HasCatch innertag inner m' => m' a) ->
10+ m a
data/examples/declaration/value/function/fancy-forall-0.hsnew file+6
@@ -0,0 +1,6 @@
1+wrapError :: forall outertag innertag t outer inner m a.
2+ ( forall x. Coercible (t m x) (m x)
3+ , forall m'. HasCatch outertag outer m'
4+ => HasCatch innertag inner (t m')
5+ , HasCatch outertag outer m )
6+ => (forall m'. HasCatch innertag inner m' => m' a) -> m a
data/examples/declaration/value/function/fancy-forall-1-out.hsnew file+10
@@ -0,0 +1,10 @@
1+magnify ::
2+ forall outertag innertag t outer inner m a.
3+ ( forall x. Coercible (t m x) (m x),
4+ forall m'.
5+ HasReader outertag outer m' =>
6+ HasReader innertag inner (t m'),
7+ HasReader outertag outer m
8+ ) =>
9+ (forall m'. HasReader innertag inner m' => m' a) ->
10+ m a
data/examples/declaration/value/function/fancy-forall-1.hsnew file+6
@@ -0,0 +1,6 @@
1+magnify :: forall outertag innertag t outer inner m a.
2+ ( forall x. Coercible (t m x) (m x)
3+ , forall m'. HasReader outertag outer m'
4+ => HasReader innertag inner (t m')
5+ , HasReader outertag outer m )
6+ => (forall m'. HasReader innertag inner m' => m' a) -> m a
data/examples/declaration/value/function/guards-out.hs+11−13
@@ -1,14 +1,12 @@
1−foo :: Int -> Int
2−foo x
3− | x == 5 = 10
4− | otherwise = 12
1+baz :: Int -> Int
2+baz x | x < 0 = x
3+baz x | otherwise = x
54
6−bar :: Int -> Int
7−bar x
8− | x == 5 =
9− foo x +
10− foo 10
11− | x == 6 =
12− foo x +
13− foo 20
14− | otherwise = foo 100
5+multi_baz :: Int -> Int
6+multi_baz x | x < 42 = x
7+multi_baz x | x < 0 = x
8+multi_baz x | otherwise = x
9+
10+quux :: Int -> Int
11+quux x | x < 0 = x
12+quux x = x
data/examples/declaration/value/function/guards.hs+11−11
@@ -1,12 +1,12 @@
1−foo :: Int -> Int
2−foo x
3− | x == 5 = 10
4− | otherwise = 12
1+baz :: Int -> Int
2+baz x | x < 0 = x
3+baz x | otherwise = x
54
6−bar :: Int -> Int
7−bar x
8− | x == 5 = foo x
9− + foo 10
10− | x == 6 = foo x
11− + foo 20
12− | otherwise = foo 100
5+multi_baz :: Int -> Int
6+multi_baz x | x < 42 = x
7+multi_baz x | x < 0 = x
8+multi_baz x | otherwise = x
9+
10+quux :: Int -> Int
11+quux x | x < 0 = x
12+quux x = x
data/examples/declaration/value/function/if-multi-line-out.hs+14−7
@@ -1,16 +1,23 @@
11foo :: Int -> Int
22foo x =
33 if x > 5
4− then 10
5− else 12
4+ then 10
5+ else 12
66
77bar :: Int -> Int
88bar x =
99 if x > 5
10− then
11− foo x +
12− 100
13− else
14− case x of
10+ then
11+ foo x
12+ + 100
13+ else case x of
1514 1 -> 10
1615 _ -> 20
16+
17+baz :: Int -> Bar
18+baz x =
19+ if x > 5
20+ then \case
21+ Foo -> bar
22+ else do
23+ undefined
data/examples/declaration/value/function/if-multi-line.hs+10
@@ -10,3 +10,13 @@ bar x =
1010 else case x of
1111 1 -> 10
1212 _ -> 20
13+
14+baz :: Int -> Bar
15+baz x =
16+ if x > 5
17+ then
18+ \case
19+ Foo -> bar
20+ else
21+ do
22+ undefined
data/examples/declaration/value/function/if-with-comment-out.hsnew file+8
@@ -0,0 +1,8 @@
1+foo =
2+ if undefined
3+ then -- then comment
4+ undefined
5+ else -- else comment
6+
7+ do
8+ undefined
data/examples/declaration/value/function/if-with-comment.hsnew file+8
@@ -0,0 +1,8 @@
1+foo =
2+ if undefined
3+ -- then comment
4+ then undefined
5+ -- else comment
6+ else
7+ do
8+ undefined
data/examples/declaration/value/function/implicit-params-out.hs+11
@@ -1,5 +1,16 @@
11{-# LANGUAGE ImplicitParams #-}
2+
23sortBy :: (a -> a -> Bool) -> [a] -> [a]
4+sortBy = undefined
35
46sort :: (?cmp :: a -> a -> Bool) => [a] -> [a]
57sort = sortBy ?cmp
8+
9+sort' ::
10+ ( ?cmp ::
11+ a -> a -> Bool,
12+ ?foo :: Int
13+ ) =>
14+ [a] ->
15+ [a]
16+sort' = sort
data/examples/declaration/value/function/implicit-params.hs+7
@@ -1,5 +1,12 @@
11{-# LANGUAGE ImplicitParams #-}
22sortBy :: (a -> a -> Bool) -> [a] -> [a]
33
4+sortBy = undefined
5+
46sort :: (?cmp :: a -> a -> Bool) => [a] -> [a]
57sort = sortBy ?cmp
8+
9+sort' :: (?cmp
10+ :: a -> a -> Bool
11+ ,?foo :: Int) => [a] -> [a]
12+sort' = sort
data/examples/declaration/value/function/infix/applicative-out.hsnew file+4
@@ -0,0 +1,4 @@
1+f =
2+ Foo <$> bar
3+ <*> baz
4+ <*> baz'
data/examples/declaration/value/function/infix/applicative.hsnew file+4
@@ -0,0 +1,4 @@
1+f =
2+ Foo <$> bar
3+ <*> baz
4+ <*> baz'
data/examples/declaration/value/function/infix/comments-out.hsnew file+8
@@ -0,0 +1,8 @@
1+main =
2+ bar $ -- bar
3+ baz -- baz
4+
5+bar $
6+ {- foo
7+ -}
8+ bar
data/examples/declaration/value/function/infix/comments.hsnew file+8
@@ -0,0 +1,8 @@
1+main =
2+ bar $ -- bar
3+ baz -- baz
4+
5+bar $
6+ {- foo
7+ -}
8+ bar
data/examples/declaration/value/function/infix/do-out.hsnew file+13
@@ -0,0 +1,13 @@
1+main =
2+ do stuff
3+ `finally` do
4+ recover
5+
6+main = do stuff `finally` recover
7+
8+main = do { stuff } `finally` recover
9+
10+foo =
11+ do
12+ 1
13+ + 2
data/examples/declaration/value/function/infix/do.hsnew file+13
@@ -0,0 +1,13 @@
1+main =
2+ do stuff
3+ `finally` do
4+ recover
5+
6+main = do stuff `finally` recover
7+
8+main = do { stuff } `finally` recover
9+
10+foo = do
11+ 1
12+ +
13+ 2
data/examples/declaration/value/function/infix/dollar-chains-out.hsnew file+22
@@ -0,0 +1,22 @@
1+module Main where
2+
3+foo =
4+ fmap escapeLeadingDollar
5+ . dropPaddingSpace
6+ . dropWhileEnd T.null
7+ . fmap (T.stripEnd . T.pack)
8+ . lines
9+ $ unpackHDS docStr
10+
11+foo =
12+ when (GHC.xopt Cpp dynFlags && not cfgTolerateCpp) $
13+ throwIO (OrmoluCppEnabled path)
14+
15+foo =
16+ bar $
17+ baz $
18+ quux
19+
20+x =
21+ case l of { A -> B } $
22+ case q of r -> s
data/examples/declaration/value/function/infix/dollar-chains.hsnew file+22
@@ -0,0 +1,22 @@
1+module Main where
2+
3+foo =
4+ fmap escapeLeadingDollar
5+ . dropPaddingSpace
6+ . dropWhileEnd T.null
7+ . fmap (T.stripEnd . T.pack)
8+ . lines
9+ $ unpackHDS docStr
10+
11+foo =
12+ when (GHC.xopt Cpp dynFlags && not cfgTolerateCpp) $
13+ throwIO (OrmoluCppEnabled path)
14+
15+foo =
16+ bar
17+ $ baz
18+ $ quux
19+
20+x =
21+ case l of { A -> B } $
22+ case q of r -> s
data/examples/declaration/value/function/infix/hanging-out.hsnew file+23
@@ -0,0 +1,23 @@
1+f = unFoo . foo bar baz 3 $ do
2+ act
3+ ret
4+
5+g = unFoo
6+ . foo
7+ bar
8+ baz
9+ 3
10+ $ do
11+ act
12+ ret
13+
14+update =
15+ do
16+ foobar
17+ `catch` \case
18+ a -> a
19+
20+foo =
21+ bar
22+ ++ case foo of
23+ a -> a
data/examples/declaration/value/function/infix/hanging.hsnew file+19
@@ -0,0 +1,19 @@
1+f = unFoo . foo bar baz 3 $ do
2+ act
3+ ret
4+
5+g = unFoo . foo
6+ bar
7+ baz 3 $ do
8+ act
9+ ret
10+
11+update =
12+ do
13+ foobar
14+ `catch` \case
15+ a -> a
16+
17+foo = bar ++
18+ case foo of
19+ a -> a
data/examples/declaration/value/function/infix/lenses-out.hsnew file+21
@@ -0,0 +1,21 @@
1+lenses =
2+ Just $
3+ M.fromList $
4+ "type" .= ("user.connection" :: Text)
5+ # "connection" .= uc
6+ # "user" .= case name of
7+ Just n -> Just $ object ["name" .= n]
8+ Nothing -> Nothing
9+ # []
10+
11+foo =
12+ a
13+ & b .~ 2
14+ & c .~ 3
15+
16+wreq =
17+ let opts =
18+ defaults & auth ?~ awsAuth AWSv4 "key" "secret"
19+ & header "Accept" .~ ["application/json"]
20+ & header "Runscope-Bucket-Auth" .~ ["1example-1111-4yyyy-zzzz-xxxxxxxx"]
21+ in getWith opts
data/examples/declaration/value/function/infix/lenses.hsnew file+16
@@ -0,0 +1,16 @@
1+lenses = Just $ M.fromList
2+ $ "type" .= ("user.connection" :: Text)
3+ # "connection" .= uc
4+ # "user" .= case name of
5+ Just n -> Just $ object ["name" .= n]
6+ Nothing -> Nothing
7+ # []
8+
9+foo = a
10+ & b .~ 2 & c .~ 3
11+
12+wreq =
13+ let opts = defaults & auth ?~ awsAuth AWSv4 "key" "secret"
14+ & header "Accept" .~ ["application/json"]
15+ & header "Runscope-Bucket-Auth" .~ ["1example-1111-4yyyy-zzzz-xxxxxxxx"]
16+ in getWith opts
data/examples/declaration/value/function/infix.hs → data/examples/declaration/value/function/infix/simple-out.hsrenamed+2−2
@@ -8,5 +8,5 @@ bar :: Int -> Int -> Int -> Int
88(x `bar` y) z = z
99
1010multiline :: Int -> Int -> Int
11−x `multiline`
12− y = z
11+x
12+ `multiline` y = z
data/examples/declaration/value/function/infix-out.hs → data/examples/declaration/value/function/infix/simple.hsrenamed

The content is the same.

data/examples/declaration/value/function/infix/unicode-out.hsnew file+3
@@ -0,0 +1,3 @@
1+main = print ('a' → 'a')
2+ where
3+ (→) = (,)
data/examples/declaration/value/function/infix/unicode.hsnew file+3
@@ -0,0 +1,3 @@
1+main = print ('a' → 'a')
2+ where
3+ (→) = (,)
data/examples/declaration/value/function/lambda-case-out.hs+3
@@ -1,4 +1,7 @@
11{-# LANGUAGE LambdaCase #-}
2+
3+foo = bar (\case JKey {} -> True; _ -> False)
4+
25foo :: Int -> Int
36foo = \case
47 5 -> 10
data/examples/declaration/value/function/lambda-case.hs+2
@@ -1,5 +1,7 @@
11{-# LANGUAGE LambdaCase #-}
22
3+foo = bar (\case JKey{} -> True; _ -> False)
4+
35foo :: Int -> Int
46foo = \case
57 5 -> 10
data/examples/declaration/value/function/lambda-multi-line-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−foo :: a -> a -> a
2−foo x = \y ->
3− x
4−
5−bar :: Int -> Int -> Int
6−bar x = \y ->
7− if x > y
8− then 10
9− else 12
data/examples/declaration/value/function/lambda-multi-line.hsdeleted−9
@@ -1,9 +0,0 @@
1−foo :: a -> a -> a
2−foo x = \y ->
3− x
4−
5−bar :: Int -> Int -> Int
6−bar x = \y ->
7− if x > y
8− then 10
9− else 12
data/examples/declaration/value/function/lambda-multi-line1-out.hsnew file+15
@@ -0,0 +1,15 @@
1+foo :: a -> a -> a
2+foo x = \y ->
3+ x
4+
5+bar :: Int -> Int -> Int
6+bar x = \y ->
7+ if x > y
8+ then 10
9+ else 12
10+
11+foo =
12+ prop "is inverse to closure" $
13+ \(f :: StaticPtr (Int -> Int))
14+ (x :: Int) ->
15+ (unclosure . closure) f x == deRefStaticPtr f x
data/examples/declaration/value/function/lambda-multi-line1.hsnew file+14
@@ -0,0 +1,14 @@
1+foo :: a -> a -> a
2+foo x = \y ->
3+ x
4+
5+bar :: Int -> Int -> Int
6+bar x = \y ->
7+ if x > y
8+ then 10
9+ else 12
10+
11+foo =
12+ prop "is inverse to closure" $ \(f :: StaticPtr (Int -> Int))
13+ (x :: Int) ->
14+ (unclosure . closure) f x == deRefStaticPtr f x
data/examples/declaration/value/function/lambda-multi-line2-out.hsnew file+12
@@ -0,0 +1,12 @@
1+tricky0 =
2+ flip all (zip ws gs) $ \(wt, gt) ->
3+ canUnify poly_given_ok wt gt || go False wt gt
4+
5+tricky1 =
6+ flip all (zip ws gs) $
7+ \(wt, gt) -> canUnify poly_given_ok wt gt || go False wt gt
8+
9+tricky2 =
10+ flip all (zip ws gs) $
11+ \(wt, gt) ->
12+ canUnify poly_given_ok wt gt || go False wt gt
data/examples/declaration/value/function/lambda-multi-line2.hsnew file+12
@@ -0,0 +1,12 @@
1+tricky0 =
2+ flip all (zip ws gs) $ \(wt, gt) ->
3+ canUnify poly_given_ok wt gt || go False wt gt
4+
5+tricky1 =
6+ flip all (zip ws gs) $
7+ \(wt, gt) -> canUnify poly_given_ok wt gt || go False wt gt
8+
9+tricky2 =
10+ flip all (zip ws gs) $
11+ \(wt, gt) ->
12+ canUnify poly_given_ok wt gt || go False wt gt
data/examples/declaration/value/function/lambda-single-line-out.hs+13−1
@@ -1,5 +1,17 @@
1+{-# LANGUAGE BangPatterns #-}
2+
13foo :: a -> a -> a
24foo x = \y -> x
35
46bar :: a -> a -> a
5−bar x = \y -> x
7+bar x =
8+ \y -> x
9+
10+baz :: a -> a -> a
11+baz = \ ~x ~y -> x
12+
13+zag :: a -> a -> a
14+zag = \ !x !y -> x
15+
16+spl :: a -> a
17+spl = \ $([p|x|]) -> x
data/examples/declaration/value/function/lambda-single-line.hs+11
@@ -1,6 +1,17 @@
1+{-# LANGUAGE BangPatterns #-}
2+
13foo :: a -> a -> a
24foo x = \y -> x
35
46bar :: a -> a -> a
57bar x =
68 \y -> x
9+
10+baz :: a -> a -> a
11+baz = \ ~x ~y -> x
12+
13+zag :: a -> a -> a
14+zag = \ !x !y -> x
15+
16+spl :: a -> a
17+spl = \ $([p|x|]) -> x
data/examples/declaration/value/function/let-multi-line-out.hs+19−3
@@ -2,11 +2,27 @@ foo :: Int -> Int
22foo x =
33 let z = y
44 y = x
5− in z + 100
5+ in z + 100
66
77bar :: Int -> Int
88bar x =
99 let z = y
1010 y = x
11− in z +
12− 100
11+ in z
12+ + 100
13+
14+inlineComment :: Int -> Int
15+inlineComment =
16+ let {- join -} go = case () of
17+ () -> undefined
18+ in go
19+
20+implicitParams :: HasCallStack => Int
21+implicitParams =
22+ let ?cs = ?callstack
23+ in foo cs
24+
25+sitting =
26+ foo $
27+ let x = 20
28+ in x
data/examples/declaration/value/function/let-multi-line.hs+15
@@ -10,3 +10,18 @@ bar x =
1010 y = x
1111 in z
1212 + 100
13+
14+inlineComment :: Int -> Int
15+inlineComment =
16+ let {- join -} go = case () of
17+ () -> undefined
18+ in go
19+
20+implicitParams :: HasCallStack => Int
21+implicitParams =
22+ let ?cs = ?callstack
23+ in foo cs
24+
25+sitting =
26+ foo $ let x = 20
27+ in x
data/examples/declaration/value/function/let-nested-out.hsnew file+3
@@ -0,0 +1,3 @@
1+_ = _
2+ where
3+ _ = [_ | let _ = _]
data/examples/declaration/value/function/let-nested.hsnew file+3
@@ -0,0 +1,3 @@
1+_ = _
2+ where
3+ _ = [_ | let _ = _]
data/examples/declaration/value/function/let-single-line-out.hs+8
@@ -1,2 +1,10 @@
11foo :: a -> a
22foo x = let x = x in x
3+foo x = let x = z where z = 2 in x
4+foo x = let x = z where { z = 2 }; a = 3 in x
5+foo x = let g :: Int -> Int; g = id in ()
6+
7+let a = b; c = do { foo; bar }; d = baz in b
8+let a = case True of { True -> foo; False -> bar }; b = foo a in b
9+
10+foo x = let ?g = id; ?f = g in x
data/examples/declaration/value/function/let-single-line.hs+6
@@ -1,2 +1,8 @@
11foo :: a -> a
22foo x = let x = x in x
3+foo x = let x = z where z = 2 in x
4+foo x = let x = z where { z = 2; }; a = 3 in x
5+foo x = let {g :: Int -> Int; g = id} in ()
6+let a = b; c = do { foo; bar }; d = baz in b
7+let a = case True of { True -> foo; False -> bar }; b = foo a in b
8+foo x = let {?g = id; ?f = g} in x
data/examples/declaration/value/function/list-comprehensions-out.hs+17−18
@@ -4,22 +4,21 @@ bar x y = [(a, b) | a <- x, even a, b <- y, a != b]
44
55barbaz x y z w =
66 [ (a, b, c, d) -- Foo
7− | a <-
8− x -- Bar
9− , b <- y -- Baz
10− , any even [a, b]
11− , c <-
12− z *
13− z ^
14− 2 -- Bar baz
15− , d <-
16− w +
17− w -- Baz bar
18− , all
19− even
20− [ a
21− , b
22− , c
23− , d
24− ]
7+ | a <-
8+ x, -- Bar
9+ b <- y, -- Baz
10+ any even [a, b],
11+ c <-
12+ z
13+ * z ^ 2, -- Bar baz
14+ d <-
15+ w
16+ + w, -- Baz bar
17+ all
18+ even
19+ [ a,
20+ b,
21+ c,
22+ d
23+ ]
2524 ]
data/examples/declaration/value/function/list-comprehensions.hs+1−1
@@ -1,4 +1,4 @@
1−foo x = [a|a<-x]
1+foo x = [a |a<-x]
22
33bar x y = [ (a, b) | a<-x, even a , b<-y, a != b ]
44
data/examples/declaration/value/function/list-notation-0-out.hsnew file+5
@@ -0,0 +1,5 @@
1+foo =
2+ testCase "Foo" testFoo :
3+ testCase "Bar" testBar :
4+ testCase "Baz" testBaz :
5+ []
data/examples/declaration/value/function/list-notation-0.hsnew file+5
@@ -0,0 +1,5 @@
1+foo =
2+ testCase "Foo" testFoo :
3+ testCase "Bar" testBar :
4+ testCase "Baz" testBaz :
5+ []
data/examples/declaration/value/function/list-notation-1-out.hsnew file+8
@@ -0,0 +1,8 @@
1+instance A.ToJSON UpdateTable where
2+ toJSON a =
3+ A.object $
4+ "TableName" .= updateTableName a :
5+ "ProvisionedThroughput" .= updateProvisionedThroughput a :
6+ case updateGlobalSecondaryIndexUpdates a of
7+ [] -> []
8+ l -> ["GlobalSecondaryIndexUpdates" .= l]
data/examples/declaration/value/function/list-notation-1.hsnew file+7
@@ -0,0 +1,7 @@
1+instance A.ToJSON UpdateTable where
2+ toJSON a = A.object
3+ $ "TableName" .= updateTableName a
4+ : "ProvisionedThroughput" .= updateProvisionedThroughput a
5+ : case updateGlobalSecondaryIndexUpdates a of
6+ [] -> []
7+ l -> [ "GlobalSecondaryIndexUpdates" .= l ]
data/examples/declaration/value/function/list-notation-2-out.hsnew file+6
@@ -0,0 +1,6 @@
1+-- A list of the element and all its parents up to the root node.
2+getPath tree t =
3+ t :
4+ case Map.lookup (getId t) tree of
5+ Nothing -> []
6+ Just parent -> getPath tree parent
data/examples/declaration/value/function/list-notation-2.hsnew file+5
@@ -0,0 +1,5 @@
1+-- A list of the element and all its parents up to the root node.
2+getPath tree t = t :
3+ case Map.lookup (getId t) tree of
4+ Nothing -> []
5+ Just parent -> getPath tree parent
data/examples/declaration/value/function/list-notation-3-out.hsnew file+12
@@ -0,0 +1,12 @@
1+foo =
2+ reportSDoc "tc.cc" 30 $
3+ sep $ do
4+ (prettyTCM q <+> " before compilation") : do
5+ map (prettyTCM . map unArg . clPats) cls
6+
7+foo =
8+ reportSDoc "tc.cc" 30 $
9+ sep $ do
10+ (prettyTCM q <+> " before compilation") :
11+ do
12+ map (prettyTCM . map unArg . clPats) cls
data/examples/declaration/value/function/list-notation-3.hsnew file+10
@@ -0,0 +1,10 @@
1+foo =
2+ reportSDoc "tc.cc" 30 $ sep $ do
3+ (prettyTCM q <+> " before compilation") : do
4+ map (prettyTCM . map unArg . clPats) cls
5+
6+foo =
7+ reportSDoc "tc.cc" 30 $ sep $ do
8+ (prettyTCM q <+> " before compilation") :
9+ do
10+ map (prettyTCM . map unArg . clPats) cls
data/examples/declaration/value/function/multi-way-if-out.hs+12−4
@@ -1,8 +1,16 @@
11{-# LANGUAGE MultiWayIf #-}
2+
23foo x = if | x == 5 -> 5
34
45bar x y =
5− if | x > y -> x
6− | x < y ->
7− y
8− | otherwise -> x
6+ if
7+ | x > y -> x
8+ | x < y ->
9+ y
10+ | otherwise -> x
11+
12+baz =
13+ if
14+ | p -> f
15+ | otherwise -> g
16+ x
data/examples/declaration/value/function/multi-way-if.hs+5
@@ -7,3 +7,8 @@ bar x y = if
77 | x < y
88 -> y
99 | otherwise -> x
10+
11+baz =
12+ if | p -> f
13+ | otherwise -> g
14+ x
data/examples/declaration/value/function/multiline-arguments-out.hs+1−1
@@ -4,5 +4,5 @@ foo
44 ( Bar
55 x
66 y
7− )
7+ )
88 z = x
data/examples/declaration/value/function/multiple-guards-out.hsnew file+14
@@ -0,0 +1,14 @@
1+foo :: Int -> Int
2+foo x
3+ | x == 5 = 10
4+ | otherwise = 12
5+
6+bar :: Int -> Int
7+bar x
8+ | x == 5 =
9+ foo x
10+ + foo 10
11+ | x == 6 =
12+ foo x
13+ + foo 20
14+ | otherwise = foo 100
data/examples/declaration/value/function/multiple-guards.hsnew file+13
@@ -0,0 +1,13 @@
1+foo :: Int -> Int
2+foo x
3+ | x == 5 = 10
4+ | otherwise = 12
5+
6+bar :: Int -> Int
7+bar x
8+ | x == 5 = foo x
9+ + foo 10
10+ | x == 6 = foo x
11+ + foo 20
12+ | otherwise = foo 100
13+
data/examples/declaration/value/function/negation-out.hs+6
@@ -1,2 +1,8 @@
11foo :: Int
22foo = (-2)
3+
4+bar :: Int
5+bar = -2
6+
7+baz :: Int
8+baz = - 2
data/examples/declaration/value/function/negation.hs+6
@@ -1,2 +1,8 @@
11foo :: Int
22foo = (-2)
3+
4+bar :: Int
5+bar = -2
6+
7+baz :: Int
8+baz = - 2
data/examples/declaration/value/function/operator-comments-0-out.hsnew file+16
@@ -0,0 +1,16 @@
1+foo =
2+ bar
3+ ++
4+ {- some comment -}
5+ case foo of
6+ a -> a
7+
8+foo =
9+ bar
10+ ++ {- some comment -} case foo of
11+ a -> a
12+
13+foo =
14+ bar
15+ ++ case foo {- some comment -} of
16+ a -> a
data/examples/declaration/value/function/operator-comments-0.hsnew file+17
@@ -0,0 +1,17 @@
1+foo =
2+ bar
3+ ++
4+ {- some comment -}
5+ case foo of
6+ a -> a
7+
8+foo =
9+ bar
10+ ++ {- some comment -}
11+ case foo of
12+ a -> a
13+
14+foo =
15+ bar
16+ ++ case foo of {- some comment -}
17+ a -> a
data/examples/declaration/value/function/operator-comments-1-out.hsnew file+16
@@ -0,0 +1,16 @@
1+foo =
2+ bar
3+ ++
4+ -- some comment
5+ case foo of
6+ a -> a
7+
8+foo =
9+ bar
10+ ++ case foo of -- some comment
11+ a -> a
12+
13+foo =
14+ bar
15+ ++ case foo of -- some comment
16+ a -> a
data/examples/declaration/value/function/operator-comments-1.hsnew file+17
@@ -0,0 +1,17 @@
1+foo =
2+ bar
3+ ++
4+ -- some comment
5+ case foo of
6+ a -> a
7+
8+foo =
9+ bar
10+ ++ -- some comment
11+ case foo of
12+ a -> a
13+
14+foo =
15+ bar
16+ ++ case foo of -- some comment
17+ a -> a
data/examples/declaration/value/function/operator-comments-2-out.hsnew file+5
@@ -0,0 +1,5 @@
1+x =
2+ y
3+ ++ f g -- commentA
4+ -- commentB
5+ -- commentC
data/examples/declaration/value/function/operator-comments-2.hsnew file+4
@@ -0,0 +1,4 @@
1+x =
2+ y ++ -- commentA
3+-- commentB
4+ f g -- commentC
data/examples/declaration/value/function/operator-sections-out.hs+2−2
@@ -4,10 +4,10 @@ bar = (<> "hello")
44
55baz =
66 ( 1 * 2
7− +
7+ +
88 )
99 ( *
10− 3 ^ 5
10+ 3 ^ 5
1111 )
1212
1313quux = (,) <$> foo <$> bar
data/examples/declaration/value/function/operators-0-out.hsnew file+5
@@ -0,0 +1,5 @@
1+a =
2+ b & c .~ d
3+ & e
4+ %~ f
5+ g
data/examples/declaration/value/function/operators-0.hsnew file+4
@@ -0,0 +1,4 @@
1+a =
2+ b & c .~ d
3+ & e %~ f
4+ g
data/examples/declaration/value/function/operators-1-out.hsnew file+4
@@ -0,0 +1,4 @@
1+foo =
2+ f
3+ . g
4+ =<< h . i
data/examples/declaration/value/function/operators-1.hsnew file+3
@@ -0,0 +1,3 @@
1+foo = f
2+ . g
3+ =<< h . i
data/examples/declaration/value/function/operators-2-out.hsnew file+4
@@ -0,0 +1,4 @@
1+foo n
2+ | x || y && z || n ** x
3+ || x && n =
4+ 42
data/examples/declaration/value/function/operators-2.hsnew file+4
@@ -0,0 +1,4 @@
1+foo n
2+ | x || y && z || n ** x
3+ || x && n =
4+ 42
data/examples/declaration/value/function/operators-3-out.hsnew file+3
@@ -0,0 +1,3 @@
1+foo =
2+ op <> n <+> colon <+> prettySe <+> text "="
3+ <+> prettySe <> text sc
data/examples/declaration/value/function/operators-3.hsnew file+3
@@ -0,0 +1,3 @@
1+foo =
2+ op <> n <+> colon <+> prettySe <+> text "=" <+>
3+ prettySe <> text sc
data/examples/declaration/value/function/operators-4-out.hsnew file+3
@@ -0,0 +1,3 @@
1+foo =
2+ line <> bindingOf <+> text "=" <+> tPretty <+> colon
3+ <+> align <> prettyPs
data/examples/declaration/value/function/operators-4.hsnew file+3
@@ -0,0 +1,3 @@
1+foo =
2+ line <> bindingOf <+> text "=" <+> tPretty <+> colon <+>
3+ align <> prettyPs
data/examples/declaration/value/function/operators-5-out.hsnew file+5
@@ -0,0 +1,5 @@
1+foo =
2+ map bar $
3+ [ baz
4+ ]
5+ ++ quux
data/examples/declaration/value/function/operators-5.hsnew file+4
@@ -0,0 +1,4 @@
1+foo =
2+ map bar $
3+ [ baz
4+ ] ++ quux
data/examples/declaration/value/function/operators-6-out.hsnew file+9
@@ -0,0 +1,9 @@
1+type PermuteRef =
2+ "a"
3+ :> ( "b" :> "c" :> End
4+ :<|> "c" :> "b" :> End
5+ )
6+ :<|> "b"
7+ :> ( "a" :> "c" :> End
8+ :<|> "c" :> "a" :> End
9+ )
data/examples/declaration/value/function/operators-6.hsnew file+7
@@ -0,0 +1,7 @@
1+type PermuteRef =
2+ "a" :> ( "b" :> "c" :> End
3+ :<|> "c" :> "b" :> End
4+ )
5+ :<|> "b" :> ( "a" :> "c" :> End
6+ :<|> "c" :> "a" :> End
7+ )
data/examples/declaration/value/function/overindentation-out.hsnew file+11
@@ -0,0 +1,11 @@
1+reallyincrediblyLongName =
2+ f
3+ a
4+ A
5+ { reallyincrediblyLongName =
6+ f
7+ a
8+ A
9+ { reallyincrediblyLongName
10+ }
11+ }
data/examples/declaration/value/function/overindentation.hsnew file+9
@@ -0,0 +1,9 @@
1+reallyincrediblyLongName = f
2+ a
3+ A
4+ { reallyincrediblyLongName = f
5+ a
6+ A
7+ { reallyincrediblyLongName
8+ }
9+ }
data/examples/declaration/value/function/overloaded-labels-out.hs+1
@@ -1,4 +1,5 @@
11{-# LANGUAGE OverloadedLabels #-}
2+
23foo = #field
34
45bar = (#this) (#that)
data/examples/declaration/value/function/parallel-comprehensions-complex-out.hsnew file+35
@@ -0,0 +1,35 @@
1+baz x y z w =
2+ [ ( a,
3+ b,
4+ c,
5+ d,
6+ e,
7+ f,
8+ g,
9+ h,
10+ i,
11+ j
12+ )
13+ | a <- -- Foo 1
14+ x, -- Foo 2
15+ b <- -- Bar 1
16+ y, -- Bar 2
17+ a
18+ `mod` b -- Value
19+ == 0
20+ | c <- -- Baz 1
21+ z
22+ * z -- Baz 2
23+ -- Baz 3
24+ | d <- w -- Other
25+ | e <- x * x -- Foo bar
26+ | f <- -- Foo baz 1
27+ y + y -- Foo baz 2
28+ | h <- z + z * w ^ 2 -- Bar foo
29+ | i <- -- Bar bar 1
30+ a
31+ + b, -- Bar bar 2
32+ -- Bar bar 3
33+ j <- -- Bar baz 1
34+ a + b -- Bar baz 2
35+ ]
data/examples/declaration/value/function/parallel-comprehensions.hs → data/examples/declaration/value/function/parallel-comprehensions-complex.hsrenamed−4
@@ -1,7 +1,3 @@
1−foo x y = [(a,b) | a<-x | b<-y]
2−
3−bar x y z w = [(a,b,c,d) | a<-x, b<-y, a`mod`b == 0|c<-z|d<-w ]
4−
51baz x y z w = [
62 (a,b,c,d,e,
73 f,g,h,i,j) |
data/examples/declaration/value/function/parallel-comprehensions-out.hsdeleted−37
@@ -1,37 +0,0 @@
1−foo x y = [(a, b) | a <- x | b <- y]
2−
3−bar x y z w = [(a, b, c, d) | a <- x, b <- y, a `mod` b == 0 | c <- z | d <- w]
4−
5−baz x y z w =
6− [ ( a
7− , b
8− , c
9− , d
10− , e
11− , f
12− , g
13− , h
14− , i
15− , j
16− )
17− | a <- -- Foo 1
18− x -- Foo 2
19− , b <- -- Bar 1
20− y -- Bar 2
21− , a `mod`
22− b == -- Value
23− 0
24− | c <- -- Baz 1
25− z * -- Baz 2
26− z -- Baz 3
27− | d <- w -- Other
28− | e <- x * x -- Foo bar
29− | f <- -- Foo baz 1
30− y + y -- Foo baz 2
31− | h <- z + z * w ^ 2 -- Bar foo
32− | i <- -- Bar bar 1
33− a + -- Bar bar 2
34− b -- Bar bar 3
35− , j <- -- Bar baz 1
36− a + b -- Bar baz 2
37− ]
data/examples/declaration/value/function/parallel-comprehensions-single-line-out.hsnew file+3
@@ -0,0 +1,3 @@
1+foo x y = [(a, b) | a <- x | b <- y]
2+
3+bar x y z w = [(a, b, c, d) | a <- x, b <- y, a `mod` b == 0 | c <- z | d <- w]
data/examples/declaration/value/function/parallel-comprehensions-single-line.hsnew file+4
@@ -0,0 +1,4 @@
1+foo x y = [(a,b) | a<-x | b<-y]
2+
3+bar x y z w = [(a,b,c,d) | a<-x, b<-y, a`mod`b == 0|c<-z|d<-w ]
4+
data/examples/declaration/value/function/parens-out.hsnew file+1
@@ -0,0 +1 @@
1+f = p (do foo; bar) baz
data/examples/declaration/value/function/parens.hsnew file+1
@@ -0,0 +1 @@
1+f = p (do foo; bar) baz
data/examples/declaration/value/function/parenthesis-lhs-out.hsnew file+9
@@ -0,0 +1,9 @@
1+(!=!) 2 y = 1
2+x !=! y = 2
3+
4+x ?=? [] = 123
5+(?=?) x (_ : []) = 456
6+x ?=? _ = f x x
7+ where
8+ f x 7 = 789
9+ x `f` _ = 101
data/examples/declaration/value/function/parenthesis-lhs.hsnew file+9
@@ -0,0 +1,9 @@
1+(!=!) 2 y = 1
2+x !=! y = 2
3+
4+x ?=? [] = 123
5+(?=?) x (_:[]) = 456
6+x ?=? _ = f x x
7+ where
8+ f x 7 = 789
9+ x `f` _ = 101
data/examples/declaration/value/function/pattern/as-pattern-out.hsnew file+3
@@ -0,0 +1,3 @@
1+main = case [1] of
2+ xs@(x : _) -> print (x, xs)
3+ xs@[] -> print xs
data/examples/declaration/value/function/pattern/as-pattern.hsnew file+3
@@ -0,0 +1,3 @@
1+main = case [1] of
2+ xs @ (x:_) -> print (x, xs)
3+ xs@[] -> print xs
data/examples/declaration/value/function/pattern/famous-cardano-pattern-out.hsnew file+8
@@ -0,0 +1,8 @@
1+( getNodeSettingsR
2+ :<|> getNodeInfoR
3+ :<|> getNextUpdateR
4+ :<|> restartNodeR
5+ )
6+ :<|> ( getUtxoR
7+ :<|> getConfirmedProposalsR
8+ ) = client nodeV1Api
data/examples/declaration/value/function/pattern/famous-cardano-pattern.hsnew file+7
@@ -0,0 +1,7 @@
1+( getNodeSettingsR
2+ :<|> getNodeInfoR
3+ :<|> getNextUpdateR
4+ :<|> restartNodeR
5+ ):<|>( getUtxoR
6+ :<|> getConfirmedProposalsR
7+ ) = client nodeV1Api
data/examples/declaration/value/function/pattern/multiline-case-pattern-out.hsnew file+15
@@ -0,0 +1,15 @@
1+readerBench doc name =
2+ runPure $ case (getReader name, getWriter name) of
3+ ( Right (TextReader r, rexts),
4+ Right (TextWriter w, wexts)
5+ ) -> undefined
6+
7+f xs = case xs of
8+ [ a,
9+ b
10+ ] -> a + b
11+
12+g xs = case xs of
13+ ( a
14+ : bs
15+ ) -> a + b
data/examples/declaration/value/function/pattern/multiline-case-pattern.hsnew file+12
@@ -0,0 +1,12 @@
1+readerBench doc name =
2+ runPure $ case (getReader name, getWriter name) of
3+ (Right (TextReader r, rexts),
4+ Right (TextWriter w, wexts)) -> undefined
5+
6+f xs = case xs of
7+ [ a,
8+ b ] -> a + b
9+
10+g xs = case xs of
11+ (a:
12+ bs) -> a + b
data/examples/declaration/value/function/pattern/n-plus-k-pattern-out.hs+5−1
@@ -1,4 +1,5 @@
11{-# LANGUAGE NPlusKPatterns #-}
2+
23singleline :: Int
34singleline (n + 1) = n
45
@@ -6,4 +7,7 @@ multiline :: Int
67multiline
78 ( n
89 + 1
9− ) = n
10+ ) = n
11+
12+n :: Int
13+(n + 1) = 3
data/examples/declaration/value/function/pattern/n-plus-k-pattern.hs+3
@@ -5,3 +5,6 @@ singleline (n + 1) = n
55multiline :: Int
66multiline(n
77 + 1) = n
8+
9+n :: Int
10+(n + 1) = 3
data/examples/declaration/value/function/pattern/pattern-bind-out.hs+4−1
@@ -1,6 +1,9 @@
1−foo :: Int
21foo = bar
32 where
43 Foo bar baz = quux
54 Baz
65 quux = zoo
6+
7+foo = bar
8+ where
9+ Foo bar baz = quux
data/examples/declaration/value/function/pattern/pattern-bind.hs+4−1
@@ -1,6 +1,9 @@
1−foo :: Int
21foo = bar
32 where
43 Foo bar baz = quux
54 Baz
65 quux = zoo
6+
7+foo = bar
8+ where Foo bar baz = quux
9+
data/examples/declaration/value/function/pattern/quasi-quotes-pattern-out.hs+1
@@ -1,4 +1,5 @@
11{-# LANGUAGE QuasiQuotes #-}
2+
23singleline :: ()
34singleline [yamlQQ|something|] = ()
45
data/examples/declaration/value/function/pattern/record-patterns-out.hs+3−3
@@ -13,7 +13,7 @@ baz Boom {boom = b, ..} = b
1313quux :: Boom -> Int
1414quux
1515 Boom
16− { boom = a
17− , foom = b
18− , ..
16+ { boom = a,
17+ foom = b,
18+ ..
1919 } = a + b
data/examples/declaration/value/function/pattern/sig-pattern-out.hs+2−2
@@ -2,6 +2,6 @@ f = do
22 x :: a <- g
33
44f = do
5− (x, y)
6− :: (a, b) <-
5+ (x, y) ::
6+ (a, b) <-
77 g
data/examples/declaration/value/function/pattern/splice-pattern-out.hs+3−2
@@ -1,11 +1,12 @@
11{-# LANGUAGE TemplateHaskell #-}
2+
23singleLine = case () of
34 $x -> ()
45 $(y "something") -> ()
56
67multiline = case () of
7− $( x +
8− y
8+ $( x
9+ + y
910 ) -> ()
1011 $( y
1112 "something"
data/examples/declaration/value/function/pattern/strictness-out.hsnew file+5
@@ -0,0 +1,5 @@
1+{-# LANGUAGE BangPatterns #-}
2+
3+!a = ()
4+
5+~b = ()
data/examples/declaration/value/function/pattern/strictness.hsnew file+4
@@ -0,0 +1,4 @@
1+{-# LANGUAGE BangPatterns #-}
2+
3+!a = ()
4+~b = ()
data/examples/declaration/value/function/pattern/unboxed-sum-pattern-out.hsnew file+26
@@ -0,0 +1,26 @@
1+{-# LANGUAGE UnboxedSums #-}
2+
3+v = True
4+ where
5+ (# _x #) = (# True #)
6+
7+p = True
8+ where
9+ (# _x | #) = (# | True #)
10+
11+q = True
12+ where
13+ (# | _x | #) = (# | True | #)
14+
15+z = True
16+ where
17+ (# | | _x #) = (# | | True #)
18+
19+z_multiline = True
20+ where
21+ (#
22+ | | _x
23+ #) =
24+ (#
25+ | | True
26+ #)
data/examples/declaration/value/function/pattern/unboxed-sum-pattern.hsnew file+23
@@ -0,0 +1,23 @@
1+{-# LANGUAGE UnboxedSums #-}
2+
3+v = True
4+ where
5+ (# _x #) = (# True #)
6+
7+p = True
8+ where
9+ (# _x | #) = (# | True #)
10+
11+q = True
12+ where
13+ (# | _x | #) = (# | True | #)
14+
15+z = True
16+ where
17+ (# | | _x #) = (# | | True #)
18+
19+z_multiline = True
20+ where
21+ (# |
22+ | _x #) = (# |
23+ | True #)
data/examples/declaration/value/function/pattern/view-pattern-out.hs+2−1
@@ -1,4 +1,5 @@
11{-# LANGUAGE ViewPatterns #-}
2+
23example f (f -> 4) = True
34
45f (t -> Nothing) = "Nothing"
@@ -11,4 +12,4 @@ multiline
1112 Foo
1213 bar
1314 baz
14− ) = True
15+ ) = True
data/examples/declaration/value/function/quasi-quotes-out.hs+1
@@ -1,4 +1,5 @@
11{-# LANGUAGE QuasiQuotes #-}
2+
23singleline :: Value
34singleline = [yamlQQ|something|]
45
data/examples/declaration/value/function/record-constructors-out.hsdeleted−8
@@ -1,8 +0,0 @@
1−foo = Foo {a = 3}
2−
3−bar = Bar
4− { abc = foo
5− , def = Foo {a = 10}
6− }
7−
8−baz = Baz {}
data/examples/declaration/value/function/record-constructors.hsdeleted−6
@@ -1,6 +0,0 @@
1−foo = Foo { a = 3 }
2−bar = Bar {
3− abc = foo,
4− def = Foo {a = 10}
5−}
6−baz = Baz{ }
data/examples/declaration/value/function/record-updaters-out.hsdeleted−9
@@ -1,9 +0,0 @@
1−foo x = x {a = 3}
2−
3−bar x =
4− x
5− { abc = foo
6− , def = Foo {a = 10}
7− }
8−
9−baz x = x {}
data/examples/declaration/value/function/record/constructors-out.hsnew file+31
@@ -0,0 +1,31 @@
1+foo = Foo {a = 3}
2+
3+bar =
4+ Bar
5+ { abc = foo,
6+ def = Foo {a = 10}
7+ }
8+
9+baz = Baz {}
10+
11+sym = Foo {(+) = 3}
12+
13+aLongVariableName =
14+ ALongRecordName
15+ { short = baz,
16+ aLongRecordFieldName =
17+ YetAnotherLongRecordName
18+ { yetAnotherLongRecordFieldName = "a long string"
19+ },
20+ aLongRecordFieldName2 =
21+ Just
22+ YetAnotherLongRecordName
23+ { yetAnotherLongRecordFieldName = "a long string",
24+ yetAnotherLongRecordFieldName =
25+ Just
26+ "a long string"
27+ },
28+ aLongRecordFieldName3 = do
29+ foo
30+ bar
31+ }
data/examples/declaration/value/function/record/constructors.hsnew file+22
@@ -0,0 +1,22 @@
1+foo = Foo { a = 3 }
2+bar = Bar {
3+ abc = foo,
4+ def = Foo {a = 10}
5+}
6+baz = Baz{ }
7+sym = Foo { (+) = 3 }
8+aLongVariableName =
9+ ALongRecordName
10+ { short = baz,
11+ aLongRecordFieldName = YetAnotherLongRecordName
12+ { yetAnotherLongRecordFieldName = "a long string"
13+ },
14+ aLongRecordFieldName2 = Just YetAnotherLongRecordName
15+ { yetAnotherLongRecordFieldName = "a long string",
16+ yetAnotherLongRecordFieldName = Just
17+ "a long string"
18+ },
19+ aLongRecordFieldName3 = do
20+ foo
21+ bar
22+ }
data/examples/declaration/value/function/record/dot-out.hsnew file+15
@@ -0,0 +1,15 @@
1+{-# OPTIONS_GHC -fplugin=RecordDotPreprocessor #-}
2+
3+data Foo = Foo {bar :: Int}
4+
5+mfoo = fmap (.bar) $ Nothing
6+
7+bar = (Foo 1).bar
8+
9+fooplus f n = f{foo = f.bar + n}
10+
11+fooplus' f n = f {foo = f.bar + n}
12+
13+fooplus'' f n = f {foo = f.bar + n}
14+
15+fooplus''' f n = f {foo = f.bar + n}
data/examples/declaration/value/function/record/dot.hsnew file+14
@@ -0,0 +1,14 @@
1+{-# OPTIONS_GHC -fplugin=RecordDotPreprocessor #-}
2+data Foo = Foo { bar :: Int }
3+
4+mfoo = fmap (.bar) $ Nothing
5+
6+bar = ( Foo 1).bar
7+
8+fooplus f n = f{foo = f.bar + n}
9+
10+fooplus' f n = f { foo = f.bar + n}
11+
12+fooplus'' f n = f {foo = f.bar + n}
13+
14+fooplus''' f n = f{ foo = f.bar + n}
data/examples/declaration/value/function/record/hanging-after-equal-con-out.hsnew file+8
@@ -0,0 +1,8 @@
1+foo =
2+ Foo
3+ { foo =
4+ -- Blah blah
5+ case x of
6+ Blah -> 1
7+ Blim -> 2
8+ }
data/examples/declaration/value/function/record/hanging-after-equal-con.hsnew file+7
@@ -0,0 +1,7 @@
1+foo = Foo
2+ { foo =
3+ -- Blah blah
4+ case x of
5+ Blah -> 1
6+ Blim -> 2
7+ }
data/examples/declaration/value/function/record/hanging-after-equal-update-out.hsnew file+8
@@ -0,0 +1,8 @@
1+foo =
2+ foo
3+ { foo =
4+ -- Blah blah
5+ case x of
6+ Blah -> 1
7+ Blim -> 2
8+ }
data/examples/declaration/value/function/record/hanging-after-equal-update.hsnew file+7
@@ -0,0 +1,7 @@
1+foo = foo
2+ { foo =
3+ -- Blah blah
4+ case x of
5+ Blah -> 1
6+ Blim -> 2
7+ }
data/examples/declaration/value/function/record/inter-comments-out.hsnew file+13
@@ -0,0 +1,13 @@
1+x =
2+ Just
3+ -- comment
4+ A
5+ { x
6+ }
7+
8+x =
9+ Just
10+ -- comment
11+ a
12+ { x
13+ }
data/examples/declaration/value/function/record/inter-comments.hsnew file+11
@@ -0,0 +1,11 @@
1+x = Just
2+ -- comment
3+ A
4+ { x
5+ }
6+
7+x = Just
8+ -- comment
9+ a
10+ { x
11+ }
data/examples/declaration/value/function/record/updaters-out.hsnew file+11
@@ -0,0 +1,11 @@
1+foo x = x {a = 3}
2+
3+bar x =
4+ x
5+ { abc = foo,
6+ def = Foo {a = 10}
7+ }
8+
9+baz x = x {}
10+
11+sym x = x {(+) = 4}
data/examples/declaration/value/function/record-updaters.hs → data/examples/declaration/value/function/record/updaters.hsrenamed+1
@@ -4,3 +4,4 @@ bar x = x {
44 def = Foo {a = 10}
55}
66baz x = x{ }
7+sym x = x { (+) = 4 }
data/examples/declaration/value/function/record-wildcards-out.hs → data/examples/declaration/value/function/record/wildcards-out.hsrenamed+8−6
@@ -1,12 +1,14 @@
11{-# LANGUAGE NamedFieldPuns #-}
22{-# LANGUAGE RecordWildCards #-}
3+
34foo x y = Foo {x, y}
45
5−bar x y z = Bar
6− { x
7− , y
8− , z
9− , ..
10− }
6+bar x y z =
7+ Bar
8+ { x,
9+ y,
10+ z,
11+ ..
12+ }
1113
1214baz = Baz {..}
data/examples/declaration/value/function/record-wildcards.hs → data/examples/declaration/value/function/record/wildcards.hsrenamed

The content is the same.

data/examples/declaration/value/function/splice-out.hs+1
@@ -1,4 +1,5 @@
11{-# LANGUAGE TemplateHaskell #-}
2+
23bar = $bar
34
45bar' = $(bar "something")
data/examples/declaration/value/function/static-pointers-out.hs+7−5
@@ -1,18 +1,20 @@
11{-# LANGUAGE StaticPointers #-}
2+
23foo :: StaticPtr Int
34foo = static 5
45
56bar :: StaticPtr [Int]
67bar =
78 static
8− [ 1
9− , 2
10− , 3
9+ [ 1,
10+ 2,
11+ 3
1112 ]
1213
1314baz :: StaticPtr Bool
1415baz =
1516 static
16− ( fun 1
17− 2
17+ ( fun
18+ 1
19+ 2
1820 )
data/examples/declaration/value/function/strings-out.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE MagicHash #-}
2+
3+foo = "foobar"
4+
5+bar = "foo\&barbaz"
6+
7+baz =
8+ "foo\
9+ \bar\
10+ \baz"
data/examples/declaration/value/function/strings.hsnew file+7
@@ -0,0 +1,7 @@
1+{-# LANGUAGE MagicHash #-}
2+
3+foo = "foobar"
4+bar = "foo\&bar\ \baz"
5+baz = "foo\
6+ \bar\
7+ \baz"
data/examples/declaration/value/function/tricky-parens-out.hsnew file+4
@@ -0,0 +1,4 @@
1+handleStuff =
2+ ( let foo = foo
3+ in foo
4+ )
data/examples/declaration/value/function/tricky-parens.hsnew file+4
@@ -0,0 +1,4 @@
1+handleStuff =
2+ ( let foo = foo
3+ in foo
4+ )
data/examples/declaration/value/function/tuple-sections-out.hs+2−2
@@ -1,8 +1,8 @@
11{-# LANGUAGE TupleSections #-}
2+
23foo = (,2)
34
45bar = (,5,)
56
67baz =
7− ( ,,5,6,7,,,
8− )
8+ (,,5,6,7,,,)
data/examples/declaration/value/function/tuples-out.hs+10−3
@@ -1,7 +1,14 @@
11foo = (1, 2, 3)
22
33bar =
4− ( 1
5− , 2
6− , 3
4+ ( 1,
5+ 2,
6+ 3
7+ )
8+
9+handleStuff =
10+ ( let foo = foo
11+ in foo,
12+ let bar = bar
13+ in bar
714 )
data/examples/declaration/value/function/tuples.hs+7
@@ -4,3 +4,10 @@ bar = (
44 2,
55 3
66 )
7+
8+handleStuff =
9+ ( let foo = foo
10+ in foo
11+ , let bar = bar
12+ in bar
13+ )
data/examples/declaration/value/function/type-applications-and-splice-out.hsnew file+4
@@ -0,0 +1,4 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+{-# LANGUAGE TypeApplications #-}
3+
4+staticKey name = [|sing @ $(symFQN name)|]
data/examples/declaration/value/function/type-applications-and-splice.hsnew file+4
@@ -0,0 +1,4 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+{-# LANGUAGE TypeApplications #-}
3+
4+staticKey name = [| sing @ $(symFQN name) |]
data/examples/declaration/value/function/type-applications-out.hs+7
@@ -1,4 +1,5 @@
11{-# LANGUAGE TypeApplications #-}
2+
23foo = f @String a b c
34
45bar = f @(Maybe Int) a b
@@ -7,3 +8,9 @@ baz =
78 f @Int @String
89 a
910 b
11+
12+goo =
13+ hash
14+ @(HASH TPraosStandardCrypto)
15+ @ByteString
16+ "And the lamb lies down on Broadway"
data/examples/declaration/value/function/type-applications.hs+5
@@ -6,3 +6,8 @@ bar = f @(Maybe Int) a b
66
77baz = f @Int @String
88 a b
9+
10+goo = hash
11+ @(HASH TPraosStandardCrypto)
12+ @ByteString
13+ "And the lamb lies down on Broadway"
data/examples/declaration/value/function/typed-expressions-out.hs+2−2
@@ -1,5 +1,5 @@
11foo x = x :: Int
22
33bar x =
4− Just x
5− :: Maybe String
4+ Just x ::
5+ Maybe String
data/examples/declaration/value/function/typed-hole-out.hsnew file+5
@@ -0,0 +1,5 @@
1+foo = 1 `_` 2
2+
3+bar = 1 `_a` 2
4+
5+baz = _ `something` _
data/examples/declaration/value/function/typed-hole.hsnew file+5
@@ -0,0 +1,5 @@
1+foo = 1 `_` 2
2+
3+bar = 1 `_a` 2
4+
5+baz = _ `something` _
data/examples/declaration/value/function/unboxed-string-lit-out.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# LANGUAGE MagicHash #-}
2+
3+main = new "p"#
data/examples/declaration/value/function/unboxed-string-lit.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# LANGUAGE MagicHash #-}
2+
3+main = new "p"#
data/examples/declaration/value/function/unboxed-sums-out.hs+3−1
@@ -1,8 +1,10 @@
11{-# LANGUAGE UnboxedSums #-}
2+
23foo = (# 1 | #)
34
45bar = (# | | 2 | #)
56
67baz =
7− (# | | | 10 | | | | |
8+ (#
9+ | | | 10 | | | | |
810 #)
data/examples/declaration/value/function/unboxed-tuples-out.hs+5−3
@@ -1,8 +1,10 @@
11{-# LANGUAGE UnboxedTuples #-}
2+
23foo = (# 1, 2, 3 #)
34
45bar =
5− (# 1
6− , 2
7− , 3
6+ (#
7+ 1,
8+ 2,
9+ 3
810 #)
data/examples/declaration/value/function/where-nested-out.hsnew file+12
@@ -0,0 +1,12 @@
1+foo = bar
2+ where
3+ f1 = f1
4+ where
5+ f1 = 3
6+ f2 = f2
7+ where
8+ f2 = 3
9+
10+foo2 = bar
11+ where
12+ f1 = f1 where { f1 = 3; f1' = 4 }; f2 = f2 where f2 = 3; f2' = 4
data/examples/declaration/value/function/where-nested.hsnew file+12
@@ -0,0 +1,12 @@
1+foo = bar
2+ where
3+ f1 = f1
4+ where
5+ f1 = 3
6+ f2 = f2
7+ where
8+ f2 = 3
9+
10+foo2 = bar
11+ where
12+ { f1 = f1 where { f1 = 3; f1' = 4 }; f2 = f2 where { f2 = 3; f2' = 4 } }
data/examples/declaration/value/function/where-out.hs+5−3
@@ -1,7 +1,5 @@
11foo :: Int -> Int
2−foo x = f x
3− where
4− f z = z
2+foo x = f x where f z = z
53
64bar :: Int -> Int
75bar x = f x
@@ -15,3 +13,7 @@ baz x = q
1513 y = x
1614 z = y
1715 q = z
16+
17+emptyWhere :: Int
18+emptyWhere = 5
19+ where
data/examples/declaration/value/function/where.hs+4
@@ -13,3 +13,7 @@ baz x = q
1313 y = x
1414 z = y
1515 q = z
16+
17+emptyWhere :: Int
18+emptyWhere = 5
19+ where
data/examples/declaration/value/other/comments-get-before-op-out.hsnew file+10
@@ -0,0 +1,10 @@
1+main :: IO ()
2+main = do
3+ migrateSchema
4+ [ migration1,
5+ migration1,
6+ migration3
7+ -- When adding migrations here, don't forget to update
8+ -- 'schemaVersion' in Galley.Data
9+ ]
10+ `finally` Log.close
data/examples/declaration/value/other/comments-get-before-op.hsnew file+11
@@ -0,0 +1,11 @@
1+main :: IO ()
2+main = do
3+ migrateSchema
4+ [ migration1
5+ , migration1
6+ , migration3
7+ -- When adding migrations here, don't forget to update
8+ -- 'schemaVersion' in Galley.Data
9+ ]
10+ `finally`
11+ Log.close
data/examples/declaration/value/other/line-multi-line-out.hs+3−3
@@ -1,6 +1,6 @@
11x :: [Int]
22x =
3− [ 1
4− , 2
5− , somethingSomething 3
3+ [ 1,
4+ 2,
5+ somethingSomething 3
66 ]
data/examples/declaration/value/pattern-synonyms/bidirectional-out.hs+21
@@ -1,7 +1,28 @@
1+{-# LANGUAGE NamedFieldPuns #-}
2+{-# LANGUAGE PatternSynonyms #-}
3+
14pattern Arrow t1 t2 = App "->" [t1, t2]
5+
6+pattern Arrow {t1, t2} = App "->" [t1, t2]
7+
8+pattern Arrow
9+ { t1,
10+ t2
11+ } =
12+ App "->" [t1, t2]
13+
214pattern Int =
315 App "Int" []
16+
17+pattern Maybe {t} =
18+ App
19+ "Maybe"
20+ [t]
21+
422pattern Maybe t =
523 App
624 "Maybe"
725 [t]
26+
27+pattern a :< b <-
28+ (a, b)
data/examples/declaration/value/pattern-synonyms/bidirectional.hs+14
@@ -1,7 +1,21 @@
1+{-# LANGUAGE PatternSynonyms #-}
2+{-# LANGUAGE NamedFieldPuns #-}
3+
14pattern Arrow t1 t2 = App "->" [t1, t2]
5+pattern Arrow{t1,t2} = App "->" [t1,t2]
6+pattern Arrow{t1
7+ , t2} = App "->" [t1, t2]
28pattern Int =
39 App "Int" []
10+pattern Maybe{t} =
11+ App
12+ "Maybe"
13+ [t]
414pattern Maybe t =
515 App
616 "Maybe"
717 [t]
18+
19+pattern a :< b <-
20+ (a , b)
21+
data/examples/declaration/value/pattern-synonyms/explicitely-bidirectional-out.hs+11
@@ -1,4 +1,5 @@
11{-# LANGUAGE PatternSynonyms #-}
2+
23pattern HeadC x <-
34 x : xs
45 where
@@ -8,3 +9,13 @@ pattern HeadC' x <-
89 x : xs
910 where
1011 HeadC' x = [x]
12+
13+pattern Simple <-
14+ "Simple"
15+ where
16+ Simple = "Complicated"
17+
18+pattern a :< b <-
19+ (a, b)
20+ where
21+ a :< b = (a, b)
data/examples/declaration/value/pattern-synonyms/explicitely-bidirectional.hs+10
@@ -7,3 +7,13 @@ pattern HeadC' x <-
77 x:xs
88 where
99 HeadC' x = [x]
10+
11+pattern Simple <- "Simple"
12+ where
13+ Simple = "Complicated"
14+
15+pattern a :< b <-
16+ (a , b)
17+ where
18+ a :< b = (a, b)
19+
data/examples/declaration/value/pattern-synonyms/unidirectional-out.hs+18
@@ -1,5 +1,23 @@
11{-# LANGUAGE PatternSynonyms #-}
2+
23pattern Head x <- x : xs
34
45pattern Head' x <-
56 x : xs
7+
8+pattern Head'' {x} <-
9+ x : xs
10+
11+pattern FirstTwo {x, y} <-
12+ x : (y : xs)
13+
14+pattern FirstTwo'
15+ { x,
16+ y
17+ } <-
18+ x : (y : xs)
19+
20+pattern Simple <- "Simple"
21+
22+pattern WithTypeSig :: String
23+pattern WithTypeSig <- "WithTypeSig"
data/examples/declaration/value/pattern-synonyms/unidirectional.hs+14
@@ -4,3 +4,17 @@ pattern Head x <- x:xs
44
55pattern Head' x
66 <- x:xs
7+
8+pattern Head''{x}
9+ <- x:xs
10+
11+pattern FirstTwo{x,y}
12+ <- x : (y : xs)
13+
14+pattern FirstTwo'{x
15+ , y} <- x : (y:xs)
16+
17+pattern Simple <- "Simple"
18+
19+pattern WithTypeSig :: String
20+pattern WithTypeSig <- "WithTypeSig"
data/examples/declaration/warning/warning-multiline-out.hsnew file+9
@@ -0,0 +1,9 @@
1+{-# WARNING
2+ test,
3+ foo
4+ [ "These are bad functions",
5+ "Really bad!"
6+ ]
7+ #-}
8+test :: IO ()
9+test = pure ()
data/examples/declaration/warning/warning-multiline.hsnew file+4
@@ -0,0 +1,4 @@
1+{-# WArNING test,
2+ foo ["These are bad functions", "Really bad!"] #-}
3+test :: IO ()
4+test = pure ()
data/examples/declaration/warning/warning-single-line-out.hsnew file+13
@@ -0,0 +1,13 @@
1+{-# DEPRECATED test, foo "This is a deprecation" #-}
2+{-# WARNING test "This is a warning" #-}
3+test :: IO ()
4+test = pure ()
5+
6+bar = 3
7+{-# DEPRECATED bar "Bar is deprecated" #-}
8+
9+{-# DEPRECATED baz "Baz is also deprecated" #-}
10+baz = 5
11+
12+data Number = Number Dobule
13+{-# DEPRECATED Number "Use Scientific instead." #-}
data/examples/declaration/warning/warning-single-line.hsnew file+15
@@ -0,0 +1,15 @@
1+{-# Deprecated test, foo "This is a deprecation"
2+ #-}
3+{-# WARNING test ["This is a warning" ] #-}
4+test :: IO ()
5+test = pure ()
6+
7+bar = 3
8+
9+{-# Deprecated bar "Bar is deprecated" #-}
10+
11+{-# DEPRECATED baz "Baz is also deprecated" #-}
12+baz = 5
13+
14+data Number = Number Dobule
15+{-# DEPRECATED Number "Use Scientific instead." #-}
data/examples/import/comments-inside-imports-out.hsnew file+7
@@ -0,0 +1,7 @@
1+-- x
2+
3+import qualified -- x
4+ Bar
5+import qualified -- x
6+ Baz
7+import Foo
data/examples/import/comments-inside-imports.hsnew file+9
@@ -0,0 +1,9 @@
1+import -- x
2+ Foo
3+
4+import -- x
5+ qualified Bar
6+
7+import qualified
8+ -- x
9+ Baz
data/examples/import/deduplication-bug-out.hsnew file+6
@@ -0,0 +1,6 @@
1+import Foo1 (Bar1 (..), Baz1)
2+import Foo2 (Bar2 (..), Baz2)
3+import Foo3 (Bar3 (x1, x2, x3))
4+import Foo4 (Bar4 (x1, x2))
5+import Foo5 (Bar5 (x1))
6+import Foo6 (Bar6 (..))
data/examples/import/deduplication-bug.hsnew file+6
@@ -0,0 +1,6 @@
1+import Foo1 (Bar1, Baz1, Bar1(..))
2+import Foo2 (Bar2(..), Baz2, Bar2)
3+import Foo3 (Bar3(x1,x3), Bar3(x1, x2))
4+import Foo4 (Bar4(x1), Bar4(x2))
5+import Foo5 (Bar5, Bar5(x1))
6+import Foo6 (Bar6(x1), Bar6(..))
data/examples/import/explicit-imports-out.hs+10−10
@@ -1,12 +1,12 @@
11import qualified MegaModule as M
2− ( (<<<)
3− , (>>>)
4− , Either
5− , Maybe (Just, Nothing)
6− , MaybeT (..)
7− , Monad ((>>), (>>=), return)
8− , MonadBaseControl
9− , join
10− , liftIO
11− , void
2+ ( Either,
3+ Maybe (Just, Nothing),
4+ MaybeT (..),
5+ Monad (return, (>>), (>>=)),
6+ MonadBaseControl,
7+ join,
8+ liftIO,
9+ void,
10+ (<<<),
11+ (>>>),
1212 )
data/examples/import/explicit-imports-with-comments-out.hs+4−3
@@ -1,6 +1,7 @@
11import qualified MegaModule as M
22 ( -- (1)
3− (<<<) -- (2)
4− , (>>>)
5− , Either -- (3)
3+ -- (2)
4+ Either, -- (3)
5+ (<<<),
6+ (>>>),
67 )
data/examples/import/merging-0-out.hsnew file+3
@@ -0,0 +1,3 @@
1+import Foo
2+import Foo (bar, foo)
3+import Foo as F
data/examples/import/merging-0.hsnew file+4
@@ -0,0 +1,4 @@
1+import Foo
2+import Foo (foo)
3+import Foo (bar)
4+import Foo as F
data/examples/import/merging-1-out.hsnew file+2
@@ -0,0 +1,2 @@
1+import "bar" Foo (bar)
2+import "foo" Foo (baz, foo)
data/examples/import/merging-1.hsnew file+3
@@ -0,0 +1,3 @@
1+import "foo" Foo (foo)
2+import "bar" Foo (bar)
3+import "foo" Foo (baz)
data/examples/import/merging-2-out.hsnew file+2
@@ -0,0 +1,2 @@
1+import Foo hiding (bar4, foo2)
2+import qualified Foo (bar3, foo1)
data/examples/import/merging-2.hsnew file+4
@@ -0,0 +1,4 @@
1+import qualified Foo (foo1)
2+import Foo hiding (foo2)
3+import qualified Foo (bar3)
4+import Foo hiding (bar4)
data/examples/import/misc-out.hs+1−7
@@ -1,11 +1,5 @@
11import A hiding
2− ( foobarbazqux
3− , foobarbazqux
4− , foobarbazqux
5− , foobarbazqux
6− , foobarbazqux
7− , foobarbazqux
8− , foobarbazqux
2+ ( foobarbazqux,
93 )
104import {-# SOURCE #-} safe qualified Module as M hiding (a, b, c, d, e, f)
115import Name hiding ()
data/examples/import/nested-explicit-imports-out.hs+8−8
@@ -1,10 +1,10 @@
11import qualified MegaModule as M
2− ( (<<<)
3− , (>>>)
4− , Either
5− , Monad
6− ( (>>)
7− , (>>=)
8− , return
9− )
2+ ( Either,
3+ Monad
4+ ( return,
5+ (>>),
6+ (>>=)
7+ ),
8+ (<<<),
9+ (>>>),
1010 )
data/examples/import/qualified-post-out.hsnew file+5
@@ -0,0 +1,5 @@
1+{-# LANGUAGE ImportQualifiedPost #-}
2+
3+import Data.Text qualified (a, b, c)
4+import Data.Text qualified hiding (a, b, c)
5+import Data.Text qualified as T
data/examples/import/qualified-post.hsnew file+5
@@ -0,0 +1,5 @@
1+{-# LANGUAGE ImportQualifiedPost #-}
2+
3+import qualified Data.Text as T
4+import qualified Data.Text (a, c, b)
5+import Data.Text qualified hiding (c, b, a)
data/examples/import/qualified-prelude-out.hsnew file+4
@@ -0,0 +1,4 @@
1+module P where
2+
3+import Prelude hiding (id, (.))
4+import qualified Prelude
data/examples/import/qualified-prelude.hsnew file+4
@@ -0,0 +1,4 @@
1+module P where
2+
3+import Prelude hiding (id, (.))
4+import qualified Prelude
data/examples/import/simple-out.hs+2−3
@@ -1,6 +1,5 @@
11import Data.Text
2−import Data.Text
3−import qualified Data.Text as T
4−import qualified Data.Text (a, b, c)
52import Data.Text (a, b, c)
63import Data.Text hiding (a, b, c)
4+import qualified Data.Text (a, b, c)
5+import qualified Data.Text as T
data/examples/import/simple.hs+2
@@ -4,3 +4,5 @@ import qualified Data.Text as T
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.hsnew file+1
@@ -0,0 +1 @@
1+import Linear.Vector (Additive (..), (*^), (^*))
data/examples/import/sorted-export-list.hsnew file+1
@@ -0,0 +1 @@
1+import Linear.Vector (Additive (..), (*^), (^*))
data/examples/module-header/double-dot-with-names-out.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# LANGUAGE PatternSynonyms #-}
2+
3+module ExportSyntax (A (.., NoA), Q (F, ..), G (T, .., U)) where
4+
5+data A = A | B
6+
7+pattern NoA = B
8+
9+data Q a = Q a
10+
11+pattern F a = Q a
12+
13+data G = G | H
14+
15+pattern T = G
16+
17+pattern U = H
data/examples/module-header/double-dot-with-names.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# LANGUAGE PatternSynonyms #-}
2+
3+module ExportSyntax ( A(.., NoA), Q(F,..), G(T,..,U)) where
4+
5+data A = A | B
6+
7+pattern NoA = B
8+
9+data Q a = Q a
10+
11+pattern F a = Q a
12+
13+data G = G | H
14+
15+pattern T = G
16+
17+pattern U = H
data/examples/module-header/leading-empty-line-out.hsnew file+11
@@ -0,0 +1,11 @@
1+-- |
2+-- Module : Text.Megaparsec
3+-- Copyright : © 2015–2019 Megaparsec contributors
4+-- © 2007 Paolo Martini
5+-- © 1999–2001 Daan Leijen
6+-- License : FreeBSD
7+--
8+-- Maintainer : Mark Karpov <markkarpov92@gmail.com>
9+-- Stability : experimental
10+-- Portability : portable
11+module Main where
data/examples/module-header/leading-empty-line.hsnew file+11
@@ -0,0 +1,11 @@
1+-- |
2+-- Module : Text.Megaparsec
3+-- Copyright : © 2015–2019 Megaparsec contributors
4+-- © 2007 Paolo Martini
5+-- © 1999–2001 Daan Leijen
6+-- License : FreeBSD
7+--
8+-- Maintainer : Mark Karpov <markkarpov92@gmail.com>
9+-- Stability : experimental
10+-- Portability : portable
11+module Main where
data/examples/module-header/multiline-out.hs+3−3
@@ -1,6 +1,6 @@
11module Foo
2− ( foo
3− , bar
4− , baz
2+ ( foo,
3+ bar,
4+ baz,
55 )
66where
data/examples/module-header/multiline-with-comments-out.hs+13−12
@@ -1,20 +1,21 @@
1−-- | Header.
2−
31{-# LANGUAGE FlexibleContexts #-}
42{-# LANGUAGE TypeFamilies #-}
3+
4+-- | Header.
55module My.Module
66 ( -- * Something
7− foo
8− , bar
9− , -- * Another thing
10− (<?>)
11− , {- some other thing -} foo2 -- yet another
12− , foo3 -- third one
13− , baz
14− , bar2 -- a multiline comment
7+ foo,
8+ bar,
9+
10+ -- * Another thing
11+ (<?>),
12+ {- some other thing -} foo2, -- yet another
13+ foo3, -- third one
14+ baz,
15+ bar2, -- a multiline comment
1516 -- the second line
16− , bar3
17− , module Foo.Bar.Baz
17+ bar3,
18+ module Foo.Bar.Baz,
1819 )
1920where
2021
data/examples/module-header/multiline2-out.hs+3−3
@@ -1,6 +1,6 @@
11module Foo
2− ( foo
3− , bar
4− , baz
2+ ( foo,
3+ bar,
4+ baz,
55 )
66where
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/named-section-out.hsnew file+13
@@ -0,0 +1,13 @@
1+module Magic
2+ ( -- * Something
3+ -- $explanation
4+
5+ -- ** Another level
6+ foo,
7+ bar,
8+ )
9+where
10+
11+-- $explanation
12+--
13+-- Here it goes.
data/examples/module-header/named-section.hsnew file+13
@@ -0,0 +1,13 @@
1+module Magic
2+ ( -- * Something
3+ -- $explanation
4+
5+ -- ** Another level
6+ foo
7+ , bar
8+ )
9+where
10+
11+-- $explanation
12+--
13+-- Here it goes.
data/examples/module-header/preceding-comment-with-haddock-out.hsnew file+8
@@ -0,0 +1,8 @@
1+{-
2+ Here we go.
3+-}
4+
5+-- | This is the module's Haddock.
6+module Main (main) where
7+
8+main = return ()
data/examples/module-header/preceding-comment-with-haddock.hsnew file+8
@@ -0,0 +1,8 @@
1+{-
2+ Here we go.
3+-}
4+
5+-- | This is the module's Haddock.
6+module Main (main) where
7+
8+main = return ()
data/examples/module-header/shebang-out.hsnew file+6
@@ -0,0 +1,6 @@
1+#! /usr/bin/env runhaskell
2+
3+import Prelude
4+
5+main :: IO ()
6+main = putStrLn "hello world"
data/examples/module-header/shebang-with-pragmas-out.hsnew file+5
@@ -0,0 +1,5 @@
1+#!/usr/bin/env stack
2+
3+{-# LANGUAGE OverloadedStrings #-}
4+
5+main = pure ()
data/examples/module-header/shebang-with-pragmas.hsnew file+5
@@ -0,0 +1,5 @@
1+#!/usr/bin/env stack
2+
3+{-# LANGUAGE OverloadedStrings #-}
4+
5+main = pure ()
data/examples/module-header/shebang.hsnew file+6
@@ -0,0 +1,6 @@
1+#! /usr/bin/env runhaskell
2+
3+import Prelude
4+
5+main :: IO ()
6+main = putStrLn "hello world"
data/examples/module-header/singleline-empty-out.hsnew file+2
@@ -0,0 +1,2 @@
1+-- | This demonstrates a BUG.
2+module Foo () where
data/examples/module-header/singleline-empty.hsnew file+2
@@ -0,0 +1,2 @@
1+-- | This demonstrates a BUG.
2+module Foo () where
data/examples/module-header/stack-header-0-out.hsnew file+7
@@ -0,0 +1,7 @@
1+-- stack runhaskell
2+
3+{-# LANGUAGE OverloadedStrings #-}
4+
5+main = return ()
6+
7+-- stack runhaskell
data/examples/module-header/stack-header-0.hsnew file+4
@@ -0,0 +1,4 @@
1+-- stack runhaskell
2+{-# LANGUAGE OverloadedStrings #-}
3+main = return ()
4+-- stack runhaskell
data/examples/module-header/stack-header-1-out.hsnew file+8
@@ -0,0 +1,8 @@
1+#!/usr/bin/env stack
2+-- stack runhaskell
3+
4+{-# LANGUAGE OverloadedStrings #-}
5+
6+main = return ()
7+
8+-- stack runhaskell
data/examples/module-header/stack-header-1.hsnew file+5
@@ -0,0 +1,5 @@
1+#!/usr/bin/env stack
2+-- stack runhaskell
3+{-# LANGUAGE OverloadedStrings #-}
4+main = return ()
5+-- stack runhaskell
data/examples/module-header/stack-header-2-out.hsnew file+12
@@ -0,0 +1,12 @@
1+#!/usr/bin/env stack
2+{- stack
3+ script
4+ --resolver lts-6.25
5+ --package turtle
6+ --package "stm async"
7+ --package http-client,http-conduit
8+-}
9+
10+{-# LANGUAGE OverloadedStrings #-}
11+
12+main = return ()
data/examples/module-header/stack-header-2.hsnew file+12
@@ -0,0 +1,12 @@
1+#!/usr/bin/env stack
2+{- stack
3+ script
4+ --resolver lts-6.25
5+ --package turtle
6+ --package "stm async"
7+ --package http-client,http-conduit
8+-}
9+
10+{-# LANGUAGE OverloadedStrings #-}
11+
12+main = return ()
data/examples/module-header/warning-pragma-list-multiline-out.hs+5−5
@@ -1,11 +1,11 @@
11module Test
22 {-# DEPRECATED
3− [ "This module is deprecated."
4− , "Please use OtherModule instead."
3+ [ "This module is deprecated.",
4+ "Please use OtherModule instead."
55 ]
66 #-}
7− ( foo
8− , bar
9− , baz
7+ ( foo,
8+ bar,
9+ baz,
1010 )
1111where
data/examples/module-header/warning-pragma-multiline-out.hs+3−5
@@ -1,8 +1,6 @@
1−module Test {-# DEPRECATED "This module is unstable" #-}
2− ( foo
3− , bar
4− , baz
5− )
1+module Test
2+ {-# DEPRECATED "This module is unstable" #-}
3+ (foo, bar, baz)
64where
75
86import Blah
data/examples/module-header/warning-pragma-out.hs+5−1
@@ -1 +1,5 @@
1−module Test {-# WARNING "This module is very internal" #-} where
1+module Test
2+ {-# WARNING
3+ "This module is very internal"
4+ #-}
5+where
data/examples/other/argument-comment-out.hs+15−3
@@ -1,4 +1,16 @@
1−foo
2− :: Int -- ^ Documentation
3− -> Bool
1+foo ::
2+ -- | Documentation
3+ Int ->
4+ Bool
45foo _ = True
6+
7+foo ::
8+ Foo a =>
9+ -- | Foo
10+ Int ->
11+ Int
12+foo ::
13+ Foo a =>
14+ -- | Foo
15+ Int ->
16+ Int
data/examples/other/argument-comment.hs+9
@@ -2,3 +2,12 @@ foo
22 :: Int -- ^ Documentation
33 -> Bool
44foo _ = True
5+
6+foo :: Foo a
7+ => Int -- ^ Foo
8+ -> Int
9+
10+foo
11+ :: Foo a
12+ => Int -- ^ Foo
13+ -> Int
data/examples/other/ascii-out.hsnew file+9
@@ -0,0 +1,9 @@
1+{- -----------------------------------
2+ < What about ASCII art in comments? >
3+ -----------------------------------
4+ \ ^__^
5+ \ (oo)\_______
6+ (__)\ )\/\
7+ ||----w |
8+ || ||
9+-}
data/examples/other/ascii.hsnew file+9
@@ -0,0 +1,9 @@
1+{- -----------------------------------
2+ < What about ASCII art in comments? >
3+ -----------------------------------
4+ \ ^__^
5+ \ (oo)\_______
6+ (__)\ )\/\
7+ ||----w |
8+ || ||
9+-}
data/examples/other/comment-after-preceding-haddock-out.hsnew file+12
@@ -0,0 +1,12 @@
1+module Main where
2+
3+-- | A
4+
5+-- B
6+
7+type D = E
8+
9+-- | This is 'f'
10+
11+-- * Comment
12+f :: a -> b
data/examples/other/comment-after-preceding-haddock.hsnew file+12
@@ -0,0 +1,12 @@
1+module Main where
2+
3+-- | A
4+
5+-- B
6+
7+type D = E
8+
9+-- | This is 'f'
10+
11+-- * Comment
12+f :: a -> b
data/examples/other/comment-alignment-out.hsnew file+9
@@ -0,0 +1,9 @@
1+class Foo a where
2+ -- | Foo.
3+ foo ::
4+ Int ->
5+ -- | Something
6+ a
7+
8+ -- | Bar.
9+ bar :: a
data/examples/other/comment-alignment.hsnew file+11
@@ -0,0 +1,11 @@
1+class Foo a where
2+
3+ -- | Foo.
4+
5+ foo
6+ :: Int
7+ -> a -- ^ Something
8+
9+ -- | Bar.
10+
11+ bar :: a
data/examples/other/comment-before-hanging-out.hsnew file+5
@@ -0,0 +1,5 @@
1+x = Just
2+ -- comment
3+ do
4+ foo
5+ bar
data/examples/other/comment-before-hanging.hsnew file+5
@@ -0,0 +1,5 @@
1+x = Just
2+ -- comment
3+ do
4+ foo
5+ bar
data/examples/other/comment-following-preceding-gap-out.hsnew file+6
@@ -0,0 +1,6 @@
1+foo = bar
2+ where
3+ baz = return (quux) -- Foo
4+
5+ -- Bar
6+ meme = gege
data/examples/other/comment-following-preceding-gap.hsnew file+6
@@ -0,0 +1,6 @@
1+foo = bar
2+ where
3+ baz = return (quux) -- Foo
4+
5+ -- Bar
6+ meme = gege
data/examples/other/comment-glued-together-out.hsnew file+7
@@ -0,0 +1,7 @@
1+module Main (main) where
2+
3+-- | Foo.
4+
5+-- Bar
6+main :: IO ()
7+main = return ()
data/examples/other/comment-glued-together.hsnew file+6
@@ -0,0 +1,6 @@
1+module Main (main) where
2+
3+{- | Foo. -}
4+-- Bar
5+main :: IO ()
6+main = return ()
data/examples/other/comment-inside-construct-out.hsnew file+8
@@ -0,0 +1,8 @@
1+xs =
2+ [ outer list item,
3+ [ inner list first item,
4+ inner list second item
5+ -- inner list last item commented
6+ ],
7+ outer list item
8+ ]
data/examples/other/comment-inside-construct.hsnew file+9
@@ -0,0 +1,9 @@
1+xs =
2+ [ outer list item,
3+ [ inner list first item,
4+ inner list second item
5+ -- inner list last item commented
6+ ],
7+ outer list item
8+ ]
9+
data/examples/other/comment-multiline-after-out.hsnew file+7
@@ -0,0 +1,7 @@
1+foo ::
2+ -- | start index
3+ Int ->
4+ -- | length
5+ Int ->
6+ t a ->
7+ t a
data/examples/other/comment-multiline-after.hsnew file+1
@@ -0,0 +1 @@
1+foo :: Int {- ^ start index -} -> Int {- ^ length -} -> t a -> t a
data/examples/other/comment-style-transform-out.hsnew file+17
@@ -0,0 +1,17 @@
1+-- |
2+-- Module: Data.Aeson.TH
3+-- Copyright: (c) 2011-2016 Bryan O'Sullivan
4+-- (c) 2011 MailRank, Inc.
5+-- License: BSD3
6+-- Stability: experimental
7+-- Portability: portable
8+module Main where
9+
10+-- |
11+--
12+-- Here is a snippet:
13+--
14+-- @
15+-- x = y + 2
16+-- @
17+x = y + 2
data/examples/other/comment-style-transform.hsnew file+22
@@ -0,0 +1,22 @@
1+{-|
2+Module: Data.Aeson.TH
3+Copyright: (c) 2011-2016 Bryan O'Sullivan
4+ (c) 2011 MailRank, Inc.
5+License: BSD3
6+Stability: experimental
7+Portability: portable
8+-}
9+
10+module Main where
11+
12+{- |
13+
14+Here is a snippet:
15+
16+@
17+x = y + 2
18+@
19+
20+-}
21+
22+x = y + 2
data/examples/other/comment-trailing-space-out.hsnew file+9
@@ -0,0 +1,9 @@
1+data T
2+ = {-
3+
4+ some multi-line comment
5+
6+ with empty lines
7+
8+ -}
9+ A
data/examples/other/comment-trailing-space.hsnew file+9
@@ -0,0 +1,9 @@
1+data T
2+ = {-
3+
4+ some multi-line comment
5+
6+ with empty lines
7+
8+ -}
9+ A
data/examples/other/comment-two-blocks-out.hsnew file+8
@@ -0,0 +1,8 @@
1+newNames :: [(String, String)]
2+newNames =
3+ let (*) = flip (,)
4+ in [ "Control" * "Monad"
5+ -- Foo
6+
7+ -- Bar
8+ ]
data/examples/other/comment-two-blocks.hsnew file+9
@@ -0,0 +1,9 @@
1+newNames :: [(String, String)]
2+newNames = let (*) = flip (,) in
3+ ["Control" * "Monad"
4+
5+ -- Foo
6+
7+ -- Bar
8+
9+ ]
data/examples/other/consequetive-pipe-comments-out.hsnew file+7
@@ -0,0 +1,7 @@
1+module Main where
2+
3+-- | Foo.
4+
5+-- | Bar.
6+bar :: Int
7+bar = 5
data/examples/other/consequetive-pipe-comments.hsnew file+8
@@ -0,0 +1,8 @@
1+module Main where
2+
3+-- | Foo.
4+
5+-- | Bar.
6+
7+bar :: Int
8+bar = 5
data/examples/other/cpp/continuation-out.hsnew file+8
@@ -0,0 +1,8 @@
1+foo :: Int
2+foo = 5
3+
4+#define message_for(a, b) \
5+ printf(#a " and " #b ": We love you!\n")
6+
7+bar :: Int
8+bar = 6
data/examples/other/cpp/continuation.hsnew file+8
@@ -0,0 +1,8 @@
1+foo :: Int
2+foo = 5
3+
4+#define message_for(a, b) \
5+ printf(#a " and " #b ": We love you!\n")
6+
7+bar :: Int
8+bar = 6
data/examples/other/cpp/lonely-hash-out.hsnew file+14
@@ -0,0 +1,14 @@
1+module Main (main) where
2+
3+import Data.Void
4+import Test.Hspec
5+import Test.Hspec.Megaparsec
6+import Text.Megaparsec
7+import Text.Megaparsec.Char
8+
9+# if !MIN_VERSION_base(4,13,0)
10+import Data.Semigroup ((<>))
11+# endif
12+
13+main :: IO ()
14+main = return ()
data/examples/other/cpp/lonely-hash.hsnew file+14
@@ -0,0 +1,14 @@
1+module Main (main) where
2+
3+import Data.Void
4+import Test.Hspec
5+import Test.Hspec.Megaparsec
6+import Text.Megaparsec
7+import Text.Megaparsec.Char
8+
9+# if !MIN_VERSION_base(4,13,0)
10+import Data.Semigroup ((<>))
11+# endif
12+
13+main :: IO ()
14+main = return ()
data/examples/other/cpp/separation-0a-out.hsnew file+7
@@ -0,0 +1,7 @@
1+instance Stream s => Monad (ParsecT e s m) where
2+ return = pure
3+ (>>=) = pBind
4+
5+#if !(MIN_VERSION_base(4,13,0))
6+ fail = Fail.fail
7+#endif
data/examples/other/cpp/separation-0a.hsnew file+6
@@ -0,0 +1,6 @@
1+instance Stream s => Monad (ParsecT e s m) where
2+ return = pure
3+ (>>=) = pBind
4+#if !(MIN_VERSION_base(4,13,0))
5+ fail = Fail.fail
6+#endif
data/examples/other/cpp/separation-0b-out.hsnew file+10
@@ -0,0 +1,10 @@
1+instance Stream s => Monad (ParsecT e s m) where
2+ return = pure
3+ (>>=) = pBind
4+
5+#if !(MIN_VERSION_base(4,13,0))
6+ fail = Fail.fail
7+#endif
8+
9+foo :: Int
10+foo = undefined
data/examples/other/cpp/separation-0b.hsnew file+9
@@ -0,0 +1,9 @@
1+instance Stream s => Monad (ParsecT e s m) where
2+ return = pure
3+ (>>=) = pBind
4+#if !(MIN_VERSION_base(4,13,0))
5+ fail = Fail.fail
6+#endif
7+
8+foo :: Int
9+foo = undefined
data/examples/other/cpp/separation-1a-out.hsnew file+12
@@ -0,0 +1,12 @@
1+decompressingPipe ::
2+ (PrimMonad m, MonadThrow m, MonadResource m) =>
3+ CompressionMethod ->
4+ ConduitT ByteString ByteString m ()
5+decompressingPipe Store = C.awaitForever C.yield
6+decompressingPipe Deflate = Z.decompress $ Z.WindowBits (-15)
7+
8+#ifdef ENABLE_BZIP2
9+decompressingPipe BZip2 = BZ.bunzip2
10+#else
11+decompressingPipe BZip2 = throwM BZip2Unsupported
12+#endif
data/examples/other/cpp/separation-1a.hsnew file+11
@@ -0,0 +1,11 @@
1+decompressingPipe
2+ :: (PrimMonad m, MonadThrow m, MonadResource m)
3+ => CompressionMethod
4+ -> ConduitT ByteString ByteString m ()
5+decompressingPipe Store = C.awaitForever C.yield
6+decompressingPipe Deflate = Z.decompress $ Z.WindowBits (-15)
7+#ifdef ENABLE_BZIP2
8+decompressingPipe BZip2 = BZ.bunzip2
9+#else
10+decompressingPipe BZip2 = throwM BZip2Unsupported
11+#endif
data/examples/other/cpp/separation-1b-out.hsnew file+15
@@ -0,0 +1,15 @@
1+decompressingPipe ::
2+ (PrimMonad m, MonadThrow m, MonadResource m) =>
3+ CompressionMethod ->
4+ ConduitT ByteString ByteString m ()
5+decompressingPipe Store = C.awaitForever C.yield
6+decompressingPipe Deflate = Z.decompress $ Z.WindowBits (-15)
7+
8+#ifdef ENABLE_BZIP2
9+decompressingPipe BZip2 = BZ.bunzip2
10+#else
11+decompressingPipe BZip2 = throwM BZip2Unsupported
12+#endif
13+
14+foo :: Int
15+foo = undefined
data/examples/other/cpp/separation-1b.hsnew file+14
@@ -0,0 +1,14 @@
1+decompressingPipe
2+ :: (PrimMonad m, MonadThrow m, MonadResource m)
3+ => CompressionMethod
4+ -> ConduitT ByteString ByteString m ()
5+decompressingPipe Store = C.awaitForever C.yield
6+decompressingPipe Deflate = Z.decompress $ Z.WindowBits (-15)
7+#ifdef ENABLE_BZIP2
8+decompressingPipe BZip2 = BZ.bunzip2
9+#else
10+decompressingPipe BZip2 = throwM BZip2Unsupported
11+#endif
12+
13+foo :: Int
14+foo = undefined
data/examples/other/cpp/separation-2a-out.hsnew file+9
@@ -0,0 +1,9 @@
1+ffff, ffffffff :: Natural
2+
3+#ifdef HASKELL_ZIP_DEV_MODE
4+ffff = 200
5+ffffffff = 5000
6+#else
7+ffff = 0xffff
8+ffffffff = 0xffffffff
9+#endif
data/examples/other/cpp/separation-2a.hsnew file+8
@@ -0,0 +1,8 @@
1+ffff, ffffffff :: Natural
2+#ifdef HASKELL_ZIP_DEV_MODE
3+ffff = 200
4+ffffffff = 5000
5+#else
6+ffff = 0xffff
7+ffffffff = 0xffffffff
8+#endif
data/examples/other/cpp/separation-2b-out.hsnew file+11
@@ -0,0 +1,11 @@
1+ffff, ffffffff :: Natural
2+#ifdef HASKELL_ZIP_DEV_MODE
3+ffff = 200
4+ffffffff = 5000
5+#else
6+ffff = 0xffff
7+ffffffff = 0xffffffff
8+#endif
9+
10+foo :: Int
11+foo = undefined
data/examples/other/cpp/separation-2b.hsnew file+11
@@ -0,0 +1,11 @@
1+ffff, ffffffff :: Natural
2+#ifdef HASKELL_ZIP_DEV_MODE
3+ffff = 200
4+ffffffff = 5000
5+#else
6+ffff = 0xffff
7+ffffffff = 0xffffffff
8+#endif
9+
10+foo :: Int
11+foo = undefined
data/examples/other/cpp/shifted-out.hsnew file+21
@@ -0,0 +1,21 @@
1+sinkData h compression = do
2+ (uncompressedSize, crc32, compressedSize) <-
3+ case compression of
4+ Store ->
5+ withCompression
6+ dataSink
7+ Deflate ->
8+ withCompression $
9+ Z.compress 9 (Z.WindowBits (-15)) .| dataSink
10+#ifdef ENABLE_BZIP2
11+ BZip2 -> withCompression $
12+ BZ.bzip2 .| dataSink
13+#else
14+ BZip2 -> throwM BZip2Unsupported
15+#endif
16+ return
17+ DataDescriptor
18+ { ddCRC32 = fromIntegral crc32,
19+ ddCompressedSize = compressedSize,
20+ ddUncompressedSize = uncompressedSize
21+ }
data/examples/other/cpp/shifted.hsnew file+17
@@ -0,0 +1,17 @@
1+sinkData h compression = do
2+ (uncompressedSize, crc32, compressedSize) <-
3+ case compression of
4+ Store -> withCompression
5+ dataSink
6+ Deflate -> withCompression $
7+ Z.compress 9 (Z.WindowBits (-15)) .| dataSink
8+#ifdef ENABLE_BZIP2
9+ BZip2 -> withCompression $
10+ BZ.bzip2 .| dataSink
11+#else
12+ BZip2 -> throwM BZip2Unsupported
13+#endif
14+ return DataDescriptor
15+ { ddCRC32 = fromIntegral crc32
16+ , ddCompressedSize = compressedSize
17+ , ddUncompressedSize = uncompressedSize }
data/examples/other/cpp/simple-import-out.hsnew file+14
@@ -0,0 +1,14 @@
1+module Main (main) where
2+
3+import Data.Void
4+import Test.Hspec
5+import Test.Hspec.Megaparsec
6+import Text.Megaparsec
7+import Text.Megaparsec.Char
8+
9+#if !MIN_VERSION_base(4,13,0)
10+import Data.Semigroup ((<>))
11+#endif
12+
13+main :: IO ()
14+main = return ()
data/examples/other/cpp/simple-import.hsnew file+14
@@ -0,0 +1,14 @@
1+module Main (main) where
2+
3+import Data.Void
4+import Test.Hspec
5+import Test.Hspec.Megaparsec
6+import Text.Megaparsec
7+import Text.Megaparsec.Char
8+
9+#if !MIN_VERSION_base(4,13,0)
10+import Data.Semigroup ((<>))
11+#endif
12+
13+main :: IO ()
14+main = return ()
data/examples/other/disabling/indented-fragment-out.hsnew file+7
@@ -0,0 +1,7 @@
1+foo =
2+ {- ORMOLU_DISABLE -}
3+ testCase "Foo" testFoo :
4+ testCase "Bar" testBar :
5+ testCase "Baz" testBaz :
6+ {- ORMOLU_ENABLE -}
7+ []
data/examples/other/disabling/indented-fragment.hsnew file+7
@@ -0,0 +1,7 @@
1+foo =
2+ {- ORMOLU_DISABLE -}
3+ testCase "Foo" testFoo :
4+ testCase "Bar" testBar :
5+ testCase "Baz" testBaz :
6+ {- ORMOLU_ENABLE -}
7+ []
data/examples/other/disabling/single-definition-out.hsnew file+10
@@ -0,0 +1,10 @@
1+module Foo (foo, bar) where
2+
3+{- ORMOLU_DISABLE -}
4+foo :: Int -> Int
5+foo = (+5)
6+{- ORMOLU_ENABLE -}
7+
8+bar :: Bool -> Bool
9+bar True = True
10+bar False = True
data/examples/other/disabling/single-definition.hsnew file+10
@@ -0,0 +1,10 @@
1+module Foo (foo,bar) where
2+
3+{- ORMOLU_DISABLE -}
4+foo :: Int -> Int
5+foo = (+5)
6+{- ORMOLU_ENABLE -}
7+
8+bar :: Bool -> Bool
9+bar True = True
10+bar False = True
data/examples/other/disabling/whole-file-out.hsnew file+10
@@ -0,0 +1,10 @@
1+{- ORMOLU_DISABLE -}
2+
3+module Foo (foo,bar) where
4+
5+foo :: Int -> Int
6+foo = (+5)
7+
8+bar :: Bool -> Bool
9+bar True = True
10+bar False = True
data/examples/other/disabling/whole-file.hsnew file+10
@@ -0,0 +1,10 @@
1+{- ORMOLU_DISABLE -}
2+
3+module Foo (foo,bar) where
4+
5+foo :: Int -> Int
6+foo = (+5)
7+
8+bar :: Bool -> Bool
9+bar True = True
10+bar False = True
data/examples/other/empty-forall-out.hsnew file+18
@@ -0,0 +1,18 @@
1+-- Empty foralls are handled correctly in different situations.
2+
3+data D = forall. D Int
4+
5+data G where
6+ G :: forall. Int -> G
7+
8+f :: forall. a -> a
9+f x = x
10+
11+type family T x where
12+ forall. T x = x
13+
14+{-# RULES
15+"r"
16+ r a =
17+ ()
18+ #-}
data/examples/other/empty-forall.hsnew file+17
@@ -0,0 +1,17 @@
1+-- Empty foralls are handled correctly in different situations.
2+
3+data D = forall. D Int
4+
5+data G where
6+ G :: forall. Int -> G
7+
8+f :: forall. a -> a
9+f x = x
10+
11+type family T x where
12+ forall. T x = x
13+
14+{-# RULES
15+ "r"
16+ forall. r a = ()
17+#-}
data/examples/other/empty-haddock-out.hsnew file+5
@@ -0,0 +1,5 @@
1+module Main where
2+
3+-- |
4+foo :: Int
5+foo = 5
data/examples/other/empty-haddock.hsnew file+6
@@ -0,0 +1,6 @@
1+module Main where
2+
3+-- |
4+
5+foo :: Int
6+foo = 5
data/examples/other/following-comment-last-0-out.hsnew file+5
@@ -0,0 +1,5 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+-- ^ ...with two docstrings.
data/examples/other/following-comment-last-0.hsnew file+5
@@ -0,0 +1,5 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+-- ^ ...with two docstrings.
data/examples/other/following-comment-last-1-out.hsnew file+8
@@ -0,0 +1,8 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+ deriving (Show)
6+-- ^ ...with two docstrings.
7+
8+-- more
data/examples/other/following-comment-last-1.hsnew file+8
@@ -0,0 +1,8 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+ deriving (Show)
6+-- ^ ...with two docstrings.
7+
8+-- more
data/examples/other/following-comment-last-2-out.hsnew file+10
@@ -0,0 +1,10 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+ deriving (Show)
6+-- ^ ...with two docstrings.
7+
8+-- more
9+
10+data B
data/examples/other/following-comment-last-2.hsnew file+10
@@ -0,0 +1,10 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+ deriving (Show)
6+-- ^ ...with two docstrings.
7+
8+-- more
9+
10+data B
data/examples/other/following-comment-last-3-out.hsnew file+6
@@ -0,0 +1,6 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+-- ^ ...with two docstrings.
6+-- even on second line
data/examples/other/following-comment-last-3.hsnew file+6
@@ -0,0 +1,6 @@
1+module Main where
2+
3+-- | Another datatype...
4+data D'
5+-- ^ ...with two docstrings.
6+-- even on second line
data/examples/other/haddock-sections-out.hsnew file+7
@@ -0,0 +1,7 @@
1+-- $weird #anchor#
2+--
3+-- Section 1
4+
5+-- $normal
6+--
7+-- Section 2
data/examples/other/haddock-sections.hsnew file+7
@@ -0,0 +1,7 @@
1+-- $weird #anchor#
2+--
3+-- Section 1
4+
5+-- $normal
6+--
7+-- Section 2
data/examples/other/inline-comment-0-out.hsnew file+3
@@ -0,0 +1,3 @@
1+x = ({-a-} b, c)
2+
3+y = ({-a-} b)
data/examples/other/inline-comment-0.hsnew file+3
@@ -0,0 +1,3 @@
1+x = ({-a-}b, c)
2+
3+y = ({-a-}b)
data/examples/other/inline-comment-1-out.hsnew file+12
@@ -0,0 +1,12 @@
1+showPs env ((n, _, Let _ t v) : bs) =
2+ " " ++ show n ++ " : "
3+ ++ showEnv env ({- normalise ctxt env -} t)
4+ ++ " = "
5+ ++ showEnv env ({- normalise ctxt env -} v)
6+ ++ "\n"
7+ ++ showPs env bs
8+showPs env ((n, _, b) : bs) =
9+ " " ++ show n ++ " : "
10+ ++ showEnv env ({- normalise ctxt env -} (binderTy b))
11+ ++ "\n"
12+ ++ showPs env bs
data/examples/other/inline-comment-1.hsnew file+9
@@ -0,0 +1,9 @@
1+showPs env ((n, _, Let _ t v):bs)
2+ = " " ++ show n ++ " : " ++
3+ showEnv env ({- normalise ctxt env -} t) ++ " = " ++
4+ showEnv env ({- normalise ctxt env -} v) ++
5+ "\n" ++ showPs env bs
6+showPs env ((n, _, b):bs)
7+ = " " ++ show n ++ " : " ++
8+ showEnv env ({- normalise ctxt env -} (binderTy b)) ++
9+ "\n" ++ showPs env bs
data/examples/other/merging-comments-out.hsnew file+12
@@ -0,0 +1,12 @@
1+foo xs = baz
2+ where
3+ bar =
4+ catMaybes
5+ [ lookup langKey gets, -- 1
6+ lookup langKey cookies, -- 2
7+ lookupText langKey session -- 3
8+ ]
9+ ++ xs -- 4
10+
11+ -- Blah
12+ baz = addTwoLetters (id, Set.empty) bar
data/examples/other/merging-comments.hsnew file+9
@@ -0,0 +1,9 @@
1+foo xs = baz
2+ where
3+ bar = catMaybes [ lookup langKey gets -- 1
4+ , lookup langKey cookies -- 2
5+ , lookupText langKey session -- 3
6+ ] ++ xs -- 4
7+
8+ -- Blah
9+ baz = addTwoLetters (id, Set.empty) bar
data/examples/other/multiline-comments-reindent-out.hs+3−3
@@ -1,6 +1,6 @@
11{-
2−And so here we have a
3−multiline comment.
2+ And so here we have a
3+ multiline comment.
44
5−Indeed.
5+ Indeed.
66-}
data/examples/other/multiline-forall-out.hsnew file+58
@@ -0,0 +1,58 @@
1+{-# LANGUAGE GADTs #-}
2+{-# LANGUAGE PolyKinds #-}
3+{-# LANGUAGE RankNTypes #-}
4+{-# LANGUAGE TypeFamilies #-}
5+
6+-- Multiline foralls are consistent across all declarations
7+
8+data D
9+ = forall
10+ ( f ::
11+ * -> * -> *
12+ )
13+ (x :: *)
14+ (y :: *).
15+ D (f x y)
16+
17+data G where
18+ G ::
19+ forall
20+ ( f ::
21+ * -> * -> *
22+ )
23+ (x :: *)
24+ (y :: *).
25+ f x y ->
26+ G
27+
28+f ::
29+ forall
30+ ( f ::
31+ * -> * -> *
32+ )
33+ (x :: *)
34+ (y :: *).
35+ f x y ->
36+ ()
37+f = const ()
38+
39+type family T f x y where
40+ forall
41+ ( f ::
42+ * -> * -> *
43+ )
44+ (x :: *)
45+ (y :: *).
46+ T f x y =
47+ f x y
48+
49+{-# RULES
50+"r" forall
51+ ( f ::
52+ * -> * -> *
53+ )
54+ (x :: *)
55+ (y :: *).
56+ r (a :: f x y) =
57+ ()
58+ #-}
data/examples/other/multiline-forall.hsnew file+46
@@ -0,0 +1,46 @@
1+{-# LANGUAGE RankNTypes, PolyKinds, GADTs, TypeFamilies #-}
2+
3+-- Multiline foralls are consistent across all declarations
4+
5+data D =
6+ forall
7+ (f ::
8+ * -> * -> *)
9+ (x :: *)
10+ (y :: *)
11+ . D (f x y)
12+
13+data G where
14+ G :: forall
15+ (f ::
16+ * -> * -> *)
17+ (x :: *)
18+ (y :: *)
19+ . f x y -> G
20+
21+f :: forall
22+ (f ::
23+ * -> * -> *)
24+ (x :: *)
25+ (y :: *)
26+ . f x y -> ()
27+f = const ()
28+
29+type family T f x y where
30+ forall
31+ (f ::
32+ * -> * -> *)
33+ (x :: *)
34+ (y :: *)
35+ . T f x y = f x y
36+
37+{-# RULES
38+ "r"
39+ forall
40+ (f ::
41+ * -> * -> *)
42+ (x :: *)
43+ (y :: *)
44+ . r (a :: f x y) =
45+ ()
46+ #-}
data/examples/other/multiple-blank-line-comment-out.hsnew file+9
@@ -0,0 +1,9 @@
1+module A where
2+
3+a =
4+ b
5+ [ f
6+ {-,
7+
8+ -}
9+ ]
data/examples/other/multiple-blank-line-comment.hsnew file+10
@@ -0,0 +1,10 @@
1+module A where
2+
3+a =
4+ b
5+ [ f
6+ {-,
7+
8+
9+ -}
10+ ]
data/examples/other/overly-indented-out.hsnew file+11
@@ -0,0 +1,11 @@
1+tagCloudField ::
2+ -- | Destination key
3+ String ->
4+ -- | Smallest font size, in percent
5+ Double ->
6+ -- | Biggest font size, in percent
7+ Double ->
8+ -- | Input tags
9+ Tags ->
10+ -- | Context
11+ Context a
data/examples/other/overly-indented.hsnew file+10
@@ -0,0 +1,10 @@
1+tagCloudField :: String
2+ -- ^ Destination key
3+ -> Double
4+ -- ^ Smallest font size, in percent
5+ -> Double
6+ -- ^ Biggest font size, in percent
7+ -> Tags
8+ -- ^ Input tags
9+ -> Context a
10+ -- ^ Context
data/examples/other/pragma-comments-after-out.hsnew file+4
@@ -0,0 +1,4 @@
1+{-# LANGUAGE AllowAmbiguousTypes #-}
2+{-# LANGUAGE ConstraintKinds #-}
3+-- TODO: Fix and delete this pragma
4+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
data/examples/other/pragma-comments-after.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} -- TODO: Fix and delete this pragma
2+{-# LANGUAGE AllowAmbiguousTypes #-}
3+{-# LANGUAGE ConstraintKinds #-}
data/examples/other/pragma-comments-out.hsnew file+8
@@ -0,0 +1,8 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+-- TODO This extension is probably too dangerous, remove it.
3+{-# LANGUAGE RecordWildCards #-}
4+-- Avoid warning produced by TH.
5+{-# OPTIONS_GHC -fno-warn-overlapping-patterns #-}
6+
7+-- | Header comment.
8+module Foo () where
data/examples/other/pragma-comments.hsnew file+11
@@ -0,0 +1,11 @@
1+-- | Header comment.
2+
3+{-# LANGUAGE OverloadedStrings #-}
4+
5+-- Avoid warning produced by TH.
6+{-# OPTIONS_GHC -fno-warn-overlapping-patterns #-}
7+
8+-- TODO This extension is probably too dangerous, remove it.
9+{-# LANGUAGE RecordWildCards #-}
10+
11+module Foo () where
data/examples/other/pragma-no-header-out.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE LambdaCase #-}
3+{-# LANGUAGE ViewPatterns #-}
data/examples/other/pragma-no-header.hsnew file+3
@@ -0,0 +1,3 @@
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGuagE ViewPatterns #-}
3+{-# language DataKinds, LambdaCase #-}
data/examples/other/pragma-out.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE AllowAmbiguousTypes #-}
2+{-# LANGUAGE DataKinds #-}
3+{-# LANGUAGE IncoherentInstances #-}
4+{-# LANGUAGE LambdaCase #-}
5+{-# LANGUAGE OverloadedStrings #-}
6+{-# LANGUAGE ViewPatterns #-}
7+{-# OPTIONS_GHC -O2 -H 300 #-}
8+{-# OPTIONS_GHC -Wall -Werror #-}
9+{-# OPTIONS_HADDOCK prune, show-extensions #-}
10+
11+-- | Header comment.
12+module Foo () where
data/examples/other/pragma-sorting-out.hsnew file+11
@@ -0,0 +1,11 @@
1+{-# LANGUAGE NondecreasingIndentation #-}
2+{-# LANGUAGE ScopedTypeVariables #-}
3+{-# LANGUAGE TypeFamilies #-}
4+-- This gap is necessary for stylish Haskell not to re-arrange
5+-- NoMonoLocalBinds before TypeFamilies
6+{-# LANGUAGE NoMonoLocalBinds #-}
7+
8+module Foo
9+ ( bar,
10+ )
11+where
data/examples/other/pragma-sorting.hsnew file+10
@@ -0,0 +1,10 @@
1+{-# LANGUAGE ScopedTypeVariables #-}
2+{-# LANGUAGE TypeFamilies #-}
3+{-# LANGUAGE NondecreasingIndentation #-}
4+-- This gap is necessary for stylish Haskell not to re-arrange
5+-- NoMonoLocalBinds before TypeFamilies
6+{-# LANGUAGE NoMonoLocalBinds #-}
7+
8+module Foo (
9+ bar
10+ ) where
data/examples/other/pragma.hsnew file+13
@@ -0,0 +1,13 @@
1+-- | Header comment.
2+
3+{-# LANGUAGE LambdaCase #-}
4+{-#LANGuagE ViewPatterns #-}
5+{-# LANGUAGE OverloadedStrings#-}
6+{-# OPTIONS_GHC -Wall -Werror #-}
7+{-# language DataKinds, LambdaCase #-}
8+{-# OPTIONS_HADDOCK prune, show-extensions #-}
9+{-# OPTIONS_GHC -O2 -H 300 #-}
10+{-# language IncoherentInstances
11+ , AllowAmbiguousTypes #-}
12+
13+module Foo () where
data/examples/other/trailing-whitespace-out.hsnew file+7
@@ -0,0 +1,7 @@
1+-- Here is a comment with trailing whitespace.
2+foo = 5
3+
4+{- Block comment with trailing whitespace.
5+ Bo.
6+ -}
7+bar = 6
data/examples/other/trailing-whitespace.hsnew file+7
@@ -0,0 +1,7 @@
1+-- Here is a comment with trailing whitespace.
2+foo = 5
3+
4+{- Block comment with trailing whitespace.
5+ Bo.
6+ -}
7+bar = 6
data/printer/list0-multi.hsdeleted−4
@@ -1,4 +0,0 @@
1−[ foo
2−, bar
3−, baz
4−]
data/printer/list0-single.hsdeleted−1
@@ -1 +0,0 @@
1−[foo, bar, baz]
data/printer/list1-multi.hsdeleted−8
@@ -1,8 +0,0 @@
1−[ foo
2−, bar
3−, foo
4− :: ( Int
5− -> Int
6− )
7− -> Bool
8−]
data/printer/list1-single.hsdeleted−1
@@ -1 +0,0 @@
1−[foo, bar, foo :: (Int -> Int) -> Bool]
data/printer/mhdr-multi.hsdeleted−7
@@ -1,7 +0,0 @@
1−module MyModule
2− ( R
3− , runR
4− , txt
5− , blah
6− )
7−where
data/printer/mhdr-single.hsdeleted−3
@@ -1,3 +0,0 @@
1−module MyModule
2− (R, runR, txt, blah)
3−where
data/printer/ssig-multi.hsdeleted−5
@@ -1,5 +0,0 @@
1−foo
2− :: ( Int
3− -> Int
4− )
5− -> Bool
data/printer/ssig-single.hsdeleted−1
@@ -1 +0,0 @@
1−foo :: (Int -> Int) -> Bool
default.nix+163−12
@@ -1,18 +1,169 @@
1+{ pkgs ? (import ./nix/nixpkgs { inherit system; })
2+, system ? builtins.currentSystem
3+, ormoluCompiler ? "ghc884" # the shell doesn't work with ghc8101 yet
4+}:
5+
16let
2− pkgs = import ./nix/nixpkgs;
3− gitignoreSource = import ./nix/gitignore { inherit (pkgs) lib; };
4− compiler = "ghc864";
5− source = gitignoreSource ./.;
6− haskellPackages = pkgs.haskell.packages.${compiler}.override {
7− overrides = (self: super:
8− super // {
9− "ormolu" = super.callCabal2nix "ormolu" source { };
10− });
7+ source = pkgs.lib.sourceByRegex ./. [
8+ "^.*\.md$"
9+ "^app.*$"
10+ "^data.*$"
11+ "^ormolu\.cabal$"
12+ "^src.*$"
13+ "^tests.*$"
14+ ];
15+ haskellPackages = pkgs.haskell.packages.${ormoluCompiler}.override {
16+ overrides = ormoluOverlay;
1117 };
18+ ormoluOverlay = self: super: {
19+ "ormolu" = super.callCabal2nixWithOptions "ormolu" source "-fdev" { };
20+ };
21+ ormolize = import ./nix/ormolize {
22+ inherit pkgs;
23+ inherit haskellPackages;
24+ };
25+ expectedFailures = [
26+ "Agda"
27+ "aws"
28+ "distributed-process"
29+ "esqueleto"
30+ "fay"
31+ "hlint"
32+ "idris"
33+ "intero"
34+ "leksah"
35+ "pandoc"
36+ "pipes"
37+ "postgrest"
38+ "purescript"
39+ "tensorflow"
40+ ] ++ (if ormoluCompiler == "ghc8101" then [] else ["lens"]);
41+ ormolizedPackages = doCheck:
42+ pkgs.lib.mapAttrs (name: p: ormolize {
43+ package = p;
44+ inherit doCheck;
45+ expectedFailures =
46+ if pkgs.lib.lists.any (x: x == name) expectedFailures
47+ then ./expected-failures + "/${name}.txt"
48+ else null;
49+ }) haskellPackages;
1250in {
1351 ormolu = haskellPackages.ormolu;
14− ormolu-shell = haskellPackages.shellFor {
15− packages = ps: [ ps.ormolu ];
16− buildInputs = [ pkgs.cabal-install ];
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+ };
72+ };
73+ inherit ormoluOverlay ormoluCompiler;
74+ hackage = ormolizedPackages false;
75+ hackageTests = with pkgs.lib; pkgs.recurseIntoAttrs (
76+ let ps = [
77+ "Agda"
78+ "QuickCheck"
79+ "ShellCheck"
80+ "aeson"
81+ "attoparsec"
82+ "aws"
83+ "brick"
84+ "capability"
85+ "cassava"
86+ "conduit"
87+ "cryptonite"
88+ "diagrams-core"
89+ "distributed-process"
90+ "esqueleto"
91+ "fay"
92+ "hakyll"
93+ "haxl"
94+ "hedgehog"
95+ "hledger"
96+ "hlint"
97+ "http-client"
98+ "idris"
99+ "intero"
100+ "leksah"
101+ "lens"
102+ "megaparsec"
103+ "optics"
104+ "ormolu"
105+ "pandoc"
106+ "parsec3"
107+ "pipes"
108+ "postgrest"
109+ "purescript"
110+ "servant"
111+ "servant-server"
112+ "stack"
113+ "tensorflow"
114+ "text_1_2_4_0"
115+ "tls"
116+ "yesod-core"
117+ ];
118+ in listToAttrs (map (p: nameValuePair p (ormolizedPackages true).${p}) ps)
119+ );
120+ regionTests = pkgs.stdenv.mkDerivation {
121+ name = "ormolu-region-tests";
122+ src = ./region-tests;
123+ buildInputs = [
124+ haskellPackages.ormolu
125+ pkgs.diffutils
126+ ];
127+ doCheck = true;
128+ buildPhase = ''
129+ cp src.hs result-all-implicit.hs
130+ ormolu --check-idempotence --mode inplace result-all-implicit.hs
131+ cp src.hs result-all-explicit.hs
132+ ormolu --check-idempotence --mode inplace --start-line 1 --end-line 18 result-all-explicit.hs
133+ cp src.hs result-only-start.hs
134+ ormolu --check-idempotence --mode inplace --start-line 1 result-only-start.hs
135+ cp src.hs result-only-end.hs
136+ ormolu --check-idempotence --mode inplace --end-line 18 result-only-end.hs
137+ cp src.hs result-6-7.hs
138+ ormolu --check-idempotence --mode inplace --start-line 6 --end-line 7 result-6-7.hs
139+ cp src.hs result-6-8.hs
140+ ormolu --check-idempotence --mode inplace --start-line 6 --end-line 8 result-6-8.hs
141+ cp src.hs result-9-12.hs
142+ ormolu --check-idempotence --mode inplace --start-line 9 --end-line 12 result-9-12.hs
143+ cp src.hs result-17-18.hs
144+ ormolu --check-idempotence --mode inplace --start-line 17 --end-line 18 result-17-18.hs
145+ '';
146+ checkPhase = ''
147+ echo result-all-implicit.hs
148+ diff --color=always expected-result-all.hs result-all-implicit.hs
149+ echo result-all-explicit.hs
150+ diff --color=always expected-result-all.hs result-all-explicit.hs
151+ echo result-only-start.hs
152+ diff --color=always expected-result-all.hs result-only-start.hs
153+ echo result-only-end.hs
154+ diff --color=always expected-result-all.hs result-only-end.hs
155+ echo result-6-7.hs
156+ diff --color=always expected-result-6-7.hs result-6-7.hs
157+ echo result-6-8.hs
158+ diff --color=always expected-result-6-8.hs result-6-8.hs
159+ echo result-9-12.hs
160+ diff --color=always expected-result-9-12.hs result-9-12.hs
161+ echo result-17-18.hs
162+ diff --color=always expected-result-17-18.hs result-17-18.hs
163+ '';
164+ installPhase = ''
165+ mkdir "$out"
166+ find . -name '*.hs' -exec cp --parents {} $out \;
167+ '';
17168 };
18169}
expected-failures/Agda.txtnew file+11
@@ -0,0 +1,11 @@
1+Formatting is not idempotent:
2+ dist/build/Agda/Syntax/Parser/Lexer.hs<rendered>:1602:17
3+ before: " = (check_ac"
4+ after: " =\n "
5+Please, consider reporting the bug.
6+
7+Formatting is not idempotent:
8+ src/full/Agda/Syntax/Translation/InternalToAbstract.hs<rendered>:769:4
9+ before: " nes\n\n "
10+ after: " nes\n\n -- Andreas"
11+Please, consider reporting the bug.
expected-failures/aws.txtnew file+9
@@ -0,0 +1,9 @@
1+The GHC parser (in Haddock mode) failed:
2+ Examples/PutBucketNearLine.hs:5:1-6
3+ parse error on input `import'
4+
5+The GHC parser (in Haddock mode) failed:
6+ Examples/Sqs.hs:(88,3)-(90,4)
7+ parse error on input `{- | Let's make sure the queue was actually deleted and that the same number of queues exist at when
8+ | the program ends as when it started.
9+ -}'
expected-failures/distributed-process.txtnew file+7
@@ -0,0 +1,7 @@
1+The GHC parser (in Haddock mode) failed:
2+ benchmarks/Channels.hs:2:1-6
3+ parse error on input `import'
4+
5+The GHC parser (in Haddock mode) failed:
6+ benchmarks/Spawns.hs:5:1-6
7+ parse error on input `import'
expected-failures/esqueleto.txtnew file+7
@@ -0,0 +1,7 @@
1+The GHC parser (in Haddock mode) failed:
2+ src/Database/Esqueleto/Internal/Internal.hs:379:1
3+ lexical error in string/character literal at character 's'
4+
5+The GHC parser (in Haddock mode) failed:
6+ test/PostgreSQL/Test.hs:562:9-41
7+ parse error on input `-- | Check the result is not null'
expected-failures/fay.txtnew file+18
@@ -0,0 +1,18 @@
1+The GHC parser (in Haddock mode) failed:
2+ examples/Separated.hs:12:1-6
3+ parse error on input `module'
4+
5+The GHC parser (in Haddock mode) failed:
6+ examples/calc.hs:(4,1)-(6,2)
7+ parse error on input `-- $ fay -p --html-wrapper --html-js-lib jquery.min.js examples/calc.hs
8+-- You also need to download jquery.min.js.
9+--'
10+
11+The GHC parser (in Haddock mode) failed:
12+ examples/canvaswater.hs:(6,1)-(7,17)
13+ parse error on input `-- | A demonstration of Fay using the canvas element to display a
14+-- simple effect.'
15+
16+The GHC parser (in Haddock mode) failed:
17+ examples/data.hs:9:1-6
18+ parse error on input `module'
expected-failures/hlint.txtnew file+11
@@ -0,0 +1,11 @@
1+Formatting is not idempotent:
2+ src/Extension.hs<rendered>:19:22
3+ before: "DoRec , -} Recursive"
4+ after: "DoRec , -}\n "
5+Please, consider reporting the bug.
6+
7+Formatting is not idempotent:
8+ src/Hint/Bracket.hs<rendered>:249:50
9+ before: "\" x y [r]) {ideaSpan"
10+ after: "\" x y [r])\n "
11+Please, consider reporting the bug.
expected-failures/idris.txtnew file+7
@@ -0,0 +1,7 @@
1+The GHC parser (in Haddock mode) failed:
2+ src/Idris/Parser.hs:1052:1
3+ parse error on input `@'
4+
5+The GHC parser (in Haddock mode) failed:
6+ src/Idris/Parser/Expr.hs:75:1
7+ parse error on input `@'
expected-failures/intero.txtnew file+5
@@ -0,0 +1,5 @@
1+Formatting is not idempotent:
2+ src/InteractiveUI.hs<rendered>:3748:33
3+ before: "text \"Try\" <+> doWha"
4+ after: "text \"Try\"\n "
5+Please, consider reporting the bug.
expected-failures/leksah.txtnew file+5
@@ -0,0 +1,5 @@
1+Formatting is not idempotent:
2+ src/IDE/Pane/Modules.hs<rendered>:1184:7
3+ before: "cr\n -- show"
4+ after: "cr\n in -- show"
5+Please, consider reporting the bug.
expected-failures/lens.txtnew file+3
@@ -0,0 +1,3 @@
1+The GHC parser (in Haddock mode) failed:
2+ src/Control/Exception/Lens.hs:180:13-37
3+ parse error on input `AllocationLimitExceeded__'
expected-failures/pandoc.txtnew file+9
@@ -0,0 +1,9 @@
1+The GHC parser (in Haddock mode) failed:
2+ benchmark/weigh-pandoc.hs:14:1-6
3+ parse error on input `import'
4+
5+Formatting is not idempotent:
6+ src/Text/Pandoc/Readers/Vimwiki.hs<rendered>:613:19
7+ before: ".softbreak <$ endlin"
8+ after: ".softbreak\n <$ en"
9+Please, consider reporting the bug.
expected-failures/pipes.txtnew file+3
@@ -0,0 +1,3 @@
1+AST of input and AST of formatted code differ.
2+ at src/Pipes/Core.hs:(128,1)-(151,2)
3+Please, consider reporting the bug.
expected-failures/postgrest.txtnew file+5
@@ -0,0 +1,5 @@
1+Formatting is not idempotent:
2+ src/PostgREST/DbRequestBuilder.hs<rendered>:149:24
3+ before: " || -- clients"
4+ after: " || ( origin ="
5+Please, consider reporting the bug.
expected-failures/purescript.txtnew file+18
@@ -0,0 +1,18 @@
1+The GHC parser (in Haddock mode) failed:
2+ src/Language/PureScript/AST/Declarations.hs:479:1-17
3+ Invalid type signature: pattern ValueDecl :: ...
4+Perhaps you meant to use PatternSynonyms?
5+
6+The GHC parser (in Haddock mode) failed:
7+ src/Language/PureScript/AST/SourcePos.hs:99:1-22
8+ Invalid type signature: pattern NullSourceSpan :: ...
9+Perhaps you meant to use PatternSynonyms?
10+
11+The GHC parser (in Haddock mode) failed:
12+ src/Language/PureScript/Constants.hs:42:1-15
13+ Invalid type signature: pattern Discard :: ...
14+Perhaps you meant to use PatternSynonyms?
15+
16+The GHC parser (in Haddock mode) failed:
17+ src/Language/PureScript/Crash.hs:16:1-6
18+ parse error on input `import'
expected-failures/tensorflow.txtnew file+7
@@ -0,0 +1,7 @@
1+The GHC parser (in Haddock mode) failed:
2+ tensorflow-mnist/app/Main.hs:50:13-14
3+ parse error on input `->'
4+
5+The GHC parser (in Haddock mode) failed:
6+ tensorflow-ops/tests/RegressionTest.hs:3:1-6
7+ parse error on input `import'
format.shnew file+14
@@ -0,0 +1,14 @@
1+#!/usr/bin/env nix-shell
2+#!nix-shell default.nix -A dev.withOrmolu -i bash --pure
3+#
4+# Format Ormolu using current version of Ormolu.
5+
6+set -e
7+
8+export LANG="C.UTF-8"
9+
10+cabal format
11+
12+ormolu -m inplace $(find app -type f -name "*.hs")
13+ormolu -m inplace $(find src -type f \( -name "*.hs" -o -name "*.hs-boot" \))
14+ormolu -m inplace $(find tests -type f -name "*.hs")
nix/gitignore/default.nixdeleted−8
@@ -1,8 +0,0 @@
1−{ lib }:
2−
3−let
4− rev = "ec5dd0536a5e4c3a99c797b86180f7261197c124";
5− sha256 = "0k2r8y21rn4kr5dmddd3906x0733fs3bb8hzfpabkdav3wcy3klv";
6− url = "https://github.com/hercules-ci/gitignore/archive/${rev}.tar.gz";
7− nixGitIgnore = builtins.fetchTarball { inherit url sha256; };
8−in (import nixGitIgnore { inherit lib; }).gitignoreSource
nix/nixpkgs/default.nix+7−3
@@ -1,9 +1,13 @@
1+{ system ? builtins.currentSystem }:
12let
2− rev = "454eea84a757ca5f733c4ec0f234eba2281c74eb";
3− sha256 = "1k9jbix4w43brqlfmvwy218pf5fbmzsnc08shaww9qfdl1rdlaxy";
3+ rev = "32b46dd897ab2143a609988a04d87452f0bbef59";
4+ sha256 = "1gzfrpjnr1bz9zljsyg3a4zrhk8r927sz761mrgcg56dwinkhpjk";
45 nixpkgs = builtins.fetchTarball {
56 url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
67 inherit sha256;
78 };
8− pkgs = import nixpkgs { config.allowUnfree = true; };
9+ pkgs = import nixpkgs {
10+ inherit system;
11+ config.allowUnfree = true;
12+ };
913in pkgs
nix/ormolize/default.nixnew file+53
@@ -0,0 +1,53 @@
1+{ pkgs
2+, haskellPackages
3+}:
4+{ package
5+, expectedFailures ? null
6+, doCheck ? false
7+}:
8+ pkgs.stdenv.mkDerivation rec {
9+ name = package.name + "-ormolized";
10+ src = package.src;
11+ buildInputs = [
12+ haskellPackages.cpphs
13+ haskellPackages.ormolu
14+ pkgs.diffutils
15+ pkgs.glibcLocales
16+ ];
17+ LANG = "en_US.UTF-8";
18+ buildPhase = ''
19+ hs_files=$(find . -name '*.hs')
20+ for hs_file in $hs_files; do
21+
22+ # drop includes
23+ sed -i '/^#include/d' "$hs_file"
24+
25+ # deal with CPP
26+ cpphs "$hs_file" --noline -DARCH_X86 > "''${hs_file}-nocpp" 2> /dev/null
27+
28+ # annoyingly, cpphs cannot modify files in place
29+ mv "''${hs_file}-nocpp" "$hs_file"
30+
31+ # preserve the original
32+ cp "$hs_file" "''${hs_file}-original"
33+ done
34+
35+ (ormolu --check-idempotence --mode inplace $hs_files || true) 2> log.txt
36+ '';
37+ inherit doCheck;
38+ checkPhase =
39+ if expectedFailures == null
40+ then ''
41+ echo "No failures expected"
42+ if [[ -s log.txt ]]; then exit 1; fi
43+ ''
44+ else ''
45+ diff --ignore-blank-lines --color=always ${expectedFailures} log.txt
46+ '';
47+ installPhase = ''
48+ mkdir "$out"
49+ find . -name '*.hs-original' -exec cp --parents {} $out \;
50+ find . -name '*.hs' -exec cp --parents {} $out \;
51+ cp log.txt $out/log.txt
52+ '';
53+ }
ormolu.cabal+174−122
@@ -1,132 +1,184 @@
1−name: ormolu
2−version: 0.0.1.0
3−cabal-version: 1.18
4−tested-with: GHC==8.6.4
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: CHANGELOG.md
15− , README.md
16−data-files: data/examples/declaration/data/*.hs
17− , data/examples/declaration/data/gadt/*.hs
18− , data/examples/declaration/type-families/closed-type-family/*.hs
19− , data/examples/declaration/type-families/data-family/*.hs
20− , data/examples/declaration/type-families/type-family/*.hs
21− , data/examples/declaration/type-synonyms/*.hs
22− , data/examples/import/*.hs
23− , data/examples/module-header/*.hs
24− , data/examples/other/*.hs
25− , data/printer/*.hs
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
2657
2758source-repository head
28− type: git
29− location: https://github.com/tweag/ormolu.git
59+ type: git
60+ location: https://github.com/tweag/ormolu.git
3061
3162flag dev
32− description: Turn on development settings.
33− manual: True
34− default: False
63+ description: Turn on development settings.
64+ default: False
65+ manual: True
3566
3667library
37− hs-source-dirs: src
38− build-depends: base >= 4.12 && < 5.0
39− , containers >= 0.5 && < 0.7
40− , dlist >= 0.8 && < 0.9
41− , exceptions >= 0.6 && < 0.11
42− , ghc >= 8.4.3
43− , ghc-boot-th >= 8.4.3
44− , ghc-paths >= 0.1 && < 0.2
45− , mtl >= 2.0 && < 3.0
46− , syb >= 0.7 && < 0.8
47− , text >= 0.2 && < 1.3
48− , yaml >= 0.8 && < 0.12
49− exposed-modules: Ormolu
50− , Ormolu.Anns
51− , Ormolu.CommentStream
52− , Ormolu.Config
53− , Ormolu.Diff
54− , Ormolu.Exception
55− , Ormolu.Imports
56− , Ormolu.Parser
57− , Ormolu.Printer
58− , Ormolu.Printer.Combinators
59− , Ormolu.Printer.Comments
60− , Ormolu.Printer.Internal
61− , Ormolu.Printer.Meat.Common
62− , Ormolu.Printer.Meat.Declaration
63− , Ormolu.Printer.Meat.Declaration.Annotation
64− , Ormolu.Printer.Meat.Declaration.Class
65− , Ormolu.Printer.Meat.Declaration.Data
66− , Ormolu.Printer.Meat.Declaration.Default
67− , Ormolu.Printer.Meat.Declaration.Foreign
68− , Ormolu.Printer.Meat.Declaration.Instance
69− , Ormolu.Printer.Meat.Declaration.RoleAnnotation
70− , Ormolu.Printer.Meat.Declaration.Signature
71− , Ormolu.Printer.Meat.Declaration.Splice
72− , Ormolu.Printer.Meat.Declaration.Type
73− , Ormolu.Printer.Meat.Declaration.TypeFamily
74− , Ormolu.Printer.Meat.Declaration.Value
75− , Ormolu.Printer.Meat.ImportExport
76− , Ormolu.Printer.Meat.Module
77− , Ormolu.Printer.Meat.Type
78− , Ormolu.SpanStream
79− , Ormolu.Utils
80− if flag(dev)
81− ghc-options: -Wall -Werror -Wcompat
82− -Wincomplete-record-updates
83− -Wincomplete-uni-patterns
84− -Wnoncanonical-monad-instances
85− -Wnoncanonical-monadfail-instances
86− else
87− ghc-options: -O2 -Wall
88− default-language: Haskell2010
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
89111
90−test-suite tests
91− main-is: Spec.hs
92− hs-source-dirs: tests
93− type: exitcode-stdio-1.0
94− build-depends: base >= 4.12 && < 5.0
95− , containers >= 0.5 && < 0.7
96− , filepath >= 1.2 && < 1.5
97− , hspec >= 2.0 && < 3.0
98− , ormolu
99− , path >= 0.6 && < 0.7
100− , path-io >= 1.4.2 && < 2.0
101− , text >= 0.2 && < 1.3
102− build-tools: hspec-discover >= 2.0 && < 3.0
103− other-modules:
104− Ormolu.Printer.CombinatorsSpec
105− , Ormolu.PrinterSpec
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
106128
107− if flag(dev)
108− ghc-options: -Wall -Werror
109− else
110− ghc-options: -O2 -Wall
111− default-language: Haskell2010
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
112137
113138executable ormolu
114− main-is: Main.hs
115− hs-source-dirs: app
116− build-depends: base >= 4.12 && < 5.0
117− , ghc >= 8.4.3
118− , gitrev >= 1.3 && < 1.4
119− , optparse-applicative >= 0.14 && < 0.15
120− , ormolu
121− , text >= 0.2 && < 1.3
122− , yaml >= 0.8 && < 0.12
123− other-modules: Paths_ormolu
124− if flag(dev)
125− ghc-options: -Wall -Werror -Wcompat
126− -Wincomplete-record-updates
127− -Wincomplete-uni-patterns
128− -Wnoncanonical-monad-instances
129− -Wnoncanonical-monadfail-instances
130− else
131− ghc-options: -O2 -Wall
132− default-language: Haskell2010
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
159+
160+test-suite tests
161+ type: exitcode-stdio-1.0
162+ main-is: Spec.hs
163+ build-tools: hspec-discover >=2.0 && <3.0
164+ hs-source-dirs: tests
165+ other-modules:
166+ Ormolu.Parser.PragmaSpec
167+ Ormolu.PrinterSpec
168+
169+ default-language: Haskell2010
170+ build-depends:
171+ base >=4.12 && <5.0,
172+ containers >=0.5 && <0.7,
173+ filepath >=1.2 && <1.5,
174+ hspec >=2.0 && <3.0,
175+ ormolu -any,
176+ path >=0.6 && <0.8,
177+ path-io >=1.4.2 && <2.0,
178+ text >=0.2 && <1.3
179+
180+ if flag(dev)
181+ ghc-options: -Wall -Werror
182+
183+ else
184+ ghc-options: -O2 -Wall
region-tests/expected-result-17-18.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# LANGUAGE LambdaCase #-}
2+
3+module Foo (
4+ foo, bar, baz) where
5+
6+foo :: Int
7+foo = 5
8+
9+bar :: Int -> Int
10+bar = \case
11+ 0 -> foo
12+ x -> x - foo
13+
14+baz :: Int -> Int
15+baz = gege
16+ where
17+ gege = 1 + 2
region-tests/expected-result-6-7.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# LANGUAGE LambdaCase #-}
2+
3+module Foo (
4+ foo, bar, baz) where
5+
6+foo :: Int
7+foo = 5
8+
9+bar :: Int -> Int
10+bar = \case
11+ 0 -> foo
12+ x -> x - foo
13+
14+baz :: Int -> Int
15+baz = gege
16+ where
17+ gege = 1 + 2
region-tests/expected-result-6-8.hsnew file+16
@@ -0,0 +1,16 @@
1+{-# LANGUAGE LambdaCase #-}
2+
3+module Foo (
4+ foo, bar, baz) where
5+
6+foo :: Int
7+foo = 5
8+bar :: Int -> Int
9+bar = \case
10+ 0 -> foo
11+ x -> x - foo
12+
13+baz :: Int -> Int
14+baz = gege
15+ where
16+ gege = 1 + 2
region-tests/expected-result-9-12.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# LANGUAGE LambdaCase #-}
2+
3+module Foo (
4+ foo, bar, baz) where
5+
6+foo :: Int
7+foo = 5
8+
9+bar :: Int -> Int
10+bar = \case
11+ 0 -> foo
12+ x -> x - foo
13+
14+baz :: Int -> Int
15+baz = gege
16+ where
17+ gege = 1 + 2
region-tests/expected-result-all.hsnew file+21
@@ -0,0 +1,21 @@
1+{-# LANGUAGE LambdaCase #-}
2+
3+module Foo
4+ ( foo,
5+ bar,
6+ baz,
7+ )
8+where
9+
10+foo :: Int
11+foo = 5
12+
13+bar :: Int -> Int
14+bar = \case
15+ 0 -> foo
16+ x -> x - foo
17+
18+baz :: Int -> Int
19+baz = gege
20+ where
21+ gege = 1 + 2
region-tests/src.hsnew file+17
@@ -0,0 +1,17 @@
1+{-# LANGUAGE LambdaCase #-}
2+
3+module Foo (
4+ foo, bar, baz) where
5+
6+foo :: Int
7+foo = 5
8+
9+bar :: Int -> Int
10+bar = \case
11+ 0 -> foo
12+ x -> x - foo
13+
14+baz :: Int -> Int
15+baz = gege
16+ where
17+ gege = 1 + 2
shell.nix+5−1
@@ -1 +1,5 @@
1−(import ./default.nix).ormolu-shell
1+{ pkgs ? (import ./nix/nixpkgs { inherit system; })
2+, system ? builtins.currentSystem
3+}:
4+
5+(import ./default.nix { inherit pkgs; }).dev.ormoluShell
src/GHC.hsnew file+12
@@ -0,0 +1,12 @@
1+module GHC
2+ ( module X,
3+ )
4+where
5+
6+import ApiAnnotation as X
7+import BasicTypes as X
8+import GHC.Hs as X
9+import GHC.Hs.Instances as X ()
10+import Module as X
11+import RdrName as X
12+import SrcLoc as X
src/GHC/DynFlags.hsnew file+49
@@ -0,0 +1,49 @@
1+{-# OPTIONS_GHC -Wno-missing-fields #-}
2+
3+-- Modified from ghc-lib-api-ext.
4+
5+module GHC.DynFlags
6+ ( baseDynFlags,
7+ )
8+where
9+
10+import Config
11+import DynFlags
12+import Fingerprint
13+import GHC.Platform
14+import ToolSettings
15+
16+fakeSettings :: Settings
17+fakeSettings =
18+ Settings
19+ { sGhcNameVersion =
20+ GhcNameVersion
21+ { ghcNameVersion_programName = "ghc",
22+ ghcNameVersion_projectVersion = cProjectVersion
23+ },
24+ sFileSettings = FileSettings {},
25+ sTargetPlatform =
26+ Platform
27+ { platformWordSize = PW8,
28+ platformMini =
29+ PlatformMini
30+ { platformMini_arch = ArchUnknown,
31+ platformMini_os = OSUnknown
32+ },
33+ platformUnregisterised = True
34+ },
35+ sPlatformMisc = PlatformMisc {},
36+ sPlatformConstants =
37+ PlatformConstants {pc_DYNAMIC_BY_DEFAULT = False, pc_WORD_SIZE = 8},
38+ sToolSettings =
39+ ToolSettings
40+ { toolSettings_opt_P_fingerprint = fingerprint0,
41+ toolSettings_pgm_F = ""
42+ }
43+ }
44+
45+fakeLlvmConfig :: LlvmConfig
46+fakeLlvmConfig = LlvmConfig [] []
47+
48+baseDynFlags :: DynFlags
49+baseDynFlags = defaultDynFlags fakeSettings fakeLlvmConfig
src/Ormolu.hs+98−70
@@ -1,34 +1,34 @@
1−-- | A formatter for Haskell source code.
2−
3−{-# LANGUAGE RecordWildCards #-}
1+{-# LANGUAGE BangPatterns #-}
42
3+-- | A formatter for Haskell source code.
54module Ormolu
6− ( ormolu
7− , ormoluFile
8− , Config (..)
9− , defaultConfig
10− , DynOption (..)
11− , OrmoluException (..)
12− , withPrettyOrmoluExceptions
5+ ( ormolu,
6+ ormoluFile,
7+ ormoluStdin,
8+ Config (..),
9+ RegionIndices (..),
10+ defaultConfig,
11+ DynOption (..),
12+ OrmoluException (..),
13+ withPrettyOrmoluExceptions,
1314 )
1415where
1516
17+import qualified CmdLineParser as GHC
1618import Control.Exception
1719import Control.Monad
1820import Control.Monad.IO.Class (MonadIO (..))
1921import Data.Text (Text)
22+import qualified Data.Text as T
2023import Debug.Trace
21−import Ormolu.Anns
22−import Ormolu.CommentStream
2324import Ormolu.Config
2425import Ormolu.Diff
2526import Ormolu.Exception
2627import Ormolu.Parser
28+import Ormolu.Parser.Result
2729import Ormolu.Printer
28−import qualified CmdLineParser as GHC
29−import qualified Data.Text as T
30−import qualified GHC
31−import qualified Outputable as GHC
30+import Ormolu.Utils (showOutputable)
31+import qualified SrcLoc as GHC
3232
3333-- | Format a 'String', return formatted version as 'Text'.
3434--
@@ -40,29 +40,52 @@ import qualified Outputable as GHC
4040-- side-effects though.
4141-- * Takes file name just to use it in parse error messages.
4242-- * Throws 'OrmoluException'.
43−
44−ormolu
45− :: MonadIO m
46− => Config -- ^ Ormolu configuration
47− -> FilePath -- ^ Location of source file
48− -> String -- ^ Input to format
49− -> m Text
50−ormolu cfg path str = do
51− (ws, (cstream0, anns0, parsedSrc0)) <-
43+ormolu ::
44+ MonadIO m =>
45+ -- | Ormolu configuration
46+ Config RegionIndices ->
47+ -- | Location of source file
48+ FilePath ->
49+ -- | Input to format
50+ String ->
51+ m Text
52+ormolu cfgWithIndices path str = do
53+ let totalLines = length (lines str)
54+ cfg = regionIndicesToDeltas totalLines <$> cfgWithIndices
55+ (warnings, result0) <-
5256 parseModule' cfg OrmoluParsingFailed path str
5357 when (cfgDebug cfg) $ do
5458 traceM "warnings:\n"
55− traceM (concatMap showWarn ws)
56− traceM "comment stream:\n"
57− traceM (showCommentStream cstream0)
58− let txt = printModule (cfgDebug cfg) cstream0 anns0 parsedSrc0
59− -- Parse the result of pretty-printing again and make sure that AST is the
60− -- same as AST of original snippet module span positions.
61− unless (cfgUnsafe cfg) $ do
62− (_, (cstream1, _, parsedSrc1)) <-
63− parseModule' cfg OrmoluOutputParsingFailed "<rendered>" (T.unpack txt)
64− when (diff (cstream0, parsedSrc0) (cstream1, parsedSrc1)) $
65− liftIO $ throwIO (OrmoluASTDiffers str txt)
59+ traceM (concatMap showWarn warnings)
60+ traceM (prettyPrintParseResult result0)
61+ -- We're forcing 'txt' here because otherwise errors (such as messages
62+ -- about not-yet-supported functionality) will be thrown later when we try
63+ -- to parse the rendered code back, inside of GHC monad wrapper which will
64+ -- lead to error messages presenting the exceptions as GHC bugs.
65+ let !txt = printModule result0
66+ when (not (cfgUnsafe cfg) || cfgCheckIdempotence cfg) $ do
67+ let pathRendered = path ++ "<rendered>"
68+ -- Parse the result of pretty-printing again and make sure that AST
69+ -- is the same as AST of original snippet module span positions.
70+ (_, result1) <-
71+ parseModule'
72+ cfg
73+ OrmoluOutputParsingFailed
74+ pathRendered
75+ (T.unpack txt)
76+ unless (cfgUnsafe cfg) $
77+ case diffParseResult result0 result1 of
78+ Same -> return ()
79+ Different ss -> liftIO $ throwIO (OrmoluASTDiffers path ss)
80+ -- Try re-formatting the formatted result to check if we get exactly
81+ -- the same output.
82+ when (cfgCheckIdempotence cfg) $
83+ let txt2 = printModule result1
84+ in case diffText txt txt2 pathRendered of
85+ Nothing -> return ()
86+ Just (loc, l, r) ->
87+ liftIO $
88+ throwIO (OrmoluNonIdempotentOutput loc l r)
6689 return txt
6790
6891-- | Load a file and format it. The file stays intact and the rendered
@@ -70,50 +93,55 @@ ormolu cfg path str = do
7093--
7194-- > ormoluFile cfg path =
7295-- > liftIO (readFile path) >>= ormolu cfg path
73−
74−ormoluFile
75− :: MonadIO m
76− => Config -- ^ Ormolu configuration
77− -> FilePath -- ^ Location of source file
78− -> m Text -- ^ Resulting rendition
96+ormoluFile ::
97+ MonadIO m =>
98+ -- | Ormolu configuration
99+ Config RegionIndices ->
100+ -- | Location of source file
101+ FilePath ->
102+ -- | Resulting rendition
103+ m Text
79104ormoluFile cfg path =
80105 liftIO (readFile path) >>= ormolu cfg path
81106
107+-- | Read input from stdin and format it.
108+--
109+-- > ormoluStdin cfg =
110+-- > liftIO (hGetContents stdin) >>= ormolu cfg "<stdin>"
111+ormoluStdin ::
112+ MonadIO m =>
113+ -- | Ormolu configuration
114+ Config RegionIndices ->
115+ -- | Resulting rendition
116+ m Text
117+ormoluStdin cfg =
118+ liftIO getContents >>= ormolu cfg "<stdin>"
119+
82120----------------------------------------------------------------------------
83121-- Helpers
84122
85123-- | A wrapper around 'parseModule'.
86−
87−parseModule'
88− :: MonadIO m
89− => Config -- ^ Ormolu configuration
90− -> (GHC.SrcSpan -> String -> OrmoluException)
91− -- ^ How to obtain 'OrmoluException' to throw when parsing fails
92− -> FilePath -- ^ File name to use in errors
93− -> String -- ^ Actual input for the parser
94− -> m ([GHC.Warn], (CommentStream, Anns, GHC.ParsedSource))
95− -- ^ Comment stream and parsed source
96−parseModule' Config {..} mkException path str = do
97− (ws, r) <- parseModule cfgDynOptions path str
124+parseModule' ::
125+ MonadIO m =>
126+ -- | Ormolu configuration
127+ Config RegionDeltas ->
128+ -- | How to obtain 'OrmoluException' to throw when parsing fails
129+ (GHC.SrcSpan -> String -> OrmoluException) ->
130+ -- | File name to use in errors
131+ FilePath ->
132+ -- | Actual input for the parser
133+ String ->
134+ m ([GHC.Warn], ParseResult)
135+parseModule' cfg mkException path str = do
136+ (warnings, r) <- parseModule cfg path str
98137 case r of
99138 Left (spn, err) -> liftIO $ throwIO (mkException spn err)
100− Right x -> return (ws, x)
139+ Right x -> return (warnings, x)
101140
102141-- | Pretty-print a 'GHC.Warn'.
103−
104142showWarn :: GHC.Warn -> String
105143showWarn (GHC.Warn reason l) =
106− showOutputable reason ++ "\n" ++ showOutputable l ++ "\n"
107−
108−-- | Pretty-print a 'CommentStream'.
109−
110−showCommentStream :: CommentStream -> String
111−showCommentStream (CommentStream xs) = unlines $
112− showComment <$> xs
113− where
114− showComment (GHC.L l str) = showOutputable l ++ " " ++ show str
115−
116−-- | Pretty-print an 'GHC.Outputable' thing.
117−
118−showOutputable :: GHC.Outputable o => o -> String
119−showOutputable = GHC.showSDocUnsafe . GHC.ppr
144+ unlines
145+ [ showOutputable reason,
146+ showOutputable l
147+ ]
src/Ormolu/CommentStream.hsdeleted−96
@@ -1,96 +0,0 @@
1−{-# LANGUAGE DeriveDataTypeable #-}
2−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3−{-# LANGUAGE LambdaCase #-}
4−
5−-- | Functions for working with comment stream.
6−
7−module Ormolu.CommentStream
8− ( CommentStream (..)
9− , Comment (..)
10− , mkCommentStream
11− , isPrevHaddock
12− )
13−where
14−
15−import Data.Data (Data)
16−import Data.List (isPrefixOf, sortOn)
17−import Data.List.NonEmpty (NonEmpty (..))
18−import Data.Maybe (mapMaybe)
19−import SrcLoc
20−import qualified Data.List.NonEmpty as NE
21−import qualified GHC
22−import qualified Lexer as GHC
23−
24−-- | A stream of 'RealLocated' 'Comment's in ascending order with respect to
25−-- beginning of corresponding spans.
26−
27−newtype CommentStream = CommentStream [RealLocated Comment]
28− deriving (Eq, Data, Semigroup, Monoid)
29−
30−-- | A wrapper for a single comment. The 'NonEmpty' list inside contains
31−-- lines of multiline comment @{- … -}@ or just single item\/line otherwise.
32−
33−newtype Comment = Comment (NonEmpty String)
34− deriving (Eq, Show, Data)
35−
36−-- | Create 'CommentStream' from 'GHC.PState'.
37−
38−mkCommentStream
39− :: [Located String] -- ^ Extra comments to include
40− -> GHC.PState -- ^ Parser state to use for comment extraction
41− -> CommentStream
42−mkCommentStream extraComments pstate
43− = CommentStream
44− -- NOTE It's easier to normalize pragmas right when we construct comment
45− -- streams. Because this way we need to do it only once and when we
46− -- perform checking later they'll automatically match.
47− . fmap (fmap (Comment . normalizeComment . normalizePragma))
48− . sortOn startOfSpan
49− . mapMaybe toRealSpan $
50− extraComments ++
51− (fmap unAnnotationComment <$> GHC.comment_q pstate) ++
52− concatMap (fmap (fmap unAnnotationComment) . snd)
53− (GHC.annotations_comments pstate)
54− where
55− startOfSpan (L l _) = realSrcSpanStart l
56− toRealSpan (L (RealSrcSpan l) a) = Just (L l a)
57− toRealSpan _ = Nothing
58−
59−-- | Test whether a 'Comment' looks like a Haddock following a definition,
60−-- i.e. something starting with @-- ^@.
61−
62−isPrevHaddock :: Comment -> Bool
63−isPrevHaddock (Comment (x :| _)) = "-- ^" `isPrefixOf` x
64−
65−----------------------------------------------------------------------------
66−-- Helpers
67−
68−-- | Normalize pragmas by deleting extra white space.
69−
70−normalizePragma :: String -> String
71−normalizePragma x =
72− if "{-#" `isPrefixOf` x
73− then unwords (words x)
74− else x
75−
76−-- | Normalize comment string. Sometimes one multi-line comment is turned
77−-- into several lines for subsequent outputting with correct indentation for
78−-- each line.
79−
80−normalizeComment :: String -> NonEmpty String
81−normalizeComment s =
82− case NE.nonEmpty (lines s) of
83− Nothing -> s :| []
84− Just xs -> dropWhile (== ' ') <$> xs
85−
86−-- | Get a 'String' from 'GHC.AnnotationComment'.
87−
88−unAnnotationComment :: GHC.AnnotationComment -> String
89−unAnnotationComment = \case
90− GHC.AnnDocCommentNext s -> s
91− GHC.AnnDocCommentPrev s -> s
92− GHC.AnnDocCommentNamed s -> s
93− GHC.AnnDocSection _ s -> s
94− GHC.AnnDocOptions s -> s
95− GHC.AnnLineComment s -> s
96− GHC.AnnBlockComment s -> s
src/Ormolu/Config.hs+68−44
@@ -1,65 +1,89 @@
1−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
1+{-# LANGUAGE DeriveFunctor #-}
2+{-# LANGUAGE RecordWildCards #-}
43
54-- | Configuration options used by the tool.
6−
75module Ormolu.Config
8− ( Config (..)
9− , defaultConfig
10− , DynOption (..)
11− , dynOptionToLocatedStr
6+ ( Config (..),
7+ RegionIndices (..),
8+ RegionDeltas (..),
9+ defaultConfig,
10+ regionIndicesToDeltas,
11+ DynOption (..),
12+ dynOptionToLocatedStr,
1213 )
1314where
1415
15−import Data.Yaml
1616import qualified SrcLoc as GHC
1717
1818-- | 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)
1932
20−data Config = Config
21− { cfgDynOptions :: ![DynOption]
22− -- ^ Dynamic options to pass to GHC parser
23− , cfgUnsafe :: !Bool
24− -- ^ Do formatting faster but without automatic detection of defects
25− , cfgDebug :: !Bool
26− -- ^ Output information useful for debugging
27− } deriving (Eq, Show)
28−
29−instance Semigroup Config where
30− a <> b = Config
31− { cfgDynOptions = cfgDynOptions a <> cfgDynOptions b
32− , cfgUnsafe = cfgUnsafe a || cfgUnsafe b
33− , cfgDebug = cfgDebug a || cfgDebug b
34− }
35−
36−instance Monoid Config where
37− mempty = defaultConfig
38− mappend = (<>)
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)
3941
40−instance FromJSON Config where
41− parseJSON = withObject "config" $ \o -> do
42− cfgDynOptions <- o .: "ghc-opts"
43− cfgUnsafe <- o .: "unsafe"
44− cfgDebug <- o .: "debug"
45− return Config {..}
42+-- | Region selection as the length of the literal prefix and the literal
43+-- suffix.
44+data RegionDeltas = RegionDeltas
45+ { -- | Prefix length in number of lines
46+ regionPrefixLength :: !Int,
47+ -- | Suffix length in number of lines
48+ regionSuffixLength :: !Int
49+ }
50+ deriving (Eq, Show)
4651
47−-- | Default 'Config'.
52+-- | Default @'Config' 'RegionIndices'@.
53+defaultConfig :: Config RegionIndices
54+defaultConfig =
55+ Config
56+ { cfgDynOptions = [],
57+ cfgUnsafe = False,
58+ cfgDebug = False,
59+ cfgCheckIdempotence = False,
60+ cfgRegion =
61+ RegionIndices
62+ { regionStartLine = Nothing,
63+ regionEndLine = Nothing
64+ }
65+ }
4866
49−defaultConfig :: Config
50−defaultConfig = Config
51− { cfgDynOptions = []
52− , cfgUnsafe = False
53− , cfgDebug = False
54− }
67+-- | Convert 'RegionIndices' into 'RegionDeltas'.
68+regionIndicesToDeltas ::
69+ -- | Total number of lines in the input
70+ Int ->
71+ -- | Region indices
72+ RegionIndices ->
73+ -- | Region deltas
74+ RegionDeltas
75+regionIndicesToDeltas total RegionIndices {..} =
76+ RegionDeltas
77+ { regionPrefixLength = maybe 0 (subtract 1) regionStartLine,
78+ regionSuffixLength = maybe 0 (total -) regionEndLine
79+ }
5580
5681-- | A wrapper for dynamic options.
57−
5882newtype DynOption = DynOption
5983 { unDynOption :: String
60− } deriving (Eq, Ord, Show, FromJSON)
84+ }
85+ deriving (Eq, Ord, Show)
6186
6287-- | Convert 'DynOption' to @'GHC.Located' 'String'@.
63−
6488dynOptionToLocatedStr :: DynOption -> GHC.Located String
6589dynOptionToLocatedStr (DynOption o) = GHC.L GHC.noSrcSpan o
src/Ormolu/Diff.hs+143−40
@@ -1,55 +1,158 @@
1−{-# LANGUAGE DeriveDataTypeable #-}
2−{-# LANGUAGE RankNTypes #-}
3−{-# LANGUAGE RecordWildCards #-}
1+{-# LANGUAGE RankNTypes #-}
42
53-- | Diffing GHC ASTs modulo span positions.
6−
74module Ormolu.Diff
8− ( diff
5+ ( Diff (..),
6+ diffParseResult,
7+ diffText,
98 )
109where
1110
12−import BasicTypes (SourceText)
11+import Data.ByteString (ByteString)
1312import Data.Generics
13+import Data.Text (Text)
14+import qualified Data.Text as T
15+import qualified FastString as GHC
1416import GHC
15−import Ormolu.CommentStream
16−import Ormolu.Imports (sortImports)
17+import Ormolu.Imports (normalizeImports)
18+import Ormolu.Parser.CommentStream
19+import Ormolu.Parser.Result
20+import Ormolu.Utils
21+
22+-- | Result of comparing two 'ParseResult's.
23+data Diff
24+ = -- | Two parse results are the same
25+ Same
26+ | -- | Two parse results differ
27+ Different [SrcSpan]
28+
29+instance Semigroup Diff where
30+ Same <> a = a
31+ a <> Same = a
32+ Different xs <> Different ys = Different (xs ++ ys)
1733
18−-- | Return 'False' if two annotated ASTs are the same modulo span
19−-- positions.
34+instance Monoid Diff where
35+ mempty = Same
2036
21−diff
22− :: (CommentStream, ParsedSource) -- ^ First comment stream and AST
23− -> (CommentStream, ParsedSource) -- ^ Second comment stream and AST
24− -> Bool
25−diff (cstream0, ps0) (cstream1, ps1) =
26− not (matchIgnoringSrcSpans cstream0 cstream1)
27− || not (matchIgnoringSrcSpans ps0 ps1)
37+-- | Return 'Diff' of two 'ParseResult's.
38+diffParseResult :: ParseResult -> ParseResult -> Diff
39+diffParseResult
40+ ParseResult
41+ { prCommentStream = cstream0,
42+ prParsedSource = hs0
43+ }
44+ ParseResult
45+ { prCommentStream = cstream1,
46+ prParsedSource = hs1
47+ } =
48+ matchIgnoringSrcSpans cstream0 cstream1
49+ <> matchIgnoringSrcSpans
50+ hs0 {hsmodImports = normalizeImports (hsmodImports hs0)}
51+ hs1 {hsmodImports = normalizeImports (hsmodImports hs1)}
2852
2953-- | Compare two values for equality disregarding differences in 'SrcSpan's
3054-- and the ordering of import lists.
31−
32−matchIgnoringSrcSpans :: Data a => a -> a -> Bool
55+matchIgnoringSrcSpans :: Data a => a -> a -> Diff
3356matchIgnoringSrcSpans = genericQuery
3457 where
35− genericQuery :: GenericQ (GenericQ Bool)
36− genericQuery x y = (toConstr x == toConstr y)
37− && and (gzipWithQ (genericQuery
38− `extQ` srcSpanEq
39− `extQ` hsModuleEq
40− `extQ` sourceTextEq) x y)
41−
42− srcSpanEq :: SrcSpan -> GenericQ Bool
43− srcSpanEq _ _ = True
44−
45− hsModuleEq :: HsModule GhcPs -> GenericQ Bool
46− hsModuleEq hs0 hs1' =
47− case cast hs1' :: Maybe (HsModule GhcPs) of
48− Nothing -> False
49− Just hs1 ->
50− matchIgnoringSrcSpans
51− hs0 { hsmodImports = sortImports (hsmodImports hs0) }
52− hs1 { hsmodImports = sortImports (hsmodImports hs1) }
53−
54− sourceTextEq :: SourceText -> GenericQ Bool
55− sourceTextEq _ _ = True
58+ genericQuery :: GenericQ (GenericQ Diff)
59+ genericQuery x y
60+ -- 'ByteString' implements 'Data' instance manually and does not
61+ -- implement 'toConstr', so we have to deal with it in a special way.
62+ | Just x' <- cast x,
63+ Just y' <- cast y =
64+ if x' == (y' :: ByteString)
65+ then Same
66+ else Different []
67+ | typeOf x == typeOf y,
68+ toConstr x == toConstr y =
69+ mconcat $
70+ gzipWithQ
71+ ( genericQuery
72+ `extQ` srcSpanEq
73+ `extQ` commentEq
74+ `extQ` sourceTextEq
75+ `extQ` hsDocStringEq
76+ `extQ` importDeclQualifiedStyleEq
77+ `ext2Q` forLocated
78+ )
79+ x
80+ y
81+ | otherwise = Different []
82+ srcSpanEq :: SrcSpan -> GenericQ Diff
83+ srcSpanEq _ _ = Same
84+ commentEq :: Comment -> GenericQ Diff
85+ commentEq (Comment _ x) d =
86+ case cast d :: Maybe Comment of
87+ Nothing -> Different []
88+ Just (Comment _ y) ->
89+ if x == y
90+ then Same
91+ else Different []
92+ sourceTextEq :: SourceText -> GenericQ Diff
93+ sourceTextEq _ _ = Same
94+ importDeclQualifiedStyleEq :: ImportDeclQualifiedStyle -> GenericQ Diff
95+ importDeclQualifiedStyleEq d0 d1' =
96+ case (d0, cast d1' :: Maybe ImportDeclQualifiedStyle) of
97+ (x, Just x') | x == x' -> Same
98+ (QualifiedPre, Just QualifiedPost) -> Same
99+ (QualifiedPost, Just QualifiedPre) -> Same
100+ _ -> Different []
101+ hsDocStringEq :: HsDocString -> GenericQ Diff
102+ hsDocStringEq str0 str1' =
103+ case cast str1' :: Maybe HsDocString of
104+ Nothing -> Different []
105+ Just str1 ->
106+ if splitDocString str0 == splitDocString str1
107+ then Same
108+ else Different []
109+ forLocated ::
110+ (Data e0, Data e1) =>
111+ GenLocated e0 e1 ->
112+ GenericQ Diff
113+ forLocated x@(L mspn _) y =
114+ maybe id appendSpan (cast mspn) (genericQuery x y)
115+ appendSpan :: SrcSpan -> Diff -> Diff
116+ appendSpan s (Different ss) | fresh && helpful = Different (s : ss)
117+ where
118+ fresh = not $ any (`isSubspanOf` s) ss
119+ helpful = isGoodSrcSpan s
120+ appendSpan _ d = d
121+
122+-- | Diff two texts and return the location they start to differ, alongside
123+-- with excerpts around that location.
124+diffText ::
125+ -- | Text before
126+ Text ->
127+ -- | Text after
128+ Text ->
129+ -- | Path to use to construct 'GHC.RealSrcLoc'
130+ FilePath ->
131+ Maybe (GHC.RealSrcLoc, Text, Text)
132+diffText left right fp =
133+ case go (0, 0, 0) left right of
134+ Nothing -> Nothing
135+ Just (row, col, loc) ->
136+ Just
137+ ( GHC.mkRealSrcLoc (GHC.mkFastString fp) row col,
138+ getSpan loc left,
139+ getSpan loc right
140+ )
141+ where
142+ go (row, col, loc) t1 t2 =
143+ case (T.uncons t1, T.uncons t2) of
144+ -- both text empty, all good
145+ (Nothing, Nothing) ->
146+ Nothing
147+ -- first chars are the same, adjust position and recurse
148+ (Just (c1, r1), Just (c2, r2))
149+ | c1 == c2 ->
150+ let (row', col', loc') =
151+ if c1 == '\n'
152+ then (row + 1, 0, loc + 1)
153+ else (row, col + 1, loc + 1)
154+ in go (row', col', loc') r1 r2
155+ -- something is different, return the position
156+ _ ->
157+ Just (row, col, loc)
158+ getSpan loc = T.take 20 . T.drop (loc - 10)
src/Ormolu/Exception.hs+63−43
@@ -1,53 +1,72 @@
11{-# LANGUAGE LambdaCase #-}
22
33-- | 'OrmoluException' type and surrounding definitions.
4−
54module Ormolu.Exception
6− ( OrmoluException (..)
7− , withPrettyOrmoluExceptions
5+ ( OrmoluException (..),
6+ withPrettyOrmoluExceptions,
87 )
98where
109
1110import Control.Exception
11+import Data.List.NonEmpty (NonEmpty (..))
12+import qualified Data.List.NonEmpty as NE
1213import Data.Text (Text)
13−import System.Exit (ExitCode (..), exitWith)
14−import System.IO
1514import qualified GHC
15+import Ormolu.Utils (showOutputable)
1616import qualified Outputable as GHC
17+import System.Exit (ExitCode (..), exitWith)
18+import System.IO
1719
1820-- | Ormolu exception representing all cases when Ormolu can fail.
19−
2021data OrmoluException
21− = OrmoluCppEnabled
22− -- ^ Ormolu does not work with source files that use CPP
23− | OrmoluParsingFailed GHC.SrcSpan String
24− -- ^ Parsing of original source code failed
25− | OrmoluOutputParsingFailed GHC.SrcSpan String
26− -- ^ Parsing of formatted source code failed
27− | OrmoluASTDiffers String Text
28− -- ^ Original and resulting ASTs differ, first argument is the original
29− -- source code, second argument is rendered source code
22+ = -- | Parsing of original source code failed
23+ OrmoluParsingFailed GHC.SrcSpan String
24+ | -- | Parsing of formatted source code failed
25+ OrmoluOutputParsingFailed GHC.SrcSpan String
26+ | -- | Original and resulting ASTs differ
27+ OrmoluASTDiffers FilePath [GHC.SrcSpan]
28+ | -- | Formatted source code is not idempotent
29+ OrmoluNonIdempotentOutput GHC.RealSrcLoc Text Text
30+ | -- | Some GHC options were not recognized
31+ OrmoluUnrecognizedOpts (NonEmpty String)
3032 deriving (Eq, Show)
3133
3234instance Exception OrmoluException where
3335 displayException = \case
34− OrmoluCppEnabled -> "CPP is not supported"
3536 OrmoluParsingFailed s e ->
36− showParsingErr "Parsing of source code failed:" s e
37+ showParsingErr "The GHC parser (in Haddock mode) failed:" s [e]
3738 OrmoluOutputParsingFailed s e ->
38− showParsingErr "Parsing of formatted code failed:" s e ++
39− "Please, consider reporting the bug."
40− OrmoluASTDiffers _ _ -> unlines
41− [ "AST of input and AST of formatted code differ."
42− , "Please, consider reporting the bug."
43− ]
39+ showParsingErr "Parsing of formatted code failed:" s [e]
40+ ++ "Please, consider reporting the bug.\n"
41+ OrmoluASTDiffers path ss ->
42+ unlines $
43+ [ "AST of input and AST of formatted code differ."
44+ ]
45+ ++ fmap
46+ withIndent
47+ ( case fmap (\s -> "at " ++ showOutputable s) ss of
48+ [] -> ["in " ++ path]
49+ xs -> xs
50+ )
51+ ++ ["Please, consider reporting the bug."]
52+ OrmoluNonIdempotentOutput loc left right ->
53+ showParsingErr
54+ "Formatting is not idempotent:"
55+ loc
56+ ["before: " ++ show left, "after: " ++ show right]
57+ ++ "Please, consider reporting the bug.\n"
58+ OrmoluUnrecognizedOpts opts ->
59+ unlines
60+ [ "The following GHC options were not recognized:",
61+ (withIndent . unwords . NE.toList) opts
62+ ]
4463
4564-- | Inside this wrapper 'OrmoluException' will be caught and displayed
4665-- nicely using 'displayException'.
47−
48−withPrettyOrmoluExceptions
49− :: IO a -- ^ Action that may throw the exception
50− -> IO a
66+withPrettyOrmoluExceptions ::
67+ -- | Action that may throw the exception
68+ IO a ->
69+ IO a
5170withPrettyOrmoluExceptions m = m `catch` h
5271 where
5372 h :: OrmoluException -> IO a
@@ -55,25 +74,26 @@ withPrettyOrmoluExceptions m = m `catch` h
5574 hPutStrLn stderr (displayException e)
5675 exitWith . ExitFailure $
5776 case e of
58− -- Error code 1 is for `error` or `notImplemented`
59− OrmoluCppEnabled -> 2
60− OrmoluParsingFailed _ _ -> 3
61− OrmoluOutputParsingFailed _ _ -> 4
62− OrmoluASTDiffers _ _ -> 5
77+ -- Error code 1 is for 'error' or 'notImplemented'
78+ -- 2 used to be for erroring out on CPP
79+ OrmoluParsingFailed {} -> 3
80+ OrmoluOutputParsingFailed {} -> 4
81+ OrmoluASTDiffers {} -> 5
82+ OrmoluNonIdempotentOutput {} -> 6
83+ OrmoluUnrecognizedOpts {} -> 7
6384
6485----------------------------------------------------------------------------
6586-- Helpers
6687
6788-- | Show a parse error.
89+showParsingErr :: GHC.Outputable a => String -> a -> [String] -> String
90+showParsingErr msg spn err =
91+ unlines $
92+ [ msg,
93+ withIndent (showOutputable spn)
94+ ]
95+ ++ map withIndent err
6896
69−showParsingErr :: String -> GHC.SrcSpan -> String -> String
70−showParsingErr msg spn err = unlines
71− [ msg
72− , showOutputable spn
73− , err
74− ]
75−
76−-- | Display something 'GHC.Outputable'.
77−
78−showOutputable :: GHC.Outputable o => o -> String
79−showOutputable = GHC.showSDocUnsafe . GHC.ppr
97+-- | Indent with 2 spaces for readability.
98+withIndent :: String -> String
99+withIndent txt = " " ++ txt
src/Ormolu/Imports.hs+176−61
@@ -1,87 +1,202 @@
11{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE RankNTypes #-}
3+{-# LANGUAGE RecordWildCards #-}
34
45-- | Manipulations on import lists.
5−
66module Ormolu.Imports
7− ( sortImports
7+ ( normalizeImports,
88 )
99where
1010
1111import Data.Bifunctor
12+import Data.Char (isAlphaNum)
1213import Data.Function (on)
13−import Data.List (sortBy)
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)
1418import GHC hiding (GhcPs, IE)
15−import HsExtension
16−import HsImpExp (IE (..))
17−import Ormolu.Utils (notImplemented)
18−
19−-- | Sort imports by module name. This also sorts explicit import lists for
20−-- each declaration.
21−
22−sortImports :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]
23−sortImports = sortBy compareIdecl . fmap (fmap sortImportLists)
19+import GHC.Hs.Extension
20+import GHC.Hs.ImpExp (IE (..))
21+import Ormolu.Utils (notImplemented, showOutputable)
22+
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))
2430 where
25− sortImportLists :: ImportDecl GhcPs -> ImportDecl GhcPs
26− sortImportLists decl =
27− decl { ideclHiding = second (fmap sortLies) <$> ideclHiding decl
28− }
29−
30−-- | Compare two @'LImportDecl' 'GhcPs'@ things.
31−
32−compareIdecl :: LImportDecl GhcPs -> LImportDecl GhcPs -> Ordering
33−compareIdecl (L _ m0) (L _ m1) =
34− if isPrelude n0
35− then GT
36− else if isPrelude n1
37− then LT
38− else n0 `compare` n1
31+ g (L l ImportDecl {..}) =
32+ L
33+ l
34+ ImportDecl
35+ { ideclHiding = second (fmap normalizeLies) <$> ideclHiding,
36+ ..
37+ }
38+ g _ = notImplemented "XImportDecl"
39+
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+ }
3991 where
40− n0 = unLoc (ideclName m0)
41− n1 = unLoc (ideclName m1)
42− isPrelude = (== "Prelude") . moduleNameString
43−
44−-- | Sort located import or export.
45−
46−sortLies :: [LIE GhcPs] -> [LIE GhcPs]
47−sortLies = sortBy (compareIE `on` unLoc) . fmap (fmap sortThings)
92+ isPrelude = moduleNameString moduleName == "Prelude"
93+ moduleName = unLoc ideclName
94+importId _ = notImplemented "XImportDecl"
4895
49−-- | Sort imports\/exports inside of 'IEThingWith'.
50−
51−sortThings :: IE GhcPs -> IE GhcPs
52−sortThings = \case
53− IEThingWith NoExt x w xs fl ->
54− IEThingWith NoExt x w (sortBy (compareIewn `on` unLoc) xs) fl
55− other -> other
56−
57−-- | Compare two located imports or exports.
58−
59−compareIE :: IE GhcPs -> IE GhcPs -> Ordering
60−compareIE = compareIewn `on` getIewn
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
151+
152+-- | A wrapper for @'IEWrappedName' 'RdrName'@ that allows us to define an
153+-- 'Ord' instance for it.
154+newtype IEWrappedNameOrd = IEWrappedNameOrd (IEWrappedName RdrName)
155+ deriving (Eq)
156+
157+instance Ord IEWrappedNameOrd where
158+ compare (IEWrappedNameOrd x) (IEWrappedNameOrd y) = compareIewn x y
61159
62160-- | Project @'IEWrappedName' 'RdrName'@ from @'IE' 'GhcPs'@.
63−
64−getIewn :: IE GhcPs -> IEWrappedName RdrName
161+getIewn :: IE GhcPs -> IEWrappedNameOrd
65162getIewn = \case
66− IEVar NoExt x -> unLoc x
67− IEThingAbs NoExt x -> unLoc x
68− IEThingAll NoExt x -> unLoc x
69− IEThingWith NoExt x _ _ _ -> unLoc x
70− IEModuleContents NoExt _ -> notImplemented "IEModuleContents"
71− IEGroup NoExt _ _ -> notImplemented "IEGroup"
72− IEDoc NoExt _ -> notImplemented "IEDoc"
73− IEDocNamed NoExt _ -> notImplemented "IEDocNamed"
74− XIE NoExt -> notImplemented "XIE"
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
75176
76177-- | Compare two @'IEWrapppedName' 'RdrName'@ things.
77−
78178compareIewn :: IEWrappedName RdrName -> IEWrappedName RdrName -> Ordering
79−compareIewn (IEName x) (IEName y) = unLoc x `compare` unLoc y
179+compareIewn (IEName x) (IEName y) = unLoc x `compareRdrName` unLoc y
80180compareIewn (IEName _) (IEPattern _) = LT
81181compareIewn (IEName _) (IEType _) = LT
82182compareIewn (IEPattern _) (IEName _) = GT
83−compareIewn (IEPattern x) (IEPattern y) = unLoc x `compare` unLoc y
183+compareIewn (IEPattern x) (IEPattern y) = unLoc x `compareRdrName` unLoc y
84184compareIewn (IEPattern _) (IEType _) = LT
85185compareIewn (IEType _) (IEName _) = GT
86186compareIewn (IEType _) (IEPattern _) = GT
87−compareIewn (IEType x) (IEType y) = unLoc x `compare` unLoc y
187+compareIewn (IEType x) (IEType y) = unLoc x `compareRdrName` unLoc y
188+
189+compareRdrName :: RdrName -> RdrName -> Ordering
190+compareRdrName x y =
191+ case (getNameStr x, getNameStr y) of
192+ ([], []) -> EQ
193+ ((_ : _), []) -> GT
194+ ([], (_ : _)) -> LT
195+ ((x' : _), (y' : _)) ->
196+ case (isAlphaNum x', isAlphaNum y') of
197+ (False, False) -> x `compare` y
198+ (True, False) -> LT
199+ (False, True) -> GT
200+ (True, True) -> x `compare` y
201+ where
202+ getNameStr = showOutputable . rdrNameOcc
src/Ormolu/Parser.hs+193−127
@@ -1,153 +1,219 @@
1+{-# LANGUAGE LambdaCase #-}
12{-# LANGUAGE RecordWildCards #-}
3+{-# OPTIONS_GHC -fno-warn-orphans #-}
24
35-- | Parser for Haskell source code.
4−
56module Ormolu.Parser
6− ( parseModule
7+ ( parseModule,
8+ manualExts,
79 )
810where
911
12+import Bag (bagToList)
13+import qualified CmdLineParser as GHC
1014import Control.Exception
11−import Control.Monad
1215import Control.Monad.IO.Class
13−import Data.List (isPrefixOf)
14−import Data.Maybe (catMaybes)
15−import GHC hiding (IE, parseModule, parser)
16−import GHC.LanguageExtensions.Type (Extension (Cpp))
17−import GHC.Paths (libdir)
18−import Ormolu.Anns
19−import Ormolu.CommentStream
20−import Ormolu.Config
21−import Ormolu.Exception
22−import qualified CmdLineParser as GHC
23−import qualified DynFlags as GHC
16+import qualified Data.List as L
17+import qualified Data.List.NonEmpty as NE
18+import Data.Ord (Down (Down))
19+import qualified Data.Text as T
20+import DynFlags as GHC
21+import ErrUtils (Severity (..), errMsgSeverity, errMsgSpan)
2422import qualified FastString as GHC
23+import GHC hiding (IE, UnicodeSyntax)
24+import GHC.DynFlags (baseDynFlags)
25+import GHC.LanguageExtensions.Type (Extension (..))
2526import qualified HeaderInfo as GHC
27+import qualified HscTypes as GHC
2628import qualified Lexer as GHC
27−import qualified Outputable as GHC
29+import Ormolu.Config
30+import Ormolu.Exception
31+import Ormolu.Parser.Anns
32+import Ormolu.Parser.CommentStream
33+import Ormolu.Parser.Result
34+import Ormolu.Processing.Preprocess (preprocess)
35+import Ormolu.Utils (incSpanLine, removeIndentation)
36+import qualified Panic as GHC
2837import qualified Parser as GHC
29−import qualified SrcLoc as GHC
3038import qualified StringBuffer as GHC
3139
3240-- | Parse a complete module from string.
33−
34−parseModule
35− :: MonadIO m
36− => [DynOption] -- ^ Dynamic options that affect parsing
37− -> FilePath -- ^ File name (only for source location annotations)
38− -> String -- ^ Input for parser
39− -> m ( [GHC.Warn]
40− , Either (SrcSpan, String)
41− (CommentStream, Anns, ParsedSource)
42− )
43−parseModule dynOpts path input' = liftIO $ do
44− let (input, extraComments) = stripLinePragmas input'
45− (ws, dynFlags) <- ghcWrapper $ do
46− dynFlags0 <- initDynFlagsPure path input
47− (dynFlags1, _, ws) <-
48− GHC.parseDynamicFilePragma dynFlags0 (dynOptionToLocatedStr <$> dynOpts)
49− return (ws, dynFlags1)
50− -- NOTE It's better to throw this outside of 'ghcWrapper' because
51− -- otherwise the exception will be wrapped as a GHC panic, which we don't
52− -- want.
53− when (GHC.xopt Cpp dynFlags) $
54− throwIO OrmoluCppEnabled
55− let r = case runParser GHC.parseModule dynFlags path input of
56− GHC.PFailed _ ss m ->
57− Left (ss, GHC.showSDoc dynFlags m)
58− GHC.POk pstate pmod ->
59− Right ( mkCommentStream extraComments pstate
60− , mkAnns pstate
61− , pmod
62− )
63− return (ws, r)
64−
65−----------------------------------------------------------------------------
66−-- Helpers (taken from ghc-exactprint)
67−
68−-- | Requires GhcMonad constraint because there is no pure variant of
69−-- 'parseDynamicFilePragma'. Yet, in constrast to 'initDynFlags', it does
70−-- not (try to) read the file at filepath, but solely depends on the module
71−-- source in the input string.
72−--
73−-- Passes "-hide-all-packages" to the GHC API to prevent parsing of package
74−-- environment files. However this only works if there is no invocation of
75−-- 'setSessionDynFlags' before calling 'initDynFlagsPure'. See GHC tickets
76−-- #15513, #15541.
77−
78−initDynFlagsPure
79− :: GHC.GhcMonad m
80− => FilePath -- ^ Module path
81− -> String -- ^ Module contents
82− -> m GHC.DynFlags -- ^ Dynamic flags for that module
83−initDynFlagsPure fp input = do
84− -- I was told we could get away with using the 'unsafeGlobalDynFlags'. as
85− -- long as 'parseDynamicFilePragma' is impure there seems to be no reason
86− -- to use it.
87− dflags0 <- GHC.getSessionDynFlags
88− let pragmaInfo = GHC.getOptions dflags0 (GHC.stringToStringBuffer input) fp
89− (dflags1, _, _) <- GHC.parseDynamicFilePragma dflags0 pragmaInfo
90− -- Turn this on last to avoid T10942
91− let dflags2 = dflags1 `GHC.gopt_set` GHC.Opt_KeepRawTokenStream
92− -- Prevent parsing of .ghc.environment.* "package environment files"
93− (dflags3, _, _) <- GHC.parseDynamicFlagsCmdLine
94− dflags2
95− [GHC.noLoc "-hide-all-packages"]
96− _ <- GHC.setSessionDynFlags dflags3
97− return dflags3
98−
99−-- | Default runner of 'GHC.Ghc' action in 'IO'.
100−
101−ghcWrapper :: GHC.Ghc a -> IO a
102−ghcWrapper
103− = GHC.defaultErrorHandler GHC.defaultFatalMessager GHC.defaultFlushOut
104− . GHC.runGhc (Just libdir)
41+parseModule ::
42+ MonadIO m =>
43+ -- | Ormolu configuration
44+ Config RegionDeltas ->
45+ -- | File name (only for source location annotations)
46+ FilePath ->
47+ -- | Input for parser
48+ String ->
49+ m
50+ ( [GHC.Warn],
51+ Either (SrcSpan, String) ParseResult
52+ )
53+parseModule Config {..} path rawInput = liftIO $ do
54+ let (literalPrefix, indentedInput, literalSuffix, extraComments) =
55+ preprocess path rawInput cfgRegion
56+ (input, indent) = removeIndentation indentedInput
57+ -- It's important that 'setDefaultExts' is done before
58+ -- 'parsePragmasIntoDynFlags', because otherwise we might enable an
59+ -- extension that was explicitly disabled in the file.
60+ let baseFlags =
61+ GHC.setGeneralFlag'
62+ GHC.Opt_Haddock
63+ (setDefaultExts baseDynFlags)
64+ extraOpts = dynOptionToLocatedStr <$> cfgDynOptions
65+ (warnings, dynFlags) <-
66+ parsePragmasIntoDynFlags baseFlags extraOpts path rawInput >>= \case
67+ Right res -> pure res
68+ Left err ->
69+ let loc =
70+ mkSrcSpan
71+ (mkSrcLoc (GHC.mkFastString path) 1 1)
72+ (mkSrcLoc (GHC.mkFastString path) 1 1)
73+ in throwIO (OrmoluParsingFailed loc err)
74+ let useRecordDot =
75+ "record-dot-preprocessor" == pgm_F dynFlags
76+ || any
77+ (("RecordDotPreprocessor" ==) . moduleNameString)
78+ (pluginModNames dynFlags)
79+ pStateErrors = \pstate ->
80+ let errs = bagToList $ GHC.getErrorMessages pstate dynFlags
81+ fixupErrSpan = incSpanLine (regionPrefixLength cfgRegion)
82+ in case L.sortOn (Down . SeverityOrd . errMsgSeverity) errs of
83+ [] -> Nothing
84+ err : _ ->
85+ -- Show instance returns a short error message
86+ Just (fixupErrSpan (errMsgSpan err), show err)
87+ r = case runParser GHC.parseModule dynFlags path input of
88+ GHC.PFailed pstate ->
89+ case pStateErrors pstate of
90+ Just err -> Left err
91+ Nothing -> error "PFailed does not have an error"
92+ GHC.POk pstate (L _ hsModule) ->
93+ case pStateErrors pstate of
94+ -- Some parse errors (pattern/arrow syntax in expr context)
95+ -- do not cause a parse error, but they are replaced with "_"
96+ -- by the parser and the modified AST is propagated to the
97+ -- later stages; but we fail in those cases.
98+ Just err -> Left err
99+ Nothing ->
100+ let (stackHeader, shebangs, pragmas, comments) =
101+ mkCommentStream input extraComments pstate
102+ in Right
103+ ParseResult
104+ { prParsedSource = hsModule,
105+ prAnns = mkAnns pstate,
106+ prStackHeader = stackHeader,
107+ prShebangs = shebangs,
108+ prPragmas = pragmas,
109+ prCommentStream = comments,
110+ prUseRecordDot = useRecordDot,
111+ prImportQualifiedPost =
112+ GHC.xopt ImportQualifiedPost dynFlags,
113+ prLiteralPrefix = T.pack literalPrefix,
114+ prLiteralSuffix = T.pack literalSuffix,
115+ prIndent = indent
116+ }
117+ return (warnings, r)
118+
119+-- | Enable all language extensions that we think should be enabled by
120+-- default for ease of use.
121+setDefaultExts :: DynFlags -> DynFlags
122+setDefaultExts flags = L.foldl' xopt_set flags autoExts
123+ where
124+ autoExts = allExts L.\\ manualExts
125+ allExts = [minBound .. maxBound]
126+
127+-- | Extensions that are not enabled automatically and should be activated
128+-- by user.
129+manualExts :: [Extension]
130+manualExts =
131+ [ Arrows, -- steals proc
132+ Cpp, -- forbidden
133+ BangPatterns, -- makes certain patterns with ! fail
134+ PatternSynonyms, -- steals the pattern keyword
135+ RecursiveDo, -- steals the rec keyword
136+ StaticPointers, -- steals static keyword
137+ TransformListComp, -- steals the group keyword
138+ UnboxedTuples, -- breaks (#) lens operator
139+ MagicHash, -- screws {-# these things #-}
140+ TypeApplications, -- steals (@) operator on some cases
141+ AlternativeLayoutRule,
142+ AlternativeLayoutRuleTransitional,
143+ MonadComprehensions,
144+ UnboxedSums,
145+ UnicodeSyntax, -- gives special meanings to operators like (→)
146+ TemplateHaskellQuotes, -- enables TH subset of quasi-quotes, this
147+ -- apparently interferes with QuasiQuotes in
148+ -- weird ways
149+ ImportQualifiedPost -- affects how Ormolu renders imports, so the
150+ -- decision of enabling this style is left to the user
151+ ]
105152
106153-- | Run a 'GHC.P' computation.
107−
108−runParser
109− :: GHC.P a -- ^ Computation to run
110− -> GHC.DynFlags -- ^ Dynamic flags
111− -> FilePath -- ^ Module path
112− -> String -- ^ Module contents
113− -> GHC.ParseResult a -- ^ Parse result
154+runParser ::
155+ -- | Computation to run
156+ GHC.P a ->
157+ -- | Dynamic flags
158+ GHC.DynFlags ->
159+ -- | Module path
160+ FilePath ->
161+ -- | Module contents
162+ String ->
163+ -- | Parse result
164+ GHC.ParseResult a
114165runParser parser flags filename input = GHC.unP parser parseState
115166 where
116167 location = GHC.mkRealSrcLoc (GHC.mkFastString filename) 1 1
117168 buffer = GHC.stringToStringBuffer input
118169 parseState = GHC.mkPState flags buffer location
119170
120−-- | Remove GHC style line pragams (@{-# LINE .. #-}@) and convert them into
121−-- comments.
171+-- | Wrap GHC's 'Severity' to add 'Ord' instance.
172+newtype SeverityOrd = SeverityOrd Severity
173+
174+instance Eq SeverityOrd where
175+ s1 == s2 = compare s1 s2 == EQ
176+
177+instance Ord SeverityOrd where
178+ compare (SeverityOrd s1) (SeverityOrd s2) =
179+ compare (f s1) (f s2)
180+ where
181+ f :: Severity -> Int
182+ f SevOutput = 1
183+ f SevFatal = 2
184+ f SevInteractive = 3
185+ f SevDump = 4
186+ f SevInfo = 5
187+ f SevWarning = 6
188+ f SevError = 7
122189
123−stripLinePragmas :: String -> (String, [Located String])
124−stripLinePragmas = unlines' . unzip . findLines . lines
190+----------------------------------------------------------------------------
191+-- Helpers taken from HLint
192+
193+parsePragmasIntoDynFlags ::
194+ -- | Pre-set 'DynFlags'
195+ DynFlags ->
196+ -- | Extra options (provided by user)
197+ [Located String] ->
198+ -- | File name (only for source location annotations)
199+ FilePath ->
200+ -- | Input for parser
201+ String ->
202+ IO (Either String ([GHC.Warn], DynFlags))
203+parsePragmasIntoDynFlags flags extraOpts filepath str =
204+ catchErrors $ do
205+ let opts = GHC.getOptions flags (GHC.stringToStringBuffer str) filepath
206+ (flags', leftovers, warnings) <-
207+ parseDynamicFilePragma flags (opts <> extraOpts)
208+ case NE.nonEmpty leftovers of
209+ Nothing -> return ()
210+ Just unrecognizedOpts ->
211+ throwIO (OrmoluUnrecognizedOpts (unLoc <$> unrecognizedOpts))
212+ let flags'' = flags' `gopt_set` Opt_KeepRawTokenStream
213+ return $ Right (warnings, flags'')
125214 where
126− unlines' (a, b) = (unlines a, catMaybes b)
127−
128−findLines :: [String] -> [(String, Maybe (Located String))]
129−findLines = zipWith checkLine [1..]
130−
131−checkLine :: Int -> String -> (String, Maybe (Located String))
132−checkLine line s
133− | "{-# LINE" `isPrefixOf` s =
134− let (pragma, res) = getPragma s
135− size = length pragma
136− mSrcLoc = mkSrcLoc (GHC.mkFastString "LINE")
137− ss = mkSrcSpan (mSrcLoc line 1) (mSrcLoc line (size+1))
138− in (res, Just $ L ss pragma)
139− -- Deal with shebang/cpp directives too
140− -- x | "#" `isPrefixOf` s = ("",Just $ Comment ((line, 1), (line, length s)) s)
141− | "#!" `isPrefixOf` s =
142− let mSrcLoc = mkSrcLoc (GHC.mkFastString "SHEBANG")
143− ss = mkSrcSpan (mSrcLoc line 1) (mSrcLoc line (length s))
144− in ("",Just $ L ss s)
145− | otherwise = (s, Nothing)
146−
147−getPragma :: String -> (String, String)
148−getPragma [] = error "Ormolu.Parser.getPragma: input must not be empty"
149−getPragma s@(x:xs)
150− | "#-}" `isPrefixOf` s = ("#-}", " " ++ drop 3 s)
151− | otherwise =
152− let (prag, remline) = getPragma xs
153− in (x:prag, ' ':remline)
215+ catchErrors act =
216+ GHC.handleGhcException
217+ reportErr
218+ (GHC.handleSourceError reportErr act)
219+ reportErr e = return $ Left (show e)
src/Ormolu/Anns.hs → src/Ormolu/Parser/Anns.hsrenamed+19−21
@@ -1,37 +1,34 @@
11-- | Ormolu-specific representation of GHC annotations.
2−
3−module Ormolu.Anns
4− ( Anns (..)
5− , emptyAnns
6− , mkAnns
7− , lookupAnns
2+module Ormolu.Parser.Anns
3+ ( Anns (..),
4+ emptyAnns,
5+ mkAnns,
6+ lookupAnns,
87 )
98where
109
1110import Data.Map.Strict (Map)
12−import Data.Maybe (mapMaybe)
13−import SrcLoc
1411import qualified Data.Map.Strict as M
12+import Data.Maybe (mapMaybe)
1513import qualified GHC
1614import qualified Lexer as GHC
15+import SrcLoc
1716
1817-- | Ormolu-specific representation of GHC annotations.
19−
2018newtype Anns = Anns (Map RealSrcSpan [GHC.AnnKeywordId])
2119 deriving (Eq)
2220
2321-- | Empty 'Anns'.
24−
2522emptyAnns :: Anns
2623emptyAnns = Anns M.empty
2724
2825-- | Create 'Anns' from 'GHC.PState'.
29−
30−mkAnns
31− :: GHC.PState
32− -> Anns
33−mkAnns pstate = Anns $
34− M.fromListWith (++) (mapMaybe f (GHC.annotations pstate))
26+mkAnns ::
27+ GHC.PState ->
28+ Anns
29+mkAnns pstate =
30+ Anns $
31+ M.fromListWith (++) (mapMaybe f (GHC.annotations pstate))
3532 where
3633 f ((spn, kid), _) =
3734 case spn of
@@ -39,10 +36,11 @@ mkAnns pstate = Anns $
3936 UnhelpfulSpan _ -> Nothing
4037
4138-- | Lookup 'GHC.AnnKeywordId's corresponding to a given 'SrcSpan'.
42−
43−lookupAnns
44− :: SrcSpan -- ^ Span to lookup with
45− -> Anns -- ^ Collection of annotations
46− -> [GHC.AnnKeywordId]
39+lookupAnns ::
40+ -- | Span to lookup with
41+ SrcSpan ->
42+ -- | Collection of annotations
43+ Anns ->
44+ [GHC.AnnKeywordId]
4745lookupAnns (RealSrcSpan rspn) (Anns m) = M.findWithDefault [] rspn m
4846lookupAnns (UnhelpfulSpan _) _ = []
src/Ormolu/Parser/CommentStream.hsnew file+226
@@ -0,0 +1,226 @@
1+{-# LANGUAGE DeriveDataTypeable #-}
2+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3+{-# LANGUAGE LambdaCase #-}
4+
5+-- | Functions for working with comment stream.
6+module Ormolu.Parser.CommentStream
7+ ( -- * Comment stream
8+ CommentStream (..),
9+ mkCommentStream,
10+ showCommentStream,
11+
12+ -- * Comment
13+ Comment (..),
14+ unComment,
15+ hasAtomsBefore,
16+ isMultilineComment,
17+ )
18+where
19+
20+import Data.Char (isSpace)
21+import Data.Data (Data)
22+import qualified Data.List as L
23+import Data.List.NonEmpty (NonEmpty (..))
24+import qualified Data.List.NonEmpty as NE
25+import Data.Maybe (mapMaybe)
26+import qualified GHC
27+import qualified Lexer as GHC
28+import Ormolu.Parser.Pragma
29+import Ormolu.Parser.Shebang
30+import Ormolu.Processing.Common
31+import Ormolu.Utils (onTheSameLine, showOutputable)
32+import SrcLoc
33+
34+----------------------------------------------------------------------------
35+-- Comment stream
36+
37+-- | A stream of 'RealLocated' 'Comment's in ascending order with respect to
38+-- beginning of corresponding spans.
39+newtype CommentStream = CommentStream [RealLocated Comment]
40+ deriving (Eq, Data, Semigroup, Monoid)
41+
42+-- | Create 'CommentStream' from 'GHC.PState'. The pragmas and shebangs are
43+-- removed from the 'CommentStream'. Shebangs are only extracted from the
44+-- comments that come from the first argument.
45+mkCommentStream ::
46+ -- | Original input
47+ String ->
48+ -- | Extra comments to include
49+ [Located String] ->
50+ -- | Parser state to use for comment extraction
51+ 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,
61+ pragmas,
62+ CommentStream comments
63+ )
64+ where
65+ (comments, pragmas) = extractPragmas input rawComments1
66+ (rawComments1, mstackHeader) = extractStackHeader rawComments0
67+ rawComments0 =
68+ L.sortOn (realSrcSpanStart . getRealSrcSpan) . mapMaybe toRealSpan $
69+ otherExtraComments
70+ ++ mapMaybe (liftMaybe . fmap unAnnotationComment) (GHC.comment_q pstate)
71+ ++ concatMap
72+ (mapMaybe (liftMaybe . fmap unAnnotationComment) . snd)
73+ (GHC.annotations_comments pstate)
74+ (shebangs, otherExtraComments) = extractShebangs extraComments
75+
76+-- | Pretty-print a 'CommentStream'.
77+showCommentStream :: CommentStream -> String
78+showCommentStream (CommentStream xs) =
79+ unlines $
80+ showComment <$> xs
81+ where
82+ showComment (GHC.L l str) = showOutputable l ++ " " ++ show str
83+
84+----------------------------------------------------------------------------
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)
93+
94+-- | Normalize comment string. Sometimes one multi-line comment is turned
95+-- into several lines for subsequent outputting with correct indentation for
96+-- 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)
105+ where
106+ comment =
107+ L l . Comment atomsBefore . removeConseqBlanks . fmap dropTrailing $
108+ if "{-" `L.isPrefixOf` s
109+ then case NE.nonEmpty (lines s) of
110+ Nothing -> s :| []
111+ Just (x :| xs) ->
112+ let getIndent y =
113+ if all isSpace y || y == endDisabling
114+ then startIndent
115+ else length (takeWhile isSpace y)
116+ n = minimum (startIndent : fmap getIndent xs)
117+ removeIndent y =
118+ if y == endDisabling
119+ then y
120+ else drop n y
121+ in x :| (removeIndent <$> xs)
122+ else s :| []
123+ (atomsBefore, ls') =
124+ case dropWhile ((< commentLine) . fst) ls of
125+ [] -> (False, [])
126+ ((_, i) : ls'') ->
127+ case take 2 (dropWhile isSpace i) of
128+ "--" -> (False, ls'')
129+ "{-" -> (False, ls'')
130+ _ -> (True, ls'')
131+ dropTrailing = L.dropWhileEnd isSpace
132+ startIndent = srcSpanStartCol l - 1
133+ commentLine = srcSpanStartLine l
134+
135+-- | Get a collection of lines from a 'Comment'.
136+unComment :: Comment -> NonEmpty String
137+unComment (Comment _ xs) = xs
138+
139+-- | Check whether the 'Comment' had some non-whitespace atoms in front of
140+-- it in the original input.
141+hasAtomsBefore :: Comment -> Bool
142+hasAtomsBefore (Comment atomsBefore _) = atomsBefore
143+
144+-- | Is this comment multiline-style?
145+isMultilineComment :: Comment -> Bool
146+isMultilineComment (Comment _ (x :| _)) = "{-" `L.isPrefixOf` x
147+
148+----------------------------------------------------------------------------
149+-- Helpers
150+
151+-- | Detect and extract stack header if it is present.
152+extractStackHeader ::
153+ -- | Comment stream to analyze
154+ [RealLocated String] ->
155+ ([RealLocated String], Maybe (RealLocated Comment))
156+extractStackHeader = \case
157+ [] -> ([], Nothing)
158+ (x : xs) ->
159+ let comment = snd (mkComment [] x)
160+ in if isStackHeader (unRealSrcSpan comment)
161+ then (xs, Just comment)
162+ else (x : xs, Nothing)
163+ where
164+ isStackHeader (Comment _ (x :| _)) =
165+ "stack" `L.isPrefixOf` dropWhile isSpace (drop 2 x)
166+
167+-- | Extract pragmas and their associated comments.
168+extractPragmas ::
169+ -- | Input
170+ String ->
171+ -- | Comment stream to analyze
172+ [RealLocated String] ->
173+ ([RealLocated Comment], [([RealLocated Comment], Pragma)])
174+extractPragmas input = go initialLs id id
175+ where
176+ initialLs = zip [1 ..] (lines input)
177+ go ls csSoFar pragmasSoFar = \case
178+ [] -> (csSoFar [], pragmasSoFar [])
179+ (x : xs) ->
180+ case parsePragma (unRealSrcSpan x) of
181+ Nothing ->
182+ let (ls', x') = mkComment ls x
183+ in go ls' (csSoFar . (x' :)) pragmasSoFar xs
184+ Just pragma ->
185+ let combined ys = (csSoFar ys, pragma)
186+ go' ls' ys rest = go ls' id (pragmasSoFar . (combined ys :)) rest
187+ in case xs of
188+ [] -> go' ls [] xs
189+ (y : ys) ->
190+ let (ls', y') = mkComment ls y
191+ in if onTheSameLine
192+ (RealSrcSpan (getRealSrcSpan x))
193+ (RealSrcSpan (getRealSrcSpan y))
194+ then go' ls' [y'] ys
195+ else go' ls [] xs
196+
197+-- | Get a 'String' from 'GHC.AnnotationComment'.
198+unAnnotationComment :: GHC.AnnotationComment -> Maybe String
199+unAnnotationComment = \case
200+ GHC.AnnDocCommentNext _ -> Nothing -- @-- |@
201+ GHC.AnnDocCommentPrev _ -> Nothing -- @-- ^@
202+ GHC.AnnDocCommentNamed _ -> Nothing -- @-- $@
203+ GHC.AnnDocSection _ _ -> Nothing -- @-- *@
204+ GHC.AnnDocOptions s -> Just s
205+ GHC.AnnLineComment s -> Just s
206+ GHC.AnnBlockComment s -> Just s
207+
208+liftMaybe :: Located (Maybe a) -> Maybe (Located a)
209+liftMaybe = \case
210+ L _ Nothing -> Nothing
211+ L l (Just a) -> Just (L l a)
212+
213+toRealSpan :: Located a -> Maybe (RealLocated a)
214+toRealSpan (L (RealSrcSpan l) a) = Just (L l a)
215+toRealSpan _ = Nothing
216+
217+-- | Remove consecutive blank lines.
218+removeConseqBlanks :: NonEmpty String -> NonEmpty String
219+removeConseqBlanks (x :| xs) = x :| go (null x) id xs
220+ where
221+ go seenBlank acc = \case
222+ [] -> acc []
223+ (y : ys) ->
224+ if seenBlank && null y
225+ then go True acc ys
226+ else go (null y) (acc . (y :)) ys
src/Ormolu/Parser/Pragma.hsnew file+89
@@ -0,0 +1,89 @@
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+
4+-- | A module for parsing of pragmas from comments.
5+module Ormolu.Parser.Pragma
6+ ( Pragma (..),
7+ parsePragma,
8+ )
9+where
10+
11+import Control.Monad
12+import Data.Char (isSpace, toLower)
13+import qualified Data.List as L
14+import qualified EnumSet as ES
15+import FastString (mkFastString, unpackFS)
16+import qualified Lexer as L
17+import Module (ComponentId (..), newSimpleUnitId)
18+import SrcLoc
19+import StringBuffer
20+
21+-- | Ormolu's representation of pragmas.
22+data Pragma
23+ = -- | Language pragma
24+ PragmaLanguage [String]
25+ | -- | GHC options pragma
26+ PragmaOptionsGHC String
27+ | -- | Haddock options pragma
28+ PragmaOptionsHaddock String
29+ deriving (Show, Eq)
30+
31+-- | Extract a pragma from a comment if possible, or return 'Nothing'
32+-- otherwise.
33+parsePragma ::
34+ -- | Comment to try to parse
35+ String ->
36+ Maybe Pragma
37+parsePragma input = do
38+ inputNoPrefix <- L.stripPrefix "{-#" input
39+ guard ("#-}" `L.isSuffixOf` input)
40+ let contents = take (length inputNoPrefix - 3) inputNoPrefix
41+ (pragmaName, cs) = (break isSpace . dropWhile isSpace) contents
42+ case toLower <$> pragmaName of
43+ "language" -> PragmaLanguage <$> parseExtensions cs
44+ "options_ghc" -> Just $ PragmaOptionsGHC (trimSpaces cs)
45+ "options_haddock" -> Just $ PragmaOptionsHaddock (trimSpaces cs)
46+ _ -> Nothing
47+ where
48+ trimSpaces :: String -> String
49+ trimSpaces = L.dropWhileEnd isSpace . dropWhile isSpace
50+
51+-- | Assuming the input consists of a series of tokens from a language
52+-- pragma, return the set of enabled extensions.
53+parseExtensions :: String -> Maybe [String]
54+parseExtensions str = tokenize str >>= go
55+ where
56+ go = \case
57+ [L.ITconid ext] -> return [unpackFS ext]
58+ (L.ITconid ext : L.ITcomma : xs) -> (unpackFS ext :) <$> go xs
59+ _ -> Nothing
60+
61+-- | Tokenize a given input using GHC's lexer.
62+tokenize :: String -> Maybe [L.Token]
63+tokenize input =
64+ case L.unP pLexer parseState of
65+ L.PFailed {} -> Nothing
66+ L.POk _ x -> Just x
67+ where
68+ location = mkRealSrcLoc (mkFastString "") 1 1
69+ buffer = stringToStringBuffer input
70+ parseState = L.mkPStatePure parserFlags buffer location
71+ parserFlags =
72+ L.mkParserFlags'
73+ ES.empty
74+ ES.empty
75+ (newSimpleUnitId (ComponentId (mkFastString "")))
76+ True
77+ True
78+ True
79+ True
80+
81+-- | Haskell lexer.
82+pLexer :: L.P [L.Token]
83+pLexer = go
84+ where
85+ go = do
86+ r <- L.lexer False return
87+ case unLoc r of
88+ L.ITeof -> return []
89+ x -> (x :) <$> go
src/Ormolu/Parser/Result.hsnew file+51
@@ -0,0 +1,51 @@
1+{-# LANGUAGE RecordWildCards #-}
2+
3+-- | A type for result of parsing.
4+module Ormolu.Parser.Result
5+ ( ParseResult (..),
6+ prettyPrintParseResult,
7+ )
8+where
9+
10+import Data.Text (Text)
11+import GHC
12+import Ormolu.Parser.Anns
13+import Ormolu.Parser.CommentStream
14+import Ormolu.Parser.Pragma (Pragma)
15+import Ormolu.Parser.Shebang (Shebang)
16+
17+-- | 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+ }
42+
43+-- | Pretty-print a 'ParseResult'.
44+prettyPrintParseResult :: ParseResult -> String
45+prettyPrintParseResult ParseResult {..} =
46+ unlines
47+ [ "parse result:",
48+ " comment stream:",
49+ showCommentStream prCommentStream
50+ -- XXX extend as needed
51+ ]
src/Ormolu/Parser/Shebang.hsnew file+27
@@ -0,0 +1,27 @@
1+{-# LANGUAGE DeriveDataTypeable #-}
2+
3+-- | A module for dealing with shebangs.
4+module Ormolu.Parser.Shebang
5+ ( Shebang (..),
6+ extractShebangs,
7+ isShebang,
8+ )
9+where
10+
11+import Data.Data (Data)
12+import qualified Data.List as L
13+import SrcLoc
14+
15+-- | A wrapper for a shebang.
16+newtype Shebang = Shebang (Located String)
17+ deriving (Eq, Data)
18+
19+-- | Extract shebangs from the beginning of a comment stream.
20+extractShebangs :: [Located String] -> ([Shebang], [Located String])
21+extractShebangs comments = (Shebang <$> shebangs, rest)
22+ where
23+ (shebangs, rest) = span (isShebang . unLoc) comments
24+
25+-- | Return 'True' if given 'String' is a shebang.
26+isShebang :: String -> Bool
27+isShebang str = "#!" `L.isPrefixOf` str
src/Ormolu/Printer.hs+27−18
@@ -1,29 +1,38 @@
1−{-# LANGUAGE LambdaCase #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
1+{-# LANGUAGE RecordWildCards #-}
42
53-- | Pretty-printer for Haskell AST.
6−
74module Ormolu.Printer
8− ( printModule
5+ ( printModule,
96 )
107where
118
129import Data.Text (Text)
13−import GHC
14−import Ormolu.Anns
15−import Ormolu.CommentStream
10+import Ormolu.Parser.Result
1611import Ormolu.Printer.Combinators
1712import Ormolu.Printer.Meat.Module
18−import Ormolu.SpanStream
13+import Ormolu.Printer.SpanStream
14+import Ormolu.Processing.Postprocess (postprocess)
1915
2016-- | Render a module.
21−
22−printModule
23− :: Bool -- ^ Whether to trace debugging information
24− -> CommentStream -- ^ Comment stream
25− -> Anns -- ^ Annotations
26− -> ParsedSource -- ^ Parsed source
27− -> Text -- ^ Resulting rendition
28−printModule debugOn cstream anns src =
29− runR debugOn (p_hsModule src) (mkSpanStream src) cstream anns
17+printModule ::
18+ -- | Result of parsing
19+ ParseResult ->
20+ -- | Resulting rendition
21+ Text
22+printModule 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
src/Ormolu/Printer/Combinators.hs+206−217
@@ -1,146 +1,142 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE FlexibleContexts #-}
2+{-# LANGUAGE GADTs #-}
3+{-# LANGUAGE LambdaCase #-}
24{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
45
56-- | Printing combinators. The definitions here are presented in such an
67-- order so you can just go through the Haddocks and by the end of the file
78-- you should have a pretty good idea how to program rendering logic.
8−
99module Ormolu.Printer.Combinators
1010 ( -- * The 'R' monad
11− R
12− , runR
11+ R,
12+ runR,
13+ getAnns,
14+ getEnclosingSpan,
15+
1316 -- * Combinators
17+
1418 -- ** Basic
15− , txt
16− , atom
17− , newline
18− , inci
19− , located
20− , locatedVia
21− , located'
22− , switchLayout
23− , vlayout
24− , breakpoint
25− , breakpoint'
19+ txt,
20+ atom,
21+ space,
22+ newline,
23+ inci,
24+ inciIf,
25+ located,
26+ located',
27+ switchLayout,
28+ Layout (..),
29+ vlayout,
30+ getLayout,
31+ breakpoint,
32+ breakpoint',
33+
2634 -- ** Formatting lists
27− , velt
28− , velt'
29− , withSep
30− , spaceSep
31− , newlineSep
35+ sep,
36+ sepSemi,
37+ canUseBraces,
38+ useBraces,
39+ dontUseBraces,
40+
3241 -- ** Wrapping
33− , sitcc
34− , line
35− , backticks
36− , braces
37− , brackets
38− , bracketsPar
39− , parens
40− , parensHash
41− , pragmaBraces
42− , pragma
42+ BracketStyle (..),
43+ sitcc,
44+ backticks,
45+ banana,
46+ braces,
47+ brackets,
48+ parens,
49+ parensHash,
50+ pragmaBraces,
51+ pragma,
52+
4353 -- ** Literals
44− , comma
45− , space
54+ comma,
55+ commaDel,
56+ equals,
57+
58+ -- ** Stateful markers
59+ SpanMark (..),
60+ spanMarkSpan,
61+ HaddockStyle (..),
62+ setSpanMark,
63+ getSpanMark,
4664 )
4765where
4866
49−import Data.Data (Data)
67+import Control.Monad
5068import Data.List (intersperse)
5169import Data.Text (Text)
5270import Ormolu.Printer.Comments
5371import Ormolu.Printer.Internal
54−import Ormolu.Utils (isModule)
55−import Outputable (Outputable (..), showSDocUnsafe)
5672import SrcLoc
57−import qualified Data.Text as T
5873
5974----------------------------------------------------------------------------
6075-- Basic
6176
62−-- | Output a fixed 'Text' fragment. The argument may not contain any line
63−-- breaks or tab characters. 'txt' is used to output all sorts of “fixed”
64−-- bits of syntax like keywords and pipes @|@ in functional dependencies.
65−
66−txt :: Text -> R ()
67−txt t = ensureIndent >> spit t
68−
69−-- | Output 'Outputable' fragment of AST. This can be used to output numeric
70−-- literals and similar. Everything that doesn't have inner structure but
71−-- does have an 'Outputable' instance.
72−
73−atom :: Outputable a => a -> R ()
74−atom = txt . T.pack . showSDocUnsafe . ppr
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
7585
7686-- | Enter a 'Located' entity. This combinator handles outputting comments
7787-- and sets layout (single-line vs multi-line) for the inner computation.
7888-- Roughly, the rule for using 'located' is that every time there is a
7989-- 'Located' wrapper, it should be “discharged” with a corresponding
8090-- 'located' invocation.
81−
82−located
83− :: Data a
84− => Located a -- ^ Thing to enter
85− -> (a -> R ()) -- ^ How to render inner value
86− -> R ()
87−located loc@(L l _) = locatedVia (Just l) loc
88−
89−-- | A special version of 'located' that allows to control layout using an
90−-- externally provided span. 'Nothing' means that layout won't be changed.
91−
92−locatedVia
93− :: Data a
94− => Maybe SrcSpan -- ^ Span that controls layout selection
95− -> Located a -- ^ Thing to enter
96− -> (a -> R ()) -- ^ How to render inner value
97− -> R ()
98−locatedVia ml loc f = do
99− let withRealLocated (L l a) g =
100− case l of
101− UnhelpfulSpan _ -> return ()
102− RealSrcSpan l' -> g (L l' a)
103− withRealLocated loc spitPrecedingComments
104− let setEnclosingSpan =
105− case getLoc loc of
106− UnhelpfulSpan _ -> id
107− RealSrcSpan orf ->
108− if isModule (unLoc loc)
109− then id
110− else withEnclosingSpan orf
111− setEnclosingSpan $ case ml of
112− Nothing -> f (unLoc loc)
113− Just l' -> switchLayout l' (f (unLoc loc))
114− withRealLocated loc spitFollowingComments
91+located ::
92+ -- | Thing to enter
93+ Located a ->
94+ -- | How to render inner value
95+ (a -> R ()) ->
96+ 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
115103
116104-- | A version of 'located' with arguments flipped.
117−
118−located'
119− :: Data a
120− => (a -> R ()) -- ^ How to render inner value
121− -> Located a -- ^ Thing to enter
122− -> R ()
105+located' ::
106+ -- | How to render inner value
107+ (a -> R ()) ->
108+ -- | Thing to enter
109+ Located a ->
110+ R ()
123111located' = flip located
124112
125−-- | Set layout according to given 'SrcSpan' for a given computation. Use
126−-- this only when you need to set layout based on e.g. combined span of
113+-- | Set layout according to combination of given 'SrcSpan's for a given.
114+-- Use this only when you need to set layout based on e.g. combined span of
127115-- several elements when there is no corresponding 'Located' wrapper
128116-- provided by GHC AST. It is relatively rare that this one is needed.
129−
130−switchLayout
131− :: SrcSpan -- ^ Span that controls layout
132− -> R () -- ^ Computation to run with changed layout
133− -> R ()
134−switchLayout spn = enterLayout
135− (if isOneLineSpan spn
136− then SingleLine
137− else MultiLine)
117+--
118+-- Given empty list this function will set layout to single line.
119+switchLayout ::
120+ -- | Span that controls layout
121+ [SrcSpan] ->
122+ -- | Computation to run with changed layout
123+ R () ->
124+ R ()
125+switchLayout spans' = enterLayout (spansLayout spans')
126+
127+-- | Which layout combined spans result in?
128+spansLayout :: [SrcSpan] -> Layout
129+spansLayout = \case
130+ [] -> SingleLine
131+ (x : xs) ->
132+ if isOneLineSpan (foldr combineSrcSpans x xs)
133+ then SingleLine
134+ else MultiLine
138135
139136-- | Insert a space if enclosing layout is single-line, or newline if it's
140137-- multiline.
141138--
142139-- > breakpoint = vlayout space newline
143−
144140breakpoint :: R ()
145141breakpoint = vlayout space newline
146142
@@ -148,162 +144,155 @@ breakpoint = vlayout space newline
148144-- layout.
149145--
150146-- > breakpoint' = vlayout (return ()) newline
151−
152147breakpoint' :: R ()
153148breakpoint' = vlayout (return ()) newline
154149
155150----------------------------------------------------------------------------
156151-- Formatting lists
157152
158−-- | Element of variable layout. This means that the sub-components may be
159−-- rendered either on single line or each on its own line depending on
160−-- current layout.
153+-- | Render a collection of elements inserting a separator between them.
154+sep ::
155+ -- | Separator
156+ R () ->
157+ -- | How to render an element
158+ (a -> R ()) ->
159+ -- | Elements to render
160+ [a] ->
161+ R ()
162+sep s f xs = sequence_ (intersperse s (f <$> xs))
163+
164+-- | Render a collection of elements layout-sensitively using given printer,
165+-- inserting semicolons if necessary and respecting 'useBraces' and
166+-- 'dontUseBraces' combinators.
161167--
162−-- This version does not make subsequent element (second and later) align
163−-- with the first automatically and does not insert spaces between elements
164−-- when layout is single line.
165−
166−velt :: [R ()] -> R ()
167−velt xs = sequence_ (intersperse breakpoint' (sitcc <$> xs))
168−
169−-- | Like 'velt', but all sub-elements start at the same indentation level
170−-- as first element, additionally spaces are inserted when layout is single
171−-- line.
172−
173−velt' :: [R ()] -> R ()
174−velt' xs = sitcc $ sequence_ (intersperse breakpoint (sitcc <$> xs))
175−
176−-- | Put separator between renderings of items of a list.
177−
178−withSep
179− :: R () -- ^ Separator
180− -> (a -> R ()) -- ^ How to render list items
181− -> [a] -- ^ List to render
182− -> [R ()] -- ^ List of printing actions
183−withSep sep f = \case
184− [] -> []
185− (x:xs) ->
186− let g a = sep >> f a
187− in f x : fmap g xs
188−
189−-- | Render space-separated elements.
168+-- > useBraces $ sepSemi txt ["foo", "bar"]
169+-- > == vlayout (txt "{ foo; bar }") (txt "foo\nbar")
190170--
191−-- > spaceSep f = sequence_ . withSep space f
192−
193−spaceSep
194− :: (a -> R ()) -- ^ How to render list items
195− -> [a] -- ^ List to render
196− -> R ()
197−spaceSep f = sequence_ . withSep space f
198−
199−-- | Render newline-separated elements.
200−--
201−-- > newlineSep f = sequence_ . withSep newline f
202−
203−newlineSep
204− :: (a -> R ()) -- ^ How to render list items
205− -> [a] -- ^ List to render
206− -> R ()
207−newlineSep f = sequence_ . withSep newline f
171+-- > dontUseBraces $ sepSemi txt ["foo", "bar"]
172+-- > == vlayout (txt "foo; bar") (txt "foo\nbar")
173+sepSemi ::
174+ -- | How to render an element
175+ (a -> R ()) ->
176+ -- | Elements to render
177+ [a] ->
178+ R ()
179+sepSemi f xs = vlayout singleLine multiLine
180+ where
181+ singleLine = do
182+ ub <- canUseBraces
183+ case xs of
184+ [] -> when ub $ txt "{}"
185+ xs' ->
186+ if ub
187+ then do
188+ txt "{"
189+ space
190+ sep (txt ";" >> space) (dontUseBraces . f) xs'
191+ space
192+ txt "}"
193+ else sep (txt ";" >> space) f xs'
194+ multiLine =
195+ sep newline (dontUseBraces . f) xs
208196
209197----------------------------------------------------------------------------
210198-- Wrapping
211199
212−-- | Finish given entity by a 'newline'.
213−--
214−-- > line m = do
215−-- > m
216−-- > newline
217−
218−line :: R () -> R ()
219−line m = do
220− m
221− newline
200+-- | 'BracketStyle' controlling how closing bracket is rendered.
201+data BracketStyle
202+ = -- | Normal
203+ N
204+ | -- | Shifted one level
205+ S
206+ deriving (Eq, Show)
222207
223208-- | Surround given entity by backticks.
224−
225209backticks :: R () -> R ()
226210backticks m = do
227211 txt "`"
228212 m
229213 txt "`"
230214
231−-- | Surround given entity by curly braces @{@ and @}@.
215+-- | Surround given entity by banana brackets (i.e., from arrow notation.)
216+banana :: R () -> R ()
217+banana = brackets_ True "(|" "|)" N
232218
233−braces :: R () -> R ()
234−braces m = sitcc $ do
235− txt "{"
236− ospaces m
237− txt "}"
219+-- | Surround given entity by curly braces @{@ and @}@.
220+braces :: BracketStyle -> R () -> R ()
221+braces = brackets_ False "{" "}"
238222
239223-- | Surround given entity by square brackets @[@ and @]@.
240−
241−brackets :: R () -> R ()
242−brackets m = sitcc $ do
243− txt "["
244− ospaces m
245− txt "]"
246−
247−-- | Surround given entity by parallel array brackets @[:@ and @:]@.
248−
249−bracketsPar :: R () -> R ()
250−bracketsPar m = sitcc $ do
251− txt "[: "
252− m
253− txt " :]"
224+brackets :: BracketStyle -> R () -> R ()
225+brackets = brackets_ False "[" "]"
254226
255227-- | Surround given entity by parentheses @(@ and @)@.
256−
257−parens :: R () -> R ()
258−parens m = sitcc $ do
259− txt "("
260− ospaces m
261− txt ")"
228+parens :: BracketStyle -> R () -> R ()
229+parens = brackets_ False "(" ")"
262230
263231-- | Surround given entity by @(# @ and @ #)@.
264−
265−parensHash :: R () -> R ()
266−parensHash m = sitcc $ do
267− txt "(# "
268− m
269− breakpoint
270− txt "#)"
232+parensHash :: BracketStyle -> R () -> R ()
233+parensHash = brackets_ True "(#" "#)"
271234
272235-- | Braces as used for pragmas: @{-#@ and @#-}@.
273−
274236pragmaBraces :: R () -> R ()
275237pragmaBraces m = sitcc $ do
276− txt "{-# "
238+ txt "{-#"
239+ space
277240 m
278− vlayout space (newline >> txt " ")
279− txt "#-}"
241+ breakpoint
242+ inci (txt "#-}")
280243
281244-- | Surround the body with a pragma name and 'pragmaBraces'.
282−
283−pragma
284− :: Text -- ^ Pragma text
285− -> R () -- ^ Pragma body
286− -> R ()
245+pragma ::
246+ -- | Pragma text
247+ Text ->
248+ -- | Pragma body
249+ R () ->
250+ R ()
287251pragma pragmaText body = pragmaBraces $ do
288252 txt pragmaText
289253 breakpoint
290− inci body
291−
292−-- | Surround given entity by optional space before and a newline after, iff
293−-- current layout is multiline.
294−
295−ospaces :: R () -> R ()
296−ospaces m = vlayout m (txt " " >> m >> newline)
254+ body
255+
256+-- | A helper for defining wrappers like 'parens' and 'braces'.
257+brackets_ ::
258+ -- | Insert breakpoints around brackets
259+ Bool ->
260+ -- | Opening bracket
261+ Text ->
262+ -- | Closing bracket
263+ Text ->
264+ -- | Bracket style
265+ BracketStyle ->
266+ -- | Inner expression
267+ R () ->
268+ R ()
269+brackets_ needBreaks open close style m = sitcc (vlayout singleLine multiLine)
270+ where
271+ singleLine = do
272+ txt open
273+ when needBreaks space
274+ m
275+ when needBreaks space
276+ txt close
277+ multiLine = do
278+ txt open
279+ if needBreaks
280+ then newline >> inci m
281+ else space >> sitcc m
282+ newline
283+ inciIf (style == S) (txt close)
297284
298285----------------------------------------------------------------------------
299286-- Literals
300287
301−-- | Print @,@ followed by a space.
302−
288+-- | Print @,@.
303289comma :: R ()
304−comma = txt ", "
290+comma = txt ","
305291
306−-- | Print single space.
292+-- | Delimiting combination with 'comma'. To be used with 'sep'.
293+commaDel :: R ()
294+commaDel = comma >> breakpoint
307295
308−space :: R ()
309−space = txt " "
296+-- | Print @=@. Do not use @'txt' "="@.
297+equals :: R ()
298+equals = interferingTxt "="
src/Ormolu/Printer/Comments.hs+198−125
@@ -1,185 +1,215 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE OverloadedStrings #-}
33
44-- | Helpers for formatting of comments. This is low-level code, use
55-- "Ormolu.Printer.Combinators" unless you know what you are doing.
6−
76module Ormolu.Printer.Comments
8− ( spitPrecedingComments
9− , spitFollowingComments
10− , spitRemainingComments
11− , hasMoreComments
7+ ( spitPrecedingComments,
8+ spitFollowingComments,
9+ spitRemainingComments,
10+ spitCommentNow,
11+ spitCommentPending,
1212 )
1313where
1414
1515import Control.Monad
16−import Data.Coerce (coerce)
17−import Data.Data (Data)
18−import Data.Maybe (isJust)
19−import Ormolu.CommentStream
20−import Ormolu.Printer.Internal
21−import Ormolu.Utils (isModule)
22−import SrcLoc
2316import qualified Data.List.NonEmpty as NE
17+import Data.Maybe (listToMaybe)
2418import qualified Data.Text as T
19+import Ormolu.Parser.CommentStream
20+import Ormolu.Printer.Internal
21+import SrcLoc
2522
2623----------------------------------------------------------------------------
2724-- Top-level
2825
2926-- | Output all preceding comments for an element at given location.
30−
31−spitPrecedingComments
32− :: Data a
33− => RealLocated a -- ^ AST element to attach comments to
34− -> R ()
35−spitPrecedingComments = handleCommentSeries . spitPrecedingComment
27+spitPrecedingComments ::
28+ -- | Span of the element to attach comments to
29+ RealSrcSpan ->
30+ R ()
31+spitPrecedingComments ref = do
32+ gotSome <- handleCommentSeries (spitPrecedingComment ref)
33+ when gotSome $ do
34+ lastMark <- getSpanMark
35+ -- Insert a blank line between the preceding comments and the thing
36+ -- after them if there was a blank line in the input.
37+ when (needsNewlineBefore ref lastMark) newline
3638
3739-- | Output all comments following an element at given location.
38−
39−spitFollowingComments
40− :: Data a
41− => RealLocated a -- ^ AST element of attach comments to
42− -> R ()
40+spitFollowingComments ::
41+ -- | Span of the element to attach comments to
42+ RealSrcSpan ->
43+ R ()
4344spitFollowingComments ref = do
44− trimSpanStream (getLoc ref)
45− handleCommentSeries (spitFollowingComment ref)
45+ trimSpanStream ref
46+ void $ handleCommentSeries (spitFollowingComment ref)
4647
4748-- | Output all remaining comments in the comment stream.
48−
4949spitRemainingComments :: R ()
50−spitRemainingComments = handleCommentSeries spitRemainingComment
50+spitRemainingComments = do
51+ -- Make sure we have a blank a line between the last definition and the
52+ -- trailing comments.
53+ newline
54+ void $ handleCommentSeries spitRemainingComment
5155
5256----------------------------------------------------------------------------
5357-- Single-comment functions
5458
5559-- | Output a single preceding comment for an element at given location.
56−
57−spitPrecedingComment
58− :: Data a
59− => RealLocated a -- ^ AST element to attach comments to
60− -> Maybe RealSrcSpan -- ^ Location of last comment in the series
61− -> R (Maybe RealSrcSpan) -- ^ Location of this comment
62−spitPrecedingComment (L ref a) mlastSpn = do
60+spitPrecedingComment ::
61+ -- | Span of the element to attach comments to
62+ RealSrcSpan ->
63+ -- | Are we done?
64+ R Bool
65+spitPrecedingComment ref = do
66+ mlastMark <- getSpanMark
6367 let p (L l _) = realSrcSpanEnd l <= realSrcSpanStart ref
6468 withPoppedComment p $ \l comment -> do
65− when (needsNewlineBefore l mlastSpn) newline
66− spitComment comment
67− if theSameLine l ref && not (isModule a)
68− then spit " "
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
76+ spitCommentNow l comment
77+ if theSameLinePre l ref
78+ then space
6979 else newline
7080
7181-- | Output a comment that follows element at given location immediately on
7282-- the same line, if there is any.
73−
74−spitFollowingComment
75− :: Data a
76− => RealLocated a -- ^ AST element to attach comments to
77− -> Maybe RealSrcSpan -- ^ Location of last comment in the series
78− -> R (Maybe RealSrcSpan) -- ^ Location of this comment
79−spitFollowingComment (L ref a) mlastSpn = do
83+spitFollowingComment ::
84+ -- | AST element to attach comments to
85+ RealSrcSpan ->
86+ -- | Are we done?
87+ R Bool
88+spitFollowingComment ref = do
89+ mlastMark <- getSpanMark
8090 mnSpn <- nextEltSpan
81− meSpn <- getEnclosingSpan ref
82− i <- getIndent
83− withPoppedComment (commentFollowsElt ref mnSpn meSpn mlastSpn) $ \l comment ->
84− if theSameLine l ref && not (isModule a)
85− then modNewline $ \m -> setIndent i $ do
86− spit " "
87− spitComment comment
88− m
89− else modNewline $ \m -> setIndent i $ do
90− m
91− when (needsNewlineBefore l mlastSpn) newline
92− spitComment comment
93− newline
91+ -- Get first enclosing span that is not equal to reference span, i.e. it's
92+ -- truly something enclosing the AST element.
93+ meSpn <- getEnclosingSpan (/= ref)
94+ withPoppedComment (commentFollowsElt ref mnSpn meSpn mlastMark) $ \l comment ->
95+ if theSameLinePost l ref
96+ then
97+ if isMultilineComment comment
98+ then space >> spitCommentNow l comment
99+ else spitCommentPending OnTheSameLine l comment
100+ else do
101+ when (needsNewlineBefore l mlastMark) $
102+ registerPendingCommentLine OnNextLine ""
103+ spitCommentPending OnNextLine l comment
94104
95105-- | Output a single remaining comment from the comment stream.
96−
97−spitRemainingComment
98− :: Maybe RealSrcSpan -- ^ Location of last comment in the series
99− -> R (Maybe RealSrcSpan) -- ^ Location of this comment
100−spitRemainingComment mlastSpn =
106+spitRemainingComment ::
107+ -- | Are we done?
108+ R Bool
109+spitRemainingComment = do
110+ mlastMark <- getSpanMark
101111 withPoppedComment (const True) $ \l comment -> do
102− when (needsNewlineBefore l mlastSpn) newline
103− spitComment comment
112+ when (needsNewlineBefore l mlastMark) newline
113+ spitCommentNow l comment
104114 newline
105115
106116----------------------------------------------------------------------------
107117-- Helpers
108118
109119-- | Output series of comments.
110−
111−handleCommentSeries
112− :: (Maybe RealSrcSpan -> R (Maybe RealSrcSpan))
113− -- ^ Given location of previous comment, output the next comment
114− -- returning its location, or 'Nothing' if we are done
115− -> R ()
116−handleCommentSeries f = go Nothing
120+handleCommentSeries ::
121+ -- | Given location of previous comment, output the next comment
122+ -- returning 'True' if we're done
123+ R Bool ->
124+ -- | Whether we printed any comments
125+ R Bool
126+handleCommentSeries f = go False
117127 where
118− go mlastSpn = do
119− r <- f mlastSpn
120− case r of
121− Nothing -> return ()
122− Just spn -> go (Just spn)
128+ go gotSome = do
129+ done <- f
130+ if done
131+ then return gotSome
132+ else go True
123133
124134-- | Try to pop a comment using given predicate and if there is a comment
125135-- matching the predicate, print it out.
126−
127−withPoppedComment
128− :: (RealLocated Comment -> Bool) -- ^ Comment predicate
129− -> (RealSrcSpan -> Comment -> R ()) -- ^ Priting function
130− -> R (Maybe RealSrcSpan)
136+withPoppedComment ::
137+ -- | Comment predicate
138+ (RealLocated Comment -> Bool) ->
139+ -- | Printing function
140+ (RealSrcSpan -> Comment -> R ()) ->
141+ -- | Are we done?
142+ R Bool
131143withPoppedComment p f = do
132144 r <- popComment p
133145 case r of
134− Nothing -> return Nothing
135− Just (L l comment) -> Just l <$ f l comment
146+ Nothing -> return True
147+ Just (L l comment) -> False <$ f l comment
136148
137149-- | Determine if we need to insert a newline between current comment and
138150-- last printed comment.
139−
140−needsNewlineBefore
141− :: RealSrcSpan -- ^ Current comment span
142− -> Maybe RealSrcSpan -- ^ Last printed comment span
143− -> Bool
144−needsNewlineBefore l mlastSpn =
145− case mlastSpn of
151+needsNewlineBefore ::
152+ -- | Current comment span
153+ RealSrcSpan ->
154+ -- | Last printed comment span
155+ Maybe SpanMark ->
156+ Bool
157+needsNewlineBefore _ (Just (HaddockSpan _ _)) = True
158+needsNewlineBefore l mlastMark =
159+ case spanMarkSpan <$> mlastMark of
146160 Nothing -> False
147− Just lastSpn ->
148− srcSpanStartLine l > srcSpanEndLine lastSpn + 1
161+ Just lastMark ->
162+ srcSpanStartLine l > srcSpanEndLine lastMark + 1
149163
150−-- | Is the comment and AST element are on the same line?
151−
152−theSameLine
153− :: RealSrcSpan -- ^ Current comment span
154− -> RealSrcSpan -- ^ AST element location
155− -> Bool
156−theSameLine l ref =
164+-- | Is the preceding comment and AST element are on the same line?
165+theSameLinePre ::
166+ -- | Current comment span
167+ RealSrcSpan ->
168+ -- | AST element location
169+ RealSrcSpan ->
170+ Bool
171+theSameLinePre l ref =
157172 srcSpanEndLine l == srcSpanStartLine ref
158173
159−-- | Determine if given comment follows AST element.
174+-- | Is the following comment and AST element are on the same line?
175+theSameLinePost ::
176+ -- | Current comment span
177+ RealSrcSpan ->
178+ -- | AST element location
179+ RealSrcSpan ->
180+ Bool
181+theSameLinePost l ref =
182+ srcSpanStartLine l == srcSpanEndLine ref
160183
161−commentFollowsElt
162− :: RealSrcSpan -- ^ Location of AST element
163− -> Maybe RealSrcSpan -- ^ Location of next AST element
164− -> Maybe RealSrcSpan -- ^ Location of enclosing AST element
165− -> Maybe RealSrcSpan -- ^ Location of last comment in the series
166− -> RealLocated Comment -- ^ Comment to test
167− -> Bool
168−commentFollowsElt ref mnSpn meSpn mlastSpn (L l comment) =
184+-- | Determine if given comment follows AST element.
185+commentFollowsElt ::
186+ -- | Location of AST element
187+ RealSrcSpan ->
188+ -- | Location of next AST element
189+ Maybe RealSrcSpan ->
190+ -- | Location of enclosing AST element
191+ Maybe RealSrcSpan ->
192+ -- | Location of last comment in the series
193+ Maybe SpanMark ->
194+ -- | Comment to test
195+ RealLocated Comment ->
196+ Bool
197+commentFollowsElt ref mnSpn meSpn mlastMark (L l comment) =
169198 -- A comment follows a AST element if all 4 conditions are satisfied:
170199 goesAfter
171200 && logicallyFollows
172201 && noEltBetween
173− && (continuation || supersedesParentElt)
202+ && (continuation || lastInEnclosing || supersedesParentElt)
174203 where
175204 -- 1) The comment starts after end of the AST element:
176205 goesAfter =
177206 realSrcSpanStart l >= realSrcSpanEnd ref
178− -- 2) The comment logically belongs to the element, three cases:
179− logicallyFollows
180− = theSameLine l ref -- a) it's on the same line
181− || isPrevHaddock comment -- b) it's a Haddock string starting with -- ^
182− || continuation -- c) it's a continuation of a comment block
207+ -- 2) The comment logically belongs to the element, four cases:
208+ logicallyFollows =
209+ 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
212+
183213 -- 3) There is no other AST element between this element and the comment:
184214 noEltBetween =
185215 case mnSpn of
@@ -200,14 +230,57 @@ commentFollowsElt ref mnSpn meSpn mlastSpn (L l comment) =
200230 Nothing -> True
201231 Just espn ->
202232 let startColumn = srcLocCol . realSrcSpanStart
203− in abs (startColumn espn - startColumn l)
204− >= abs (startColumn ref - startColumn l)
205− continuation = isJust mlastSpn
233+ in startColumn espn > startColumn ref
234+ || ( abs (startColumn espn - startColumn l)
235+ >= abs (startColumn ref - startColumn l)
236+ )
237+ 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+ )
247+ lastInEnclosing =
248+ case meSpn of
249+ -- When there is no enclosing element, return false
250+ Nothing -> False
251+ -- When there is an enclosing element,
252+ Just espn ->
253+ let -- Make sure that the comment is inside the enclosing element
254+ insideParent = realSrcSpanEnd l <= realSrcSpanEnd espn
255+ -- And check if the next element is outside of the parent
256+ nextOutsideParent = case mnSpn of
257+ Nothing -> True
258+ Just nspn -> realSrcSpanEnd espn < realSrcSpanStart nspn
259+ in insideParent && nextOutsideParent
206260
207−-- | Output a 'Comment'. This is a low-level printing function.
261+-- | Output a 'Comment' immediately. This is a low-level printing function.
262+spitCommentNow :: RealSrcSpan -> Comment -> R ()
263+spitCommentNow spn comment = do
264+ sitcc
265+ . sequence_
266+ . NE.intersperse newline
267+ . fmap (txt . T.pack)
268+ . unComment
269+ $ comment
270+ setSpanMark (CommentSpan spn)
208271
209−spitComment :: Comment -> R ()
210−spitComment =
211− sequence_ . NE.intersperse newline . fmap f . coerce
212− where
213− f x = ensureIndent >> spit (T.pack x)
272+-- | Output a 'Comment' at the end of correct line or after it depending on
273+-- 'CommentPosition'. Used for comments that may potentially follow on the
274+-- same line as something we just rendered, but not immediately after it.
275+spitCommentPending :: CommentPosition -> RealSrcSpan -> Comment -> R ()
276+spitCommentPending position spn comment = do
277+ let wrapper = case position of
278+ OnTheSameLine -> sitcc
279+ OnNextLine -> id
280+ wrapper
281+ . sequence_
282+ . NE.toList
283+ . fmap (registerPendingCommentLine position . T.pack)
284+ . unComment
285+ $ comment
286+ setSpanMark (CommentSpan spn)
src/Ormolu/Printer/Internal.hs+450−246
@@ -1,373 +1,577 @@
11{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2−{-# LANGUAGE LambdaCase #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE RankNTypes #-}
2+{-# LANGUAGE LambdaCase #-}
3+{-# LANGUAGE OverloadedStrings #-}
4+{-# LANGUAGE RankNTypes #-}
55
66-- | In most cases import "Ormolu.Printer.Combinators" instead, these
77-- functions are the low-level building blocks and should not be used on
88-- their own. The 'R' monad is re-exported from "Ormolu.Printer.Combinators"
99-- as well.
10−
1110module Ormolu.Printer.Internal
1211 ( -- * The 'R' monad
13− R
14− , runR
12+ R,
13+ runR,
14+
1515 -- * Internal functions
16− , spit
17− , newline
18− , modNewline
19− , ensureIndent
20− , inci
21− , sitcc
22− , Layout (..)
23− , enterLayout
24− , vlayout
16+ txt,
17+ interferingTxt,
18+ atom,
19+ space,
20+ newline,
21+ useRecordDot,
22+ inci,
23+ sitcc,
24+ Layout (..),
25+ enterLayout,
26+ vlayout,
27+ getLayout,
28+
29+ -- * Helpers for braces
30+ useBraces,
31+ dontUseBraces,
32+ canUseBraces,
33+
2534 -- * Special helpers for comment placement
26− , trimSpanStream
27− , nextEltSpan
28− , popComment
29− , hasMoreComments
30− , getIndent
31− , setIndent
32− , getEnclosingSpan
33− , withEnclosingSpan
35+ CommentPosition (..),
36+ registerPendingCommentLine,
37+ trimSpanStream,
38+ nextEltSpan,
39+ popComment,
40+ getEnclosingSpan,
41+ withEnclosingSpan,
42+ thisLineSpans,
43+
44+ -- * Stateful markers
45+ SpanMark (..),
46+ spanMarkSpan,
47+ HaddockStyle (..),
48+ setSpanMark,
49+ getSpanMark,
50+
3451 -- * Annotations
35− , getAnns
52+ getAnns,
3653 )
3754where
3855
3956import Control.Monad.Reader
4057import Control.Monad.State.Strict
58+import Data.Bool (bool)
4159import Data.Coerce
4260import Data.Maybe (listToMaybe)
4361import Data.Text (Text)
44−import Data.Text.Lazy.Builder
45−import Debug.Trace
46−import GHC
47−import Ormolu.Anns
48−import Ormolu.CommentStream
49−import Ormolu.SpanStream
50−import SrcLoc
5162import qualified Data.Text as T
5263import qualified Data.Text.Lazy as TL
64+import Data.Text.Lazy.Builder
65+import GHC
66+import Ormolu.Parser.Anns
67+import Ormolu.Parser.CommentStream
68+import Ormolu.Printer.SpanStream
69+import Ormolu.Utils (showOutputable)
70+import Outputable (Outputable)
5371
5472----------------------------------------------------------------------------
5573-- The 'R' monad
5674
5775-- | The 'R' monad hosts combinators that allow us to describe how to render
5876-- AST.
59−
6077newtype R a = R (ReaderT RC (State SC) a)
6178 deriving (Functor, Applicative, Monad)
6279
63−-- | Reader context of 'R'.
64−
80+-- | Reader context of 'R'. This should be used when we control rendering by
81+-- enclosing certain expressions with wrappers.
6582data RC = RC
66− { rcIndent :: !Int
67− -- ^ Indentation level, as the column index we need to start from after a
68− -- newline if we break lines
69− , rcLayout :: Layout
70− -- ^ Current layout
71− , rcRelaxedComments :: Bool
72− -- ^ Whether to relax aligning rules for comments
73− , rcDebug :: Bool
74− -- ^ Whether to print debugging info as we go
75− , rcEnclosingSpans :: [RealSrcSpan]
76− -- ^ Span of enclosing element of AST
77− , rcAnns :: Anns
78− -- ^ Collection of annotations
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
7996 }
8097
8198-- | State context of 'R'.
82−
8399data SC = SC
84− { scColumn :: !Int
85− -- ^ Index of the next column to render
86− , scBuilder :: Builder
87− -- ^ Rendered source code so far
88− , scSpanStream :: SpanStream
89− -- ^ Span stream
90− , scCommentStream :: CommentStream
91− -- ^ Comment stream
92− , scNewline :: R ()
93− -- ^ What to render as newline
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)
94119 }
95120
96−-- | 'Layout' options.
121+-- | Make sure next output is delimited by one of the following.
122+data RequestedDelimiter
123+ = -- | A space
124+ RequestedSpace
125+ | -- | A newline
126+ RequestedNewline
127+ | -- | Nothing
128+ RequestedNothing
129+ | -- | We just output a newline
130+ AfterNewline
131+ | -- | We haven't printed anything yet
132+ VeryBeginning
133+ deriving (Eq, Show)
97134
135+-- | 'Layout' options.
98136data Layout
99− = SingleLine -- ^ Put everything on single line
100− | MultiLine -- ^ Use multiple lines
137+ = -- | Put everything on single line
138+ SingleLine
139+ | -- | Use multiple lines
140+ MultiLine
101141 deriving (Eq, Show)
102142
103−-- | Run an 'R' monad.
143+-- | Modes for rendering of pending comments.
144+data CommentPosition
145+ = -- | Put the comment on the same line
146+ OnTheSameLine
147+ | -- | Put the comment on next line
148+ OnNextLine
149+ deriving (Eq, Show)
104150
105−runR
106− :: Bool -- ^ Whether to print debugging info
107− -> R () -- ^ Monad to run
108− -> SpanStream -- ^ Span stream
109− -> CommentStream -- ^ Comment stream
110− -> Anns -- ^ Annotations
111− -> Text -- ^ Resulting rendition
112−runR debug (R m) sstream cstream anns =
151+-- | Run an 'R' monad.
152+runR ::
153+ -- | Monad to run
154+ R () ->
155+ -- | Span stream
156+ SpanStream ->
157+ -- | Comment stream
158+ CommentStream ->
159+ -- | Annotations
160+ Anns ->
161+ -- | Use Record Dot Syntax
162+ Bool ->
163+ -- | Resulting rendition
164+ Text
165+runR (R m) sstream cstream anns recDot =
113166 TL.toStrict . toLazyText . scBuilder $ execState (runReaderT m rc) sc
114167 where
115− rc = RC
116− { rcIndent = 0
117− , rcLayout = MultiLine
118− , rcRelaxedComments = False
119− , rcDebug = debug
120− , rcEnclosingSpans = []
121− , rcAnns = anns
122− }
123− sc = SC
124− { scColumn = 0
125− , scBuilder = mempty
126− , scSpanStream = sstream
127− , scCommentStream = cstream
128− , scNewline = newlineRaw
129− }
168+ rc =
169+ RC
170+ { rcIndent = 0,
171+ rcLayout = MultiLine,
172+ rcEnclosingSpans = [],
173+ rcAnns = anns,
174+ rcCanUseBraces = False,
175+ rcUseRecDot = recDot
176+ }
177+ sc =
178+ SC
179+ { scColumn = 0,
180+ scIndent = 0,
181+ scBuilder = mempty,
182+ scSpanStream = sstream,
183+ scThisLineSpans = [],
184+ scCommentStream = cstream,
185+ scPendingComments = [],
186+ scRequestedDelimiter = VeryBeginning,
187+ scSpanMark = Nothing
188+ }
130189
131190----------------------------------------------------------------------------
132191-- Internal functions
133192
134−-- | Grow current output by appending given 'Text' to it, which may not
135−-- contain newlines.
193+-- | Type of the thing to output. Influences the primary low-level rendering
194+-- function 'spit'.
195+data SpitType
196+ = -- | Simple opaque text that breaks comment series.
197+ SimpleText
198+ | -- | Like 'SimpleText', but assume that when this text is inserted it
199+ -- will separate an 'Atom' and its pending comments, so insert an extra
200+ -- 'newline' in that case to force the pending comments and continue on
201+ -- a fresh line.
202+ InterferingText
203+ | -- | An atom that typically have span information in the AST and can
204+ -- have comments attached to it.
205+ Atom
206+ | -- | Used for rendering comment lines.
207+ CommentPart
208+ deriving (Show, Eq)
209+
210+-- | Output a fixed 'Text' fragment. The argument may not contain any line
211+-- breaks. 'txt' is used to output all sorts of “fixed” bits of syntax like
212+-- keywords and pipes @|@ in functional dependencies.
213+--
214+-- To separate various bits of syntax with white space use 'space' instead
215+-- of @'txt' " "@. To output 'Outputable' Haskell entities like numbers use
216+-- 'atom'.
217+txt ::
218+ -- | 'Text' to output
219+ Text ->
220+ R ()
221+txt = spit SimpleText
222+
223+-- | Similar to 'txt' but the text inserted this way is assumed to break the
224+-- “link” between the preceding atom and its pending comments.
225+interferingTxt ::
226+ -- | 'Text' to output
227+ Text ->
228+ R ()
229+interferingTxt = spit InterferingText
230+
231+-- | Output 'Outputable' fragment of AST. This can be used to output numeric
232+-- literals and similar. Everything that doesn't have inner structure but
233+-- does have an 'Outputable' instance.
234+atom ::
235+ Outputable a =>
236+ a ->
237+ R ()
238+atom = spit Atom . T.pack . showOutputable
239+
240+-- | Low-level non-public helper to define 'txt' and 'atom'.
241+spit ::
242+ -- | Type of the thing to spit
243+ SpitType ->
244+ -- | 'Text' to output
245+ Text ->
246+ R ()
247+spit _ "" = return ()
248+spit stype text = do
249+ requestedDel <- R (gets scRequestedDelimiter)
250+ pendingComments <- R (gets scPendingComments)
251+ when (stype == InterferingText && not (null pendingComments)) newline
252+ case requestedDel of
253+ RequestedNewline -> do
254+ R . modify $ \sc ->
255+ sc
256+ { scRequestedDelimiter = RequestedNothing
257+ }
258+ case stype of
259+ CommentPart -> newlineRaw
260+ _ -> newline
261+ _ -> return ()
262+ R $ do
263+ i <- asks rcIndent
264+ c <- gets scColumn
265+ closestEnclosing <- listToMaybe <$> asks rcEnclosingSpans
266+ let indentedTxt = spaces <> text
267+ spaces = T.replicate spacesN " "
268+ spacesN =
269+ if c == 0
270+ then i
271+ else bool 0 1 (requestedDel == RequestedSpace)
272+ modify $ \sc ->
273+ sc
274+ { scBuilder = scBuilder sc <> fromText indentedTxt,
275+ scColumn = scColumn sc + T.length indentedTxt,
276+ scIndent =
277+ if c == 0
278+ then i
279+ else scIndent sc,
280+ scThisLineSpans =
281+ let xs = scThisLineSpans sc
282+ in case stype of
283+ Atom -> case closestEnclosing of
284+ Nothing -> xs
285+ Just x -> x : xs
286+ _ -> xs,
287+ scRequestedDelimiter = RequestedNothing,
288+ scSpanMark =
289+ -- If there are pending comments, do not reset last comment
290+ -- location.
291+ if (stype == CommentPart) || (not . null . scPendingComments) sc
292+ then scSpanMark sc
293+ else Nothing
294+ }
136295
137−spit :: Text -> R ()
138−spit x = do
139− traceR "spit_before" (Just x)
140− R . modify $ \sc -> sc
141− { scBuilder = scBuilder sc <> fromText x
142− , scColumn = scColumn sc + T.length x
296+-- | This primitive /does not/ necessarily output a space. It just ensures
297+-- that the next thing that will be printed on the same line will be
298+-- separated by a single space from the previous output. Using this
299+-- combinator twice results in at most one space.
300+--
301+-- In practice this design prevents trailing white space and makes it hard
302+-- to output more than one delimiting space in a row, which is what we
303+-- usually want.
304+space :: R ()
305+space = R . modify $ \sc ->
306+ sc
307+ { scRequestedDelimiter = case scRequestedDelimiter sc of
308+ RequestedNothing -> RequestedSpace
309+ other -> other
143310 }
144− traceR "spit_after" Nothing
145−
146−-- | Output a newline.
147311
312+-- | Output a newline. First time 'newline' is used after some non-'newline'
313+-- output it gets inserted immediately. Second use of 'newline' does not
314+-- output anything but makes sure that the next non-white space output will
315+-- be prefixed by a newline. Using 'newline' more than twice in a row has no
316+-- effect. Also, using 'newline' at the very beginning has no effect, this
317+-- is to avoid leading whitespace.
318+--
319+-- Similarly to 'space', this design prevents trailing newlines and makes it
320+-- hard to output more than one blank newline in a row.
148321newline :: R ()
149322newline = do
150− n <- R (gets scNewline)
151− R . modify $ \sc -> sc
152− { scNewline = newlineRaw
153− }
154− n
323+ indent <- R (gets scIndent)
324+ cs <- reverse <$> R (gets scPendingComments)
325+ case cs of
326+ [] -> newlineRaw
327+ ((position, _) : _) -> do
328+ case position of
329+ OnTheSameLine -> space
330+ OnNextLine -> newlineRaw
331+ R . forM_ cs $ \(_, text) ->
332+ let modRC rc =
333+ rc
334+ { rcIndent = indent
335+ }
336+ R m = do
337+ unless (T.null text) $
338+ spit CommentPart text
339+ newlineRaw
340+ in local modRC m
341+ R . modify $ \sc ->
342+ sc
343+ { scPendingComments = []
344+ }
155345
156346-- | Low-level newline primitive. This one always just inserts a newline, no
157347-- hooks can be attached.
158−
159348newlineRaw :: R ()
160−newlineRaw = do
161− traceR "newline_before" (Just "\n")
162− R . modify $ \sc -> sc
163− { scBuilder = scBuilder sc <> "\n"
164− , scColumn = 0
165− }
166− traceR "newline_after" Nothing
167−
168−-- | The 'modNewline' function can be used to alter what will be inserted as
169−-- a newline. This is used to output comments following an element of AST
170−-- because we cannot output comments immediately, e.g. because we need to
171−-- close parentheses first, etc.
172−--
173−-- 'newline' auto-resets its modifications so the changes introduced with
174−-- 'modNewline' only have effect once.
175−--
176−-- The argument of the call-back is the version of 'newline' built so far.
177−
178−modNewline :: (R () -> R ()) -> R ()
179−modNewline f = R $ do
180− old <- gets scNewline
181− modify $ \sc -> sc
182− { scNewline = f old
183− }
184−
185−-- | Ensure that indentation level is satisfied. Insert correct number of
186−-- spaces if it isn't.
349+newlineRaw = R . modify $ \sc ->
350+ let requestedDel = scRequestedDelimiter sc
351+ builderSoFar = scBuilder sc
352+ in sc
353+ { scBuilder = case requestedDel of
354+ AfterNewline -> builderSoFar
355+ RequestedNewline -> builderSoFar
356+ VeryBeginning -> builderSoFar
357+ _ -> builderSoFar <> "\n",
358+ scColumn = 0,
359+ scIndent = 0,
360+ scThisLineSpans = [],
361+ scRequestedDelimiter = case scRequestedDelimiter sc of
362+ AfterNewline -> RequestedNewline
363+ RequestedNewline -> RequestedNewline
364+ VeryBeginning -> VeryBeginning
365+ _ -> AfterNewline
366+ }
187367
188−ensureIndent :: R ()
189−ensureIndent = do
190− traceR "ensure_indent" Nothing
191− i <- R (asks rcIndent)
192− c <- R (gets scColumn)
193− when (c < i) $
194− spit (T.replicate (i - c) " ")
368+-- | Return 'True' if we should print record dot syntax.
369+useRecordDot :: R Bool
370+useRecordDot = R (asks rcUseRecDot)
195371
196372-- | Increase indentation level by one indentation step for the inner
197373-- computation. 'inci' should be used when a part of code must be more
198374-- indented relative to the parts outside of 'inci' in order for the output
199375-- to be valid Haskell. When layout is single-line there is no obvious
200376-- effect, but with multi-line layout correct indentation levels matter.
201−
202377inci :: R () -> R ()
203−inci m' = do
204− traceR "inci_before" Nothing
205− let R m = traceR "inci_inside" Nothing >> m'
206− modRC rc = rc
378+inci (R m) = R (local modRC m)
379+ where
380+ modRC rc =
381+ rc
207382 { rcIndent = rcIndent rc + indentStep
208383 }
209− R (local modRC m)
210− traceR "inci_ended" Nothing
211384
212385-- | Set indentation level for the inner computation equal to current
213386-- column. This makes sure that the entire inner block is uniformly
214−-- \"shifted\" to the right. Only works (and makes sense) when enclosing
215−-- layout is multi-line.
216−
387+-- \"shifted\" to the right.
217388sitcc :: R () -> R ()
218−sitcc m' = do
219− traceR "sitcc_before" Nothing
389+sitcc (R m) = do
390+ requestedDel <- R (gets scRequestedDelimiter)
220391 i <- R (asks rcIndent)
221392 c <- R (gets scColumn)
222− let R m = traceR "sitcc_inside" Nothing >> m'
223− modRC rc = rc
224− { rcIndent = max i c
225− }
226− vlayout m' (R (local modRC m))
227− traceR "sitcc_ended" Nothing
393+ let modRC rc =
394+ rc
395+ { rcIndent = max i (c + bool 0 1 (requestedDel == RequestedSpace))
396+ }
397+ R (local modRC m)
228398
229399-- | Set 'Layout' for internal computation.
230−
231400enterLayout :: Layout -> R () -> R ()
232−enterLayout l (R m) = do
233− let label =
234− case l of
235− SingleLine -> "single_line"
236− MultiLine -> "multi_line"
237− traceR ("lstart_" ++ label) Nothing
238− let modRC rc = rc
401+enterLayout l (R m) = R (local modRC m)
402+ where
403+ modRC rc =
404+ rc
239405 { rcLayout = l
240406 }
241− x <- R (local modRC m)
242− traceR ("lend_" ++ label) Nothing
243− return x
244407
245408-- | Do one or another thing depending on current 'Layout'.
246−
247−vlayout
248− :: R a -- ^ Single line
249− -> R a -- ^ Multi line
250− -> R a
409+vlayout ::
410+ -- | Single line
411+ R a ->
412+ -- | Multi line
413+ R a ->
414+ R a
251415vlayout sline mline = do
252− l <- R (asks rcLayout)
416+ l <- getLayout
253417 case l of
254418 SingleLine -> sline
255419 MultiLine -> mline
256420
421+-- | Get current 'Layout'.
422+getLayout :: R Layout
423+getLayout = R (asks rcLayout)
424+
257425----------------------------------------------------------------------------
258426-- Special helpers for comment placement
259427
428+-- | Register a comment line for outputting. It will be inserted right
429+-- before next newline. When the comment goes after something else on the
430+-- same line, a space will be inserted between preceding text and the
431+-- comment when necessary.
432+registerPendingCommentLine ::
433+ -- | Comment position
434+ CommentPosition ->
435+ -- | 'Text' to output
436+ Text ->
437+ R ()
438+registerPendingCommentLine position text = R $ do
439+ modify $ \sc ->
440+ sc
441+ { scPendingComments = (position, text) : scPendingComments sc
442+ }
443+
260444-- | Drop elements that begin before or at the same place as given
261445-- 'SrcSpan'.
262−
263−trimSpanStream
264− :: RealSrcSpan -- ^ Reference span
265− -> R ()
446+trimSpanStream ::
447+ -- | Reference span
448+ RealSrcSpan ->
449+ R ()
266450trimSpanStream ref = do
267451 let leRef :: RealSrcSpan -> Bool
268452 leRef x = realSrcSpanStart x <= realSrcSpanStart ref
269− R . modify $ \sc -> sc
270− { scSpanStream = coerce (dropWhile leRef) (scSpanStream sc)
271− }
453+ R . modify $ \sc ->
454+ sc
455+ { scSpanStream = coerce (dropWhile leRef) (scSpanStream sc)
456+ }
272457
273458-- | Get location of next element in AST.
274−
275459nextEltSpan :: R (Maybe RealSrcSpan)
276460nextEltSpan = listToMaybe . coerce <$> R (gets scSpanStream)
277461
278462-- | Pop a 'Comment' from the 'CommentStream' if given predicate is
279463-- satisfied and there are comments in the stream.
280−
281−popComment
282− :: (RealLocated Comment -> Bool)
283− -> R (Maybe (RealLocated Comment))
464+popComment ::
465+ (RealLocated Comment -> Bool) ->
466+ R (Maybe (RealLocated Comment))
284467popComment f = R $ do
285468 CommentStream cstream <- gets scCommentStream
286469 case cstream of
287470 [] -> return Nothing
288− (x:xs) ->
471+ (x : xs) ->
289472 if f x
290− then Just x <$ modify (\sc -> sc
291− { scCommentStream = CommentStream xs
292− })
473+ then
474+ Just x
475+ <$ modify
476+ ( \sc ->
477+ sc
478+ { scCommentStream = CommentStream xs
479+ }
480+ )
293481 else return Nothing
294482
295−-- | Return 'True' if there are more comments in the 'CommentStream'.
296−
297−hasMoreComments :: R Bool
298−hasMoreComments = R $ do
299− CommentStream cstream <- gets scCommentStream
300− (return . not . null) cstream
301−
302−-- | Current indentation level.
303−
304−getIndent :: R Int
305−getIndent = R (asks rcIndent)
306−
307−-- | Set indentation level for the given computation.
308−
309−setIndent :: Int -> R () -> R ()
310−setIndent i m' = do
311− traceR "set_indent_before" Nothing
312− let R m = traceR "set_indent_inside" Nothing >> m'
313− modRC rc = rc
314− { rcIndent = i
315− }
316− R (local modRC m)
317− traceR "set_indent_after" Nothing
318−
319−-- | Get 'RealSrcSpan' of enclosing span for given referencne span.
320−
321−getEnclosingSpan :: RealSrcSpan -> R (Maybe RealSrcSpan)
322−getEnclosingSpan r =
323− listToMaybe . dropWhile (== r) <$> R (asks rcEnclosingSpans)
483+-- | Get the first enclosing 'RealSrcSpan' that satisfies given predicate.
484+getEnclosingSpan ::
485+ -- | Predicate to use
486+ (RealSrcSpan -> Bool) ->
487+ R (Maybe RealSrcSpan)
488+getEnclosingSpan f =
489+ listToMaybe . filter f <$> R (asks rcEnclosingSpans)
324490
325491-- | Set 'RealSrcSpan' of enclosing span for the given computation.
326−
327492withEnclosingSpan :: RealSrcSpan -> R () -> R ()
328−withEnclosingSpan spn (R m) = do
329− let modRC rc = rc
493+withEnclosingSpan spn (R m) = R (local modRC m)
494+ where
495+ modRC rc =
496+ rc
330497 { rcEnclosingSpans = spn : rcEnclosingSpans rc
331498 }
332− R (local modRC m)
499+
500+-- | Get spans on this line so far.
501+thisLineSpans :: R [RealSrcSpan]
502+thisLineSpans = R (gets scThisLineSpans)
503+
504+----------------------------------------------------------------------------
505+-- Stateful markers
506+
507+-- | An auxiliary marker for keeping track of last output element.
508+data SpanMark
509+ = -- | Haddock comment
510+ HaddockSpan HaddockStyle RealSrcSpan
511+ | -- | Non-haddock comment
512+ CommentSpan RealSrcSpan
513+ | -- | A statement in a do-block and such span
514+ StatementSpan RealSrcSpan
515+
516+-- | Project 'RealSrcSpan' from 'SpanMark'.
517+spanMarkSpan :: SpanMark -> RealSrcSpan
518+spanMarkSpan = \case
519+ HaddockSpan _ s -> s
520+ CommentSpan s -> s
521+ StatementSpan s -> s
522+
523+-- | Haddock string style.
524+data HaddockStyle
525+ = -- | @-- |@
526+ Pipe
527+ | -- | @-- ^@
528+ Caret
529+ | -- | @-- *@
530+ Asterisk Int
531+ | -- | @-- $@
532+ Named String
533+
534+-- | Set span of last output comment.
535+setSpanMark ::
536+ -- | Span mark to set
537+ SpanMark ->
538+ R ()
539+setSpanMark spnMark = R . modify $ \sc ->
540+ sc
541+ { scSpanMark = Just spnMark
542+ }
543+
544+-- | Get span of last output comment.
545+getSpanMark :: R (Maybe SpanMark)
546+getSpanMark = R (gets scSpanMark)
333547
334548----------------------------------------------------------------------------
335549-- Annotations
336550
337551-- | For a given span return 'AnnKeywordId's associated with it.
338−
339−getAnns
340− :: SrcSpan
341− -> R [AnnKeywordId]
552+getAnns ::
553+ SrcSpan ->
554+ R [AnnKeywordId]
342555getAnns spn = lookupAnns spn <$> R (asks rcAnns)
343556
344557----------------------------------------------------------------------------
345−-- Debug helpers
346−
347−-- | Tracing helper.
348−
349−traceR
350− :: String -- ^ Label
351− -> Maybe Text -- ^ Output, if any
352− -> R ()
353−traceR label moutput = R $ do
354− debug <- asks rcDebug
355− i <- asks rcIndent
356− c <- gets scColumn
357− when debug . traceM . concat $
358− [ replicate i ' '
359− , unwords [ label ++ ":"
360− , "i=" ++ show i
361− , "c=" ++ show c
362− ]
363− ] ++ case moutput of
364− Nothing -> []
365− Just output -> [" out=" ++ show output]
558+-- Helpers for braces
559+
560+-- | Make the inner computation use braces around single-line layouts.
561+useBraces :: R () -> R ()
562+useBraces (R r) = R (local (\i -> i {rcCanUseBraces = True}) r)
563+
564+-- | Make the inner computation omit braces around single-line layouts.
565+dontUseBraces :: R () -> R ()
566+dontUseBraces (R r) = R (local (\i -> i {rcCanUseBraces = False}) r)
567+
568+-- | Return 'True' if we can use braces in this context.
569+canUseBraces :: R Bool
570+canUseBraces = R (asks rcCanUseBraces)
366571
367572----------------------------------------------------------------------------
368573-- Constants
369574
370575-- | Indentation step.
371−
372576indentStep :: Int
373577indentStep = 2
src/Ormolu/Printer/Meat/Common.hs+121−56
@@ -1,82 +1,108 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE OverloadedStrings #-}
33
44-- | Rendering of commonly useful bits.
5−
65module Ormolu.Printer.Meat.Common
7− ( FamilyStyle (..)
8− , p_hsmodName
9− , p_ieWrappedName
10− , p_rdrName
11− , p_qualName
12− , p_ieWildcard
13− , p_infixDefHelper
6+ ( FamilyStyle (..),
7+ p_hsmodName,
8+ p_ieWrappedName,
9+ p_rdrName,
10+ doesNotNeedExtraParens,
11+ p_qualName,
12+ p_infixDefHelper,
13+ p_hsDocString,
14+ p_hsDocName,
1415 )
1516where
1617
1718import Control.Monad
1819import Data.List (isPrefixOf)
20+import qualified Data.Text as T
1921import GHC hiding (GhcPs, IE)
20−import Module (Module (..))
2122import Name (nameStableString)
2223import OccName (OccName (..))
2324import Ormolu.Printer.Combinators
24−import Ormolu.Printer.Internal (getAnns)
25−import RdrName (RdrName (..))
25+import Ormolu.Utils
2626
2727-- | Data and type family style.
28−
2928data FamilyStyle
30− = Associated
31− | Free
29+ = -- | Declarations in type classes
30+ Associated
31+ | -- | Top-level declarations
32+ Free
3233
3334p_hsmodName :: ModuleName -> R ()
3435p_hsmodName mname = do
35− txt "module "
36+ txt "module"
37+ space
3638 atom mname
3739
3840p_ieWrappedName :: IEWrappedName RdrName -> R ()
3941p_ieWrappedName = \case
4042 IEName x -> p_rdrName x
4143 IEPattern x -> do
42− txt "pattern "
44+ txt "pattern"
45+ space
4346 p_rdrName x
4447 IEType x -> do
45− txt "type "
48+ txt "type"
49+ space
4650 p_rdrName x
4751
4852-- | Render a @'Located' 'RdrName'@.
49−
5053p_rdrName :: Located RdrName -> R ()
5154p_rdrName l@(L spn _) = located l $ \x -> do
5255 ids <- getAnns spn
53− -- NOTE Right now we're mainly interested in backticks and parentheses.
5456 let backticksWrapper =
5557 if AnnBackquote `elem` ids
5658 then backticks
5759 else id
5860 parensWrapper =
5961 if AnnOpenP `elem` ids
60− then parens
62+ then parens N
6163 else id
62− (m, avoidParens) =
64+ singleQuoteWrapper =
65+ if AnnSimpleQuote `elem` ids
66+ then \y -> do
67+ txt "'"
68+ y
69+ else id
70+ m =
6371 case x of
6472 Unqual occName ->
65− (atom occName, False)
73+ atom occName
6674 Qual mname occName ->
67− (p_qualName mname occName, False)
68− Orig (Module _ mname) occName ->
69− (p_qualName mname occName, False)
75+ p_qualName mname occName
76+ Orig _ occName ->
77+ -- This is used when GHC generates code that will be fed into
78+ -- the renamer (e.g. from deriving clauses), but where we want
79+ -- to say that something comes from given module which is not
80+ -- specified in the source code, e.g. @Prelude.map@.
81+ --
82+ -- My current understanding is that the provided module name
83+ -- serves no purpose for us and can be safely ignored.
84+ atom occName
7085 Exact name ->
71− -- NOTE I'm not sure this "stable string" is stable enough, but
72− -- it looks like this is the most robust way to tell if we're
73− -- looking at exactly this piece of built-in syntax.
74− ( atom name
75− , "$ghc-prim$GHC.Tuple$" `isPrefixOf` nameStableString name
76− )
77− if avoidParens
78− then m
79− else parensWrapper (backticksWrapper m)
86+ atom name
87+ m' = backticksWrapper (singleQuoteWrapper m)
88+ if doesNotNeedExtraParens x
89+ then m'
90+ else parensWrapper m'
91+
92+-- | Whether given name should not have parentheses around it. This is used
93+-- to detect e.g. tuples for which annotations will indicate parentheses,
94+-- but the parentheses are already part of the symbol, so no extra layer of
95+-- parentheses should be added. It also detects the [] literal.
96+doesNotNeedExtraParens :: RdrName -> Bool
97+doesNotNeedExtraParens = \case
98+ Exact name ->
99+ let s = nameStableString name
100+ in -- I'm not sure this "stable string" is stable enough, but it looks
101+ -- like this is the most robust way to tell if we're looking at
102+ -- exactly this piece of built-in syntax.
103+ ("$ghc-prim$GHC.Tuple$" `isPrefixOf` s)
104+ || ("$ghc-prim$GHC.Types$[]" `isPrefixOf` s)
105+ _ -> False
80106
81107p_qualName :: ModuleName -> OccName -> R ()
82108p_qualName mname occName = do
@@ -84,37 +110,76 @@ p_qualName mname occName = do
84110 txt "."
85111 atom occName
86112
87−p_ieWildcard :: IEWildcard -> R ()
88−p_ieWildcard = \case
89− NoIEWildcard -> return ()
90− IEWildcard n -> parens (atom n)
91−
92113-- | A helper for formatting infix constructions in lhs of definitions.
93−
94−p_infixDefHelper
95− :: Bool -- ^ Whether to format in infix style
96− -> (R () -> R ()) -- ^ Indentation-bumping wrapper
97− -> R () -- ^ How to print the operator\/name
98− -> [R ()] -- ^ How to print the arguments
99− -> R ()
100−p_infixDefHelper isInfix inci' name args =
114+p_infixDefHelper ::
115+ -- | Whether to format in infix style
116+ Bool ->
117+ -- | Whether to bump indentation for arguments
118+ Bool ->
119+ -- | How to print the operator\/name
120+ R () ->
121+ -- | How to print the arguments
122+ [R ()] ->
123+ R ()
124+p_infixDefHelper isInfix indentArgs name args =
101125 case (isInfix, args) of
102− (True, p0:p1:ps) -> do
126+ (True, p0 : p1 : ps) -> do
103127 let parens' =
104128 if null ps
105129 then id
106− else parens
130+ else parens N
107131 parens' $ do
108132 p0
109− space
110− name
111133 breakpoint
112− inci' p1
113− unless (null ps) . inci' $ do
134+ inci . sitcc $ do
135+ name
136+ space
137+ p1
138+ unless (null ps) . inciIf indentArgs $ do
114139 breakpoint
115− velt' ps
140+ sitcc (sep breakpoint sitcc ps)
116141 (_, ps) -> do
117142 name
118143 unless (null ps) $ do
119144 breakpoint
120− inci' (velt' args)
145+ inciIf indentArgs $ sitcc (sep breakpoint sitcc args)
146+
147+-- | Print a Haddock.
148+p_hsDocString ::
149+ -- | Haddock style
150+ HaddockStyle ->
151+ -- | Finish the doc string with a newline
152+ Bool ->
153+ -- | The doc string to render
154+ LHsDocString ->
155+ R ()
156+p_hsDocString hstyle needsNewline (L l str) = do
157+ let isCommentSpan = \case
158+ HaddockSpan _ _ -> True
159+ CommentSpan _ -> True
160+ _ -> False
161+ goesAfterComment <- maybe False isCommentSpan <$> getSpanMark
162+ -- Make sure the Haddock is separated by a newline from other comments.
163+ when goesAfterComment newline
164+ forM_ (zip (splitDocString str) (True : repeat False)) $ \(x, isFirst) -> do
165+ if isFirst
166+ then case hstyle of
167+ Pipe -> txt "-- |"
168+ Caret -> txt "-- ^"
169+ Asterisk n -> txt ("-- " <> T.replicate n "*")
170+ Named name -> p_hsDocName name
171+ else newline >> txt "--"
172+ space
173+ unless (T.null x) (txt x)
174+ when needsNewline newline
175+ case l of
176+ UnhelpfulSpan _ ->
177+ -- It's often the case that the comment itself doesn't have a span
178+ -- attached to it and instead its location can be obtained from
179+ -- nearest enclosing span.
180+ getEnclosingSpan (const True) >>= mapM_ (setSpanMark . HaddockSpan hstyle)
181+ RealSrcSpan spn -> setSpanMark (HaddockSpan hstyle spn)
182+
183+-- | Print anchor of named doc section.
184+p_hsDocName :: String -> R ()
185+p_hsDocName name = txt ("-- $" <> T.pack name)
src/Ormolu/Printer/Meat/Declaration.hs+283−77
@@ -1,17 +1,21 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE OverloadedStrings #-}
23{-# LANGUAGE PatternSynonyms #-}
34{-# LANGUAGE RecordWildCards #-}
5+{-# LANGUAGE ViewPatterns #-}
46
57-- | Rendering of declarations.
6−
78module Ormolu.Printer.Meat.Declaration
8− ( p_hsDecls
9− , p_hsDecl
9+ ( p_hsDecls,
10+ p_hsDeclsRespectGrouping,
1011 )
1112where
1213
13−import Control.Monad (forM_)
14−import GHC
14+import Data.List (sort)
15+import Data.List.NonEmpty (NonEmpty (..), (<|))
16+import qualified Data.List.NonEmpty as NE
17+import GHC hiding (InlinePragma)
18+import OccName (occNameFS)
1519import Ormolu.Printer.Combinators
1620import Ormolu.Printer.Meat.Common
1721import Ormolu.Printer.Meat.Declaration.Annotation
@@ -21,48 +25,116 @@ import Ormolu.Printer.Meat.Declaration.Default
2125import Ormolu.Printer.Meat.Declaration.Foreign
2226import Ormolu.Printer.Meat.Declaration.Instance
2327import Ormolu.Printer.Meat.Declaration.RoleAnnotation
28+import Ormolu.Printer.Meat.Declaration.Rule
2429import Ormolu.Printer.Meat.Declaration.Signature
2530import Ormolu.Printer.Meat.Declaration.Splice
2631import Ormolu.Printer.Meat.Declaration.Type
2732import Ormolu.Printer.Meat.Declaration.TypeFamily
2833import Ormolu.Printer.Meat.Declaration.Value
34+import Ormolu.Printer.Meat.Declaration.Warning
2935import Ormolu.Printer.Meat.Type
3036import Ormolu.Utils
3137
32−p_hsDecls :: [LHsDecl GhcPs] -> R ()
33−p_hsDecls decls =
34− forM_ (zip decls ((Just <$> drop 1 decls) ++ [Nothing])) $
35− \(d, md) -> do
36− case md of
37− Nothing -> located d p_hsDecl
38− Just d' ->
39− if separatedDecls (unLoc d) (unLoc d')
40− then line (located d p_hsDecl)
41− else located d p_hsDecl
42−
43−p_hsDecl :: HsDecl GhcPs -> R ()
44−p_hsDecl = \case
45− TyClD NoExt x -> p_tyClDecl x
46− ValD NoExt x -> p_valDecl x
47− SigD NoExt x -> p_sigDecl x
48− InstD NoExt x -> p_instDecl x
49− DerivD NoExt x -> p_derivDecl x
50− DefD NoExt x -> p_defaultDecl x
51− ForD NoExt x -> p_foreignDecl x
52− WarningD _ _ -> notImplemented "WarningD"
53− AnnD NoExt x -> p_annDecl x
54− RuleD _ _ -> notImplemented "RuleD"
55− SpliceD NoExt x -> p_spliceDecl x
56− DocD _ _ -> notImplemented "DocD"
57− RoleAnnotD NoExt x -> p_roleAnnot x
58− XHsDecl _ -> notImplemented "XHsDecl"
59−
60−p_tyClDecl :: TyClDecl GhcPs -> R ()
61−p_tyClDecl = \case
62− FamDecl NoExt x -> p_famDecl Free x
63− SynDecl {..} -> p_synDecl tcdLName tcdTyVars tcdRhs
38+data UserGrouping
39+ = -- | Always put newlines where we think they should be
40+ Disregard
41+ | -- | Respect user preferences regarding grouping
42+ Respect
43+ deriving (Eq, Show)
44+
45+p_hsDecls :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
46+p_hsDecls = p_hsDecls' Disregard
47+
48+-- | Like 'p_hsDecls' but respects user choices regarding grouping. If the
49+-- user omits newlines between declarations, we also omit them in most
50+-- cases, except when said declarations have associated Haddocks.
51+--
52+-- Does some normalization (compress subsequent newlines into a single one)
53+p_hsDeclsRespectGrouping :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
54+p_hsDeclsRespectGrouping = p_hsDecls' Respect
55+
56+p_hsDecls' :: UserGrouping -> FamilyStyle -> [LHsDecl GhcPs] -> R ()
57+p_hsDecls' grouping style decls =
58+ sepSemi id $
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)
64+ where
65+ renderGroup = NE.toList . fmap (located' $ dontUseBraces . p_hsDecl style)
66+ renderGroupWithPrev prev curr =
67+ -- We can omit a blank line when the user didn't add one, but we must
68+ -- ensure we always add blank lines around documented declarations
69+ case grouping of
70+ Disregard ->
71+ breakpoint : renderGroup curr
72+ Respect ->
73+ if separatedByBlankNE getLoc prev curr
74+ || isDocumented prev
75+ || isDocumented curr
76+ then breakpoint : renderGroup curr
77+ else renderGroup curr
78+
79+-- | Is a declaration group documented?
80+isDocumented :: NonEmpty (LHsDecl GhcPs) -> Bool
81+isDocumented = any (isHaddock . unLoc)
82+ where
83+ isHaddock DocNext = True
84+ isHaddock DocPrev = True
85+ isHaddock _ = False
86+
87+-- | Group relevant declarations together.
88+groupDecls :: [LHsDecl GhcPs] -> [NonEmpty (LHsDecl GhcPs)]
89+groupDecls [] = []
90+groupDecls (l@(L _ DocNext) : xs) =
91+ -- If the first element is a doc string for next element, just include it
92+ -- in the next block:
93+ case groupDecls xs of
94+ [] -> [l :| []]
95+ (x : xs') -> (l <| x) : xs'
96+groupDecls (header : xs) =
97+ let (grp, rest) = flip span (zip (header : xs) xs) $ \(previous, current) ->
98+ let relevantToHdr = groupedDecls header current
99+ relevantToPrev = groupedDecls previous current
100+ isDeclSeries = declSeries previous current
101+ in isDeclSeries || relevantToHdr || relevantToPrev
102+ in (header :| map snd grp) : groupDecls (map snd rest)
103+
104+p_hsDecl :: FamilyStyle -> HsDecl GhcPs -> R ()
105+p_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 ->
118+ case docDecl of
119+ DocCommentNext str -> p_hsDocString Pipe False (noLoc str)
120+ DocCommentPrev str -> p_hsDocString Caret False (noLoc str)
121+ DocCommentNamed name str -> p_hsDocString (Named name) False (noLoc str)
122+ DocGroup n str -> p_hsDocString (Asterisk n) False (noLoc str)
123+ RoleAnnotD NoExtField x -> p_roleAnnot x
124+ KindSigD NoExtField s -> p_standaloneKindSig s
125+ XHsDecl x -> noExtCon x
126+
127+p_tyClDecl :: FamilyStyle -> TyClDecl GhcPs -> R ()
128+p_tyClDecl style = \case
129+ FamDecl NoExtField x -> p_famDecl style x
130+ SynDecl {..} -> p_synDecl tcdLName tcdFixity tcdTyVars tcdRhs
64131 DataDecl {..} ->
65− p_dataDecl Associated tcdLName (tyVarsToTypes tcdTyVars) tcdDataDefn
132+ p_dataDecl
133+ Associated
134+ tcdLName
135+ (tyVarsToTypes tcdTyVars)
136+ tcdFixity
137+ tcdDataDefn
66138 ClassDecl {..} ->
67139 p_classDecl
68140 tcdCtxt
@@ -74,48 +146,182 @@ p_tyClDecl = \case
74146 tcdMeths
75147 tcdATs
76148 tcdATDefs
77− XTyClDecl {} -> notImplemented "XTyClDecl"
149+ tcdDocs
150+ XTyClDecl x -> noExtCon x
78151
79−p_instDecl :: InstDecl GhcPs -> R ()
80−p_instDecl = \case
81− ClsInstD NoExt x -> p_clsInstDecl x
82− TyFamInstD NoExt x -> p_tyFamInstDecl Free x
83− DataFamInstD NoExt x -> p_dataFamInstDecl Free x
84− XInstDecl _ -> notImplemented "XInstDecl"
152+p_instDecl :: FamilyStyle -> InstDecl GhcPs -> R ()
153+p_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
85158
86159p_derivDecl :: DerivDecl GhcPs -> R ()
87160p_derivDecl = \case
88− d@DerivDecl {..} -> p_standaloneDerivDecl d
89− XDerivDecl _ -> notImplemented "XDerivDecl standalone deriving"
90−
91−-- | Determine if these declarations should be separated by a blank line.
92−
93−separatedDecls
94− :: HsDecl GhcPs
95− -> HsDecl GhcPs
96− -> Bool
97−separatedDecls (TypeSignature n) (FunctionBody n') = n /= n'
98−separatedDecls (FunctionBody n) x | Just n' <- isPragma x = n /= n'
99−separatedDecls x y | Just n <- isPragma x, Just n' <- isPragma y = n /= n'
100−separatedDecls x (TypeSignature n') | Just n <- isPragma x = n /= n'
101−separatedDecls _ _ = True
102−
103−isPragma
104− :: HsDecl GhcPs
105− -> (Maybe RdrName)
161+ d@DerivDecl {} -> p_standaloneDerivDecl d
162+ XDerivDecl x -> noExtCon x
163+
164+-- | Determine if these declarations should be grouped together.
165+groupedDecls ::
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 ->
202+ Bool
203+declSeries (L _ x) (L _ y) =
204+ case (x, y) of
205+ ( SigD NoExtField (TypeSig NoExtField _ _),
206+ SigD NoExtField (TypeSig NoExtField _ _)
207+ ) -> True
208+ _ -> False
209+
210+intersects :: Ord a => [a] -> [a] -> Bool
211+intersects a b = go (sort a) (sort b)
212+ where
213+ go :: Ord a => [a] -> [a] -> Bool
214+ go _ [] = False
215+ go [] _ = False
216+ go (x : xs) (y : ys)
217+ | x < y = go xs (y : ys)
218+ | x > y = go (x : xs) ys
219+ | otherwise = True
220+
221+isPragma ::
222+ HsDecl GhcPs ->
223+ Maybe [RdrName]
106224isPragma = \case
107− InlinePragma n -> Just n
108− SpecializePragma n -> Just n
109− SCCPragma n -> Just n
225+ InlinePragma n -> Just [n]
226+ SpecializePragma n -> Just [n]
227+ SCCPragma n -> Just [n]
228+ AnnTypePragma n -> Just [n]
229+ AnnValuePragma n -> Just [n]
230+ WarningPragma n -> Just n
110231 _ -> Nothing
111232
112−pattern TypeSignature
113− , FunctionBody
114− , InlinePragma
115− , SpecializePragma
116− , SCCPragma :: RdrName -> HsDecl GhcPs
117−pattern TypeSignature n <- SigD NoExt (TypeSig NoExt ((L _ n):_) _)
118−pattern FunctionBody n <- ValD NoExt (FunBind NoExt (L _ n) _ _ _)
119−pattern InlinePragma n <- SigD NoExt (InlineSig NoExt (L _ n) _)
120−pattern SpecializePragma n <- SigD NoExt (SpecSig NoExt (L _ n) _ _)
121−pattern SCCPragma n <- SigD NoExt (SCCFunSig NoExt _ (L _ n) _)
233+-- Declarations that do not refer to names
234+
235+pattern Splice :: HsDecl GhcPs
236+pattern Splice <- SpliceD NoExtField (SpliceDecl NoExtField _ _)
237+
238+-- Declarations referring to a single name
239+
240+pattern
241+ InlinePragma,
242+ SpecializePragma,
243+ SCCPragma,
244+ AnnTypePragma,
245+ AnnValuePragma,
246+ Pattern,
247+ DataDeclaration,
248+ ClassDeclaration,
249+ KindSignature,
250+ FamilyDeclaration ::
251+ RdrName -> HsDecl GhcPs
252+pattern InlinePragma n <- SigD NoExtField (InlineSig NoExtField (L _ n) _)
253+pattern SpecializePragma n <- SigD NoExtField (SpecSig NoExtField (L _ n) _ _)
254+pattern SCCPragma n <- SigD NoExtField (SCCFunSig NoExtField _ (L _ n) _)
255+pattern AnnTypePragma n <- AnnD NoExtField (HsAnnotation NoExtField _ (TypeAnnProvenance (L _ n)) _)
256+pattern AnnValuePragma n <- AnnD NoExtField (HsAnnotation NoExtField _ (ValueAnnProvenance (L _ n)) _)
257+pattern Pattern n <- ValD NoExtField (PatSynBind NoExtField (PSB _ (L _ n) _ _ _))
258+pattern DataDeclaration n <- TyClD NoExtField (DataDecl NoExtField (L _ n) _ _ _)
259+pattern ClassDeclaration n <- TyClD NoExtField (ClassDecl NoExtField _ (L _ n) _ _ _ _ _ _ _ _)
260+pattern KindSignature n <- KindSigD NoExtField (StandaloneKindSig NoExtField (L _ n) _)
261+pattern FamilyDeclaration n <- TyClD NoExtField (FamDecl NoExtField (FamilyDecl NoExtField _ (L _ n) _ _ _ _))
262+
263+-- Declarations which can refer to multiple names
264+
265+pattern
266+ TypeSignature,
267+ DefaultSignature,
268+ FunctionBody,
269+ PatternSignature,
270+ WarningPragma ::
271+ [RdrName] -> HsDecl GhcPs
272+pattern TypeSignature n <- (sigRdrNames -> Just n)
273+pattern DefaultSignature n <- (defSigRdrNames -> Just n)
274+pattern FunctionBody n <- (funRdrNames -> Just n)
275+pattern PatternSignature n <- (patSigRdrNames -> Just n)
276+pattern WarningPragma n <- (warnSigRdrNames -> Just n)
277+
278+pattern DocNext, DocPrev :: HsDecl GhcPs
279+pattern DocNext <- (DocD NoExtField (DocCommentNext _))
280+pattern DocPrev <- (DocD NoExtField (DocCommentPrev _))
281+
282+sigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
283+sigRdrNames (SigD NoExtField (TypeSig NoExtField ns _)) = Just $ map unLoc ns
284+sigRdrNames (SigD NoExtField (ClassOpSig NoExtField _ ns _)) = Just $ map unLoc ns
285+sigRdrNames (SigD NoExtField (PatSynSig NoExtField ns _)) = Just $ map unLoc ns
286+sigRdrNames _ = Nothing
287+
288+defSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
289+defSigRdrNames (SigD NoExtField (ClassOpSig NoExtField True ns _)) = Just $ map unLoc ns
290+defSigRdrNames _ = Nothing
291+
292+funRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
293+funRdrNames (ValD NoExtField (FunBind NoExtField (L _ n) _ _ _)) = Just [n]
294+funRdrNames (ValD NoExtField (PatBind NoExtField (L _ n) _ _)) = Just $ patBindNames n
295+funRdrNames _ = Nothing
296+
297+patSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
298+patSigRdrNames (SigD NoExtField (PatSynSig NoExtField ns _)) = Just $ map unLoc ns
299+patSigRdrNames _ = Nothing
300+
301+warnSigRdrNames :: HsDecl GhcPs -> Maybe [RdrName]
302+warnSigRdrNames (WarningD NoExtField (Warnings NoExtField _ ws)) = Just $
303+ flip concatMap ws $ \case
304+ L _ (Warning NoExtField ns _) -> map unLoc ns
305+ L _ (XWarnDecl x) -> noExtCon x
306+warnSigRdrNames _ = Nothing
307+
308+patBindNames :: Pat GhcPs -> [RdrName]
309+patBindNames (TuplePat NoExtField ps _) = concatMap (patBindNames . unLoc) ps
310+patBindNames (VarPat NoExtField (L _ n)) = [n]
311+patBindNames (WildPat NoExtField) = []
312+patBindNames (LazyPat NoExtField (L _ p)) = patBindNames p
313+patBindNames (BangPat NoExtField (L _ p)) = patBindNames p
314+patBindNames (ParPat NoExtField (L _ p)) = patBindNames p
315+patBindNames (ListPat NoExtField ps) = concatMap (patBindNames . unLoc) ps
316+patBindNames (AsPat NoExtField (L _ n) (L _ p)) = n : patBindNames p
317+patBindNames (SumPat NoExtField (L _ p) _ _) = patBindNames p
318+patBindNames (ViewPat NoExtField _ (L _ p)) = patBindNames p
319+patBindNames (SplicePat NoExtField _) = []
320+patBindNames (LitPat NoExtField _) = []
321+patBindNames (SigPat _ (L _ p) _) = patBindNames p
322+patBindNames (NPat NoExtField _ _ _) = []
323+patBindNames (NPlusKPat NoExtField (L _ n) _ _ _ _) = [n]
324+patBindNames (ConPatIn _ d) = concatMap (patBindNames . unLoc) (hsConPatArgs d)
325+patBindNames ConPatOut {} = notImplemented "ConPatOut" -- created by renamer
326+patBindNames (CoPat NoExtField _ p _) = patBindNames p
327+patBindNames (XPat x) = noExtCon x
src/Ormolu/Printer/Meat/Declaration.hs-boot+5−5
@@ -1,12 +1,12 @@
11module Ormolu.Printer.Meat.Declaration
2− ( p_hsDecls
3− , p_hsDecl
2+ ( p_hsDecls,
3+ p_hsDeclsRespectGrouping,
44 )
55where
66
77import GHC
88import Ormolu.Printer.Combinators
9+import Ormolu.Printer.Meat.Common
910
10−p_hsDecls :: [LHsDecl GhcPs] -> R ()
11−
12−p_hsDecl :: HsDecl GhcPs -> R ()
11+p_hsDecls :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
12+p_hsDeclsRespectGrouping :: FamilyStyle -> [LHsDecl GhcPs] -> R ()
src/Ormolu/Printer/Meat/Declaration/Annotation.hs+5−6
@@ -1,8 +1,8 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE OverloadedStrings #-}
33
44module Ormolu.Printer.Meat.Declaration.Annotation
5− ( p_annDecl
5+ ( p_annDecl,
66 )
77where
88
@@ -10,18 +10,17 @@ import GHC
1010import Ormolu.Printer.Combinators
1111import Ormolu.Printer.Meat.Common
1212import Ormolu.Printer.Meat.Declaration.Value
13−import Ormolu.Utils
1413
1514p_annDecl :: AnnDecl GhcPs -> R ()
1615p_annDecl = \case
17− HsAnnotation NoExt _ annProv expr -> pragma "ANN" $ do
16+ HsAnnotation NoExtField _ annProv expr -> pragma "ANN" . inci $ do
1817 p_annProv annProv
1918 breakpoint
2019 located expr p_hsExpr
21− XAnnDecl {} -> notImplemented "XAnnDecl"
20+ XAnnDecl x -> noExtCon x
2221
2322p_annProv :: AnnProvenance (IdP GhcPs) -> R ()
2423p_annProv = \case
2524 ValueAnnProvenance name -> p_rdrName name
26− TypeAnnProvenance name -> p_rdrName name
25+ TypeAnnProvenance name -> txt "type" >> space >> p_rdrName name
2726 ModuleAnnProvenance -> txt "module"
src/Ormolu/Printer/Meat/Declaration/Class.hs+67−79
@@ -1,11 +1,10 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
44
55-- | Rendering of type class declarations.
6−
76module Ormolu.Printer.Meat.Declaration.Class
8− ( p_classDecl
7+ ( p_classDecl,
98 )
109where
1110
@@ -13,96 +12,85 @@ import Class
1312import Control.Arrow
1413import Control.Monad
1514import Data.Foldable
16−import Data.Function
17−import Data.List (sortBy)
15+import Data.List (sortOn)
16+import GHC
1817import Ormolu.Printer.Combinators
19−import Ormolu.Printer.Meat.Declaration.Signature
20−import Ormolu.Printer.Meat.Declaration.Value
21−import Ormolu.Printer.Meat.Declaration.TypeFamily
2218import Ormolu.Printer.Meat.Common
19+import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration
2320import Ormolu.Printer.Meat.Type
24−import Ormolu.Utils
25−import GHC
26−import RdrName (RdrName (..))
27−import SrcLoc (Located, combineSrcSpans)
2821
29−p_classDecl
30− :: LHsContext GhcPs
31− -> Located RdrName
32− -> LHsQTyVars GhcPs
33− -> LexicalFixity
34− -> [Located (FunDep (Located RdrName))]
35− -> [LSig GhcPs]
36− -> LHsBinds GhcPs
37− -> [LFamilyDecl GhcPs]
38− -> [LTyFamDefltEqn GhcPs]
39− -> R ()
40−p_classDecl ctx name tvars fixity fdeps csigs cdefs cats catdefs = do
41− let HsQTvs {..} = tvars
42− variableSpans = foldr (combineSrcSpans . getLoc) noSrcSpan hsq_explicit
43− signatureSpans = getLoc name `combineSrcSpans` variableSpans
44− dependencySpans = foldr (combineSrcSpans . getLoc) noSrcSpan fdeps
45− combinedSpans =
46− getLoc ctx `combineSrcSpans`
47− signatureSpans `combineSrcSpans`
48− dependencySpans
49− txt "class "
50− sitcc $ do
51− switchLayout combinedSpans $ p_classContext ctx
52− switchLayout signatureSpans $ do
53− p_infixDefHelper
54− (isInfix fixity)
55− inci
56− (p_rdrName name)
57− (located' p_hsTyVarBndr <$> hsq_explicit)
58− switchLayout combinedSpans $ p_classFundeps fdeps
59− -- GHC's AST does not necessarily store each kind of element in source
60− -- location order. This happens because different declarations are stored in
61− -- different lists. Consequently, to get all the declarations in proper order,
62− -- they need to be manually sorted.
63− let sigs = (getLoc &&& located' p_sigDecl) <$> csigs
64− defs = (getLoc &&& located' p_valDecl) <$> cdefs
65− tyfam_decls = (getLoc &&& located' (p_famDecl Associated)) <$> cats
66− tyfam_defs = (getLoc &&& located' p_famDefDecl) <$> catdefs
67− decls =
68− snd <$>
69− sortBy
70− (compare `on` fst)
71− (sigs <> toList defs <> tyfam_decls <> tyfam_defs)
72− if not (null decls)
73− then do
74− txt " where"
75− newline
76− inci (sequence_ decls)
77− else newline
22+p_classDecl ::
23+ LHsContext GhcPs ->
24+ Located RdrName ->
25+ LHsQTyVars GhcPs ->
26+ LexicalFixity ->
27+ [Located (FunDep (Located RdrName))] ->
28+ [LSig GhcPs] ->
29+ LHsBinds GhcPs ->
30+ [LFamilyDecl GhcPs] ->
31+ [LTyFamDefltDecl GhcPs] ->
32+ [LDocDecl] ->
33+ R ()
34+p_classDecl ctx name HsQTvs {..} fixity fdeps csigs cdefs cats catdefs cdocs = do
35+ let variableSpans = getLoc <$> hsq_explicit
36+ signatureSpans = getLoc name : variableSpans
37+ dependencySpans = getLoc <$> fdeps
38+ combinedSpans = getLoc ctx : (signatureSpans ++ dependencySpans)
39+ -- GHC's AST does not necessarily store each kind of element in source
40+ -- location order. This happens because different declarations are stored
41+ -- in different lists. Consequently, to get all the declarations in proper
42+ -- order, they need to be manually sorted.
43+ sigs = (getLoc &&& fmap (SigD NoExtField)) <$> csigs
44+ vals = (getLoc &&& fmap (ValD NoExtField)) <$> toList cdefs
45+ tyFams = (getLoc &&& fmap (TyClD NoExtField . FamDecl NoExtField)) <$> cats
46+ docs = (getLoc &&& fmap (DocD NoExtField)) <$> cdocs
47+ tyFamDefs =
48+ ( getLoc &&& fmap (InstD NoExtField . TyFamInstD NoExtField)
49+ )
50+ <$> catdefs
51+ allDecls =
52+ snd <$> sortOn fst (sigs <> vals <> tyFams <> tyFamDefs <> docs)
53+ txt "class"
54+ switchLayout combinedSpans $ do
55+ breakpoint
56+ inci $ do
57+ p_classContext ctx
58+ switchLayout signatureSpans $
59+ p_infixDefHelper
60+ (isInfix fixity)
61+ True
62+ (p_rdrName name)
63+ (located' p_hsTyVarBndr <$> hsq_explicit)
64+ inci (p_classFundeps fdeps)
65+ unless (null allDecls) $ do
66+ breakpoint
67+ txt "where"
68+ unless (null allDecls) $ do
69+ breakpoint -- Ensure whitespace is added after where clause.
70+ inci (p_hsDeclsRespectGrouping Associated allDecls)
71+p_classDecl _ _ (XLHsQTyVars c) _ _ _ _ _ _ _ = noExtCon c
7872
7973p_classContext :: LHsContext GhcPs -> R ()
80−p_classContext ctx = unless (null (unLoc ctx)) $ do
74+p_classContext ctx = unless (null (unLoc ctx)) $ do
8175 located ctx p_hsContext
76+ space
77+ txt "=>"
8278 breakpoint
83− txt "=> "
8479
8580p_classFundeps :: [Located (FunDep (Located RdrName))] -> R ()
8681p_classFundeps fdeps = unless (null fdeps) $ do
8782 breakpoint
88− txt "| "
89− velt $ withSep comma (located' p_funDep) fdeps
90−
91−p_famDefDecl :: TyFamDefltEqn GhcPs -> R ()
92−p_famDefDecl FamEqn {..} = do
93− txt "type"
94− breakpoint
95− let eqn = FamEqn { feqn_pats = tyVarsToTypes feqn_pats, .. }
96− hsib = HsIB { hsib_ext = NoExt, hsib_body = eqn }
97− inci (p_tyFamInstEqn hsib)
98− newline
99−p_famDefDecl XFamEqn {} = notImplemented "XFamEqn"
83+ txt "|"
84+ space
85+ inci $ sep commaDel (sitcc . located' p_funDep) fdeps
10086
10187p_funDep :: FunDep (Located RdrName) -> R ()
10288p_funDep (before, after) = do
103− spaceSep p_rdrName before
104− txt " -> "
105− spaceSep p_rdrName after
89+ sep space p_rdrName before
90+ space
91+ txt "->"
92+ space
93+ sep space p_rdrName after
10694
10795----------------------------------------------------------------------------
10896-- Helpers
src/Ormolu/Printer/Meat/Declaration/Data.hs+192−98
@@ -1,127 +1,194 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
44
55-- | Renedring of data type declarations.
6−
76module Ormolu.Printer.Meat.Declaration.Data
8− ( p_dataDecl
7+ ( p_dataDecl,
98 )
109where
1110
1211import Control.Monad
13−import Data.List.NonEmpty (NonEmpty (..))
14−import Data.Maybe (isJust)
12+import Data.Maybe (isJust, maybeToList)
1513import GHC
1614import Ormolu.Printer.Combinators
1715import Ormolu.Printer.Meat.Common
1816import Ormolu.Printer.Meat.Type
1917import Ormolu.Utils
20−import RdrName (RdrName (..))
21−import SrcLoc (Located)
2218
23−p_dataDecl
24− :: FamilyStyle -- ^ Whether to format as data family
25− -> Located RdrName -- ^ Type constructor
26− -> [LHsType GhcPs] -- ^ Type patterns
27− -> HsDataDefn GhcPs -- ^ Data definition
28− -> R ()
29−p_dataDecl style name tpats HsDataDefn {..} = do
19+p_dataDecl ::
20+ -- | Whether to format as data family
21+ FamilyStyle ->
22+ -- | Type constructor
23+ Located RdrName ->
24+ -- | Type patterns
25+ [LHsType GhcPs] ->
26+ -- | Lexical fixity
27+ LexicalFixity ->
28+ -- | Data definition
29+ HsDataDefn GhcPs ->
30+ R ()
31+p_dataDecl style name tpats fixity HsDataDefn {..} = do
3032 txt $ case dd_ND of
31− NewType -> "newtype "
32− DataType -> "data "
33− txt $ case style of
33+ NewType -> "newtype"
34+ DataType -> "data"
35+ txt $ case style of
3436 Associated -> mempty
35− Free -> "instance "
36− p_rdrName name
37− unless (null tpats) space
38− spaceSep (located' p_hsType) tpats
37+ Free -> " instance"
38+ let constructorSpans = getLoc name : fmap getLoc tpats
39+ switchLayout constructorSpans $ do
40+ breakpoint
41+ inci $
42+ p_infixDefHelper
43+ (isInfix fixity)
44+ True
45+ (p_rdrName name)
46+ (located' p_hsType <$> tpats)
3947 case dd_kindSig of
4048 Nothing -> return ()
4149 Just k -> do
4250 space
43− txt ":: "
51+ txt "::"
52+ space
4453 located k p_hsType
4554 let gadt = isJust dd_kindSig || any (isGadt . unLoc) dd_cons
4655 unless (null dd_cons) $
4756 if gadt
48− then do
49− txt " where"
50− newline
51− inci $ newlineSep (sitcc . located' p_conDecl) dd_cons
52− else switchLayout (combineSrcSpans' (getLoc name :| (getLoc <$> dd_cons))) $
53− inci $ do
57+ then inci $ do
58+ switchLayout constructorSpans $ do
5459 breakpoint
55− txt "= "
56− let sep = vlayout (txt " | ") (txt "| ")
57− velt $ withSep sep (sitcc . located' p_conDecl) dd_cons
58− newline
60+ txt "where"
61+ breakpoint
62+ sepSemi (located' (p_conDecl False)) dd_cons
63+ else switchLayout (getLoc name : (getLoc <$> dd_cons)) . inci $ do
64+ let singleConstRec = isSingleConstRec dd_cons
65+ if singleConstRec
66+ then space
67+ else
68+ if hasHaddocks dd_cons
69+ then newline
70+ else breakpoint
71+ equals
72+ space
73+ layout <- getLayout
74+ let s =
75+ if layout == MultiLine || hasHaddocks dd_cons
76+ then newline >> txt "|" >> space
77+ else space >> txt "|" >> space
78+ sitcc' =
79+ if singleConstRec
80+ then id
81+ else sitcc
82+ sep s (sitcc' . located' (p_conDecl singleConstRec)) dd_cons
83+ unless (null $ unLoc dd_derivs) breakpoint
5984 inci . located dd_derivs $ \xs ->
60− forM_ xs (line . located' p_hsDerivingClause)
61−p_dataDecl _ _ _ (XHsDataDefn NoExt) = notImplemented "XHsDataDefn"
85+ sep newline (located' p_hsDerivingClause) xs
86+p_dataDecl _ _ _ _ (XHsDataDefn x) = noExtCon x
6287
63−p_conDecl :: ConDecl GhcPs -> R ()
64−p_conDecl = \case
88+p_conDecl ::
89+ Bool ->
90+ ConDecl GhcPs ->
91+ R ()
92+p_conDecl singleConstRec = \case
6593 ConDeclGADT {..} -> do
66− spaceSep p_rdrName con_names
67− breakpoint
68− inci $ do
69− txt ":: "
70− p_forallBndrs (hsq_explicit con_qvars)
94+ mapM_ (p_hsDocString Pipe True) con_doc
95+ let conDeclSpn =
96+ fmap getLoc con_names
97+ <> [getLoc con_forall]
98+ <> conTyVarsSpans con_qvars
99+ <> maybeToList (fmap getLoc con_mb_cxt)
100+ <> conArgsSpans con_args
101+ switchLayout conDeclSpn $ do
102+ case con_names of
103+ [] -> return ()
104+ (c : cs) -> do
105+ p_rdrName c
106+ unless (null cs) . inci $ do
107+ commaDel
108+ sep commaDel p_rdrName cs
109+ inci $ do
110+ space
111+ txt "::"
112+ let interArgBreak =
113+ if hasDocStrings (unLoc con_res_ty)
114+ then newline
115+ else breakpoint
116+ interArgBreak
117+ when (unLoc con_forall) $ do
118+ p_forallBndrs ForallInvis p_hsTyVarBndr (hsq_explicit con_qvars)
119+ interArgBreak
120+ forM_ con_mb_cxt p_lhsContext
121+ case con_args of
122+ PrefixCon xs -> do
123+ sep breakpoint (located' p_hsType) xs
124+ unless (null xs) $ do
125+ space
126+ txt "->"
127+ breakpoint
128+ RecCon l -> do
129+ located l p_conDeclFields
130+ unless (null $ unLoc l) $ do
131+ space
132+ txt "->"
133+ breakpoint
134+ InfixCon _ _ -> notImplemented "InfixCon"
135+ p_hsType (unLoc con_res_ty)
136+ ConDeclH98 {..} -> do
137+ mapM_ (p_hsDocString Pipe True) con_doc
138+ let conDeclWithContextSpn =
139+ [getLoc con_forall]
140+ <> fmap getLoc con_ex_tvs
141+ <> maybeToList (fmap getLoc con_mb_cxt)
142+ <> conDeclSpn
143+ conDeclSpn =
144+ getLoc con_name : conArgsSpans con_args
145+ switchLayout conDeclWithContextSpn $ do
146+ when (unLoc con_forall) $ do
147+ p_forallBndrs ForallInvis p_hsTyVarBndr con_ex_tvs
148+ breakpoint
71149 forM_ con_mb_cxt p_lhsContext
72− case con_args of
150+ switchLayout conDeclSpn $ case con_args of
73151 PrefixCon xs -> do
74− velt' (located' p_hsType <$> xs)
75− unless (null xs) $ do
76− breakpoint
77− txt "-> "
152+ p_rdrName con_name
153+ unless (null xs) breakpoint
154+ inci . sitcc $ sep breakpoint (sitcc . located' p_hsTypePostDoc) xs
78155 RecCon l -> do
79− located l p_conDeclFields
80− unless (null $ unLoc l) $ do
81− breakpoint
82− txt "-> "
83− InfixCon _ _ -> notImplemented "InfixCon"
84− locatedVia Nothing con_res_ty p_hsType
85− ConDeclH98 {..} -> do
86− p_forallBndrs con_ex_tvs
87− forM_ con_mb_cxt p_lhsContext
88− case con_args of
89− PrefixCon xs -> do
90− p_rdrName con_name
91− unless (null xs) breakpoint
92− inci $ velt' (located' p_hsType <$> xs)
93− RecCon l -> do
94− p_rdrName con_name
95− breakpoint
96− inci $ located l p_conDeclFields
97− InfixCon x y -> do
98− located x p_hsType
99− breakpoint
100− inci $ do
101156 p_rdrName con_name
102− space
103− located y p_hsType
104− XConDecl NoExt -> notImplemented "XConDecl"
157+ breakpoint
158+ inciIf (not singleConstRec) (located l p_conDeclFields)
159+ InfixCon x y -> do
160+ located x p_hsType
161+ breakpoint
162+ inci $ do
163+ p_rdrName con_name
164+ space
165+ located y p_hsType
166+ XConDecl x -> noExtCon x
167+
168+conArgsSpans :: HsConDeclDetails GhcPs -> [SrcSpan]
169+conArgsSpans = \case
170+ PrefixCon xs ->
171+ getLoc <$> xs
172+ RecCon l ->
173+ [getLoc l]
174+ InfixCon x y ->
175+ [getLoc x, getLoc y]
105176
106−p_forallBndrs
107− :: [LHsTyVarBndr GhcPs]
108− -> R ()
109−p_forallBndrs = \case
110− [] -> return ()
111− bndrs -> do
112− txt "forall "
113− spaceSep (located' p_hsTyVarBndr) bndrs
114− txt ". "
177+conTyVarsSpans :: LHsQTyVars GhcPs -> [SrcSpan]
178+conTyVarsSpans = \case
179+ HsQTvs {..} -> getLoc <$> hsq_explicit
180+ XLHsQTyVars x -> noExtCon x
115181
116−p_lhsContext
117− :: LHsContext GhcPs
118− -> R ()
182+p_lhsContext ::
183+ LHsContext GhcPs ->
184+ R ()
119185p_lhsContext = \case
120186 L _ [] -> pure ()
121187 ctx -> do
122188 located ctx p_hsContext
189+ space
190+ txt "=>"
123191 breakpoint
124− txt "=> "
125192
126193isGadt :: ConDecl GhcPs -> Bool
127194isGadt = \case
@@ -129,30 +196,35 @@ isGadt = \case
129196 ConDeclH98 {} -> False
130197 XConDecl {} -> False
131198
132−p_hsDerivingClause
133− :: HsDerivingClause GhcPs
134− -> R ()
199+p_hsDerivingClause ::
200+ HsDerivingClause GhcPs ->
201+ R ()
135202p_hsDerivingClause HsDerivingClause {..} = do
136203 txt "deriving"
137204 let derivingWhat = located deriv_clause_tys $ \case
138205 [] -> txt "()"
139− [x] -> located (hsib_body x) p_hsType
140− xs -> parens . velt $ withSep comma (located' p_hsType . hsib_body) xs
206+ xs ->
207+ parens N $
208+ sep
209+ commaDel
210+ (sitcc . located' p_hsType . hsib_body)
211+ xs
212+ space
141213 case deriv_clause_strategy of
142214 Nothing -> do
143215 breakpoint
144216 inci derivingWhat
145− Just l -> locatedVia Nothing l $ \case
217+ Just (L _ a) -> case a of
146218 StockStrategy -> do
147− txt " stock"
219+ txt "stock"
148220 breakpoint
149221 inci derivingWhat
150222 AnyclassStrategy -> do
151− txt " anyclass"
223+ txt "anyclass"
152224 breakpoint
153225 inci derivingWhat
154226 NewtypeStrategy -> do
155− txt " newtype"
227+ txt "newtype"
156228 breakpoint
157229 inci derivingWhat
158230 ViaStrategy HsIB {..} -> do
@@ -160,8 +232,30 @@ p_hsDerivingClause HsDerivingClause {..} = do
160232 inci $ do
161233 derivingWhat
162234 breakpoint
163− txt "via "
235+ txt "via"
236+ space
164237 located hsib_body p_hsType
165− ViaStrategy (XHsImplicitBndrs NoExt) ->
166− notImplemented "XHsImplicitBndrs"
167−p_hsDerivingClause (XHsDerivingClause NoExt) = notImplemented "XHsDerivingClause"
238+ ViaStrategy (XHsImplicitBndrs x) ->
239+ noExtCon x
240+p_hsDerivingClause (XHsDerivingClause x) = noExtCon x
241+
242+----------------------------------------------------------------------------
243+-- Helpers
244+
245+isInfix :: LexicalFixity -> Bool
246+isInfix = \case
247+ Infix -> True
248+ Prefix -> False
249+
250+isSingleConstRec :: [LConDecl GhcPs] -> Bool
251+isSingleConstRec [(L _ ConDeclH98 {..})] =
252+ case con_args of
253+ RecCon _ -> True
254+ _ -> False
255+isSingleConstRec _ = False
256+
257+hasHaddocks :: [LConDecl GhcPs] -> Bool
258+hasHaddocks = any (f . unLoc)
259+ where
260+ f ConDeclH98 {..} = isJust con_doc
261+ f _ = False
src/Ormolu/Printer/Meat/Declaration/Default.hs+6−7
@@ -1,21 +1,20 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE OverloadedStrings #-}
33
44module Ormolu.Printer.Meat.Declaration.Default
5− ( p_defaultDecl
5+ ( p_defaultDecl,
66 )
77where
88
99import GHC
1010import Ormolu.Printer.Combinators
1111import Ormolu.Printer.Meat.Type
12−import Ormolu.Utils
1312
1413p_defaultDecl :: DefaultDecl GhcPs -> R ()
1514p_defaultDecl = \case
16− DefaultDecl NoExt ts -> line $ do
15+ DefaultDecl NoExtField ts -> do
1716 txt "default"
1817 breakpoint
19− inci . parens . velt $
20− withSep comma (located' p_hsType) ts
21− XDefaultDecl {} -> notImplemented "XDefaultDecl"
18+ inci . parens N $
19+ sep commaDel (sitcc . located' p_hsType) ts
20+ XDefaultDecl x -> noExtCon x
src/Ormolu/Printer/Meat/Declaration/Foreign.hs+18−16
@@ -1,9 +1,9 @@
1−{-# LANGUAGE LambdaCase #-}
2−{-# LANGUAGE NamedFieldPuns #-}
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE NamedFieldPuns #-}
33{-# LANGUAGE OverloadedStrings #-}
44
55module Ormolu.Printer.Meat.Declaration.Foreign
6− ( p_foreignDecl
6+ ( p_foreignDecl,
77 )
88where
99
@@ -15,29 +15,30 @@ import GHC
1515import Ormolu.Printer.Combinators
1616import Ormolu.Printer.Meat.Common
1717import Ormolu.Printer.Meat.Declaration.Signature
18−import Ormolu.Utils
1918
2019p_foreignDecl :: ForeignDecl GhcPs -> R ()
2120p_foreignDecl = \case
22− fd@ForeignImport {fd_fi} -> line $ do
21+ fd@ForeignImport {fd_fi} -> do
2322 p_foreignImport fd_fi
2423 p_foreignTypeSig fd
25− fd@ForeignExport {fd_fe} -> line $ do
24+ fd@ForeignExport {fd_fe} -> do
2625 p_foreignExport fd_fe
2726 p_foreignTypeSig fd
28− XForeignDecl {} -> notImplemented "XForeignDecl"
27+ XForeignDecl x -> noExtCon x
2928
3029-- | Printer for the last part of an import\/export, which is function name
3130-- and type signature.
32−
3331p_foreignTypeSig :: ForeignDecl GhcPs -> R ()
3432p_foreignTypeSig fd = do
3533 breakpoint
36− -- Switch into the layout of the signature, to allow us to pull name and
37− -- signature onto a single line.
38− inci . switchLayout (getLoc . hsib_body $ fd_sig_ty fd) $ do
39− p_rdrName (fd_name fd)
40− p_typeAscription (HsWC NoExt (fd_sig_ty fd))
34+ inci
35+ . switchLayout
36+ [ getLoc (fd_name fd),
37+ (getLoc . hsib_body . fd_sig_ty) fd
38+ ]
39+ $ do
40+ p_rdrName (fd_name fd)
41+ p_typeAscription (HsWC NoExtField (fd_sig_ty fd))
4142
4243-- | Printer for 'ForeignImport'.
4344--
@@ -51,10 +52,10 @@ p_foreignTypeSig fd = do
5152-- We also layout the identifier using the 'SourceText', because printing
5253-- with the other two fields of 'CImport' is very complicated. See the
5354-- 'Outputable' instance of 'ForeignImport' for details.
54−
5555p_foreignImport :: ForeignImport -> R ()
5656p_foreignImport (CImport cCallConv safety _ _ sourceText) = do
57− txt "foreign import "
57+ txt "foreign import"
58+ space
5859 located cCallConv atom
5960 -- Need to check for 'noLoc' for the 'safe' annotation
6061 when (isGoodSrcSpan $ getLoc safety) (space >> atom safety)
@@ -62,7 +63,8 @@ p_foreignImport (CImport cCallConv safety _ _ sourceText) = do
6263
6364p_foreignExport :: ForeignExport -> R ()
6465p_foreignExport (CExport (L loc (CExportStatic _ _ cCallConv)) sourceText) = do
65− txt "foreign export "
66+ txt "foreign export"
67+ space
6668 located (L loc cCallConv) atom
6769 located sourceText p_sourceText
6870
src/Ormolu/Printer/Meat/Declaration/Instance.hs+57−58
@@ -1,29 +1,27 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
44
55-- | Type class, type family, and data family instance declarations.
6−
76module Ormolu.Printer.Meat.Declaration.Instance
8− ( p_clsInstDecl
9− , p_tyFamInstDecl
10− , p_dataFamInstDecl
11− , p_standaloneDerivDecl
7+ ( p_clsInstDecl,
8+ p_tyFamInstDecl,
9+ p_dataFamInstDecl,
10+ p_standaloneDerivDecl,
1211 )
1312where
1413
1514import BasicTypes
1615import Control.Arrow
16+import Control.Monad
1717import Data.Foldable
18−import Data.Function
19−import Data.List (sortBy)
18+import Data.List (sortOn)
2019import GHC
2120import Ormolu.Printer.Combinators
2221import Ormolu.Printer.Meat.Common
22+import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration
2323import Ormolu.Printer.Meat.Declaration.Data
24−import Ormolu.Printer.Meat.Declaration.Signature
2524import Ormolu.Printer.Meat.Declaration.TypeFamily
26−import Ormolu.Printer.Meat.Declaration.Value
2725import Ormolu.Printer.Meat.Type
2826import Ormolu.Utils
2927
@@ -34,68 +32,68 @@ p_standaloneDerivDecl DerivDecl {..} = do
3432 txt "instance"
3533 breakpoint
3634 match_overlap_mode deriv_overlap_mode breakpoint
37− if toIndent
38− then inci typesAfterInstance
39− else typesAfterInstance
35+ inciIf toIndent typesAfterInstance
4036 txt "deriving"
37+ space
4138 case deriv_strategy of
42− Nothing -> do
43− space
39+ Nothing ->
4440 instTypes False
45− Just l -> locatedVia Nothing l $ \case
41+ Just (L _ a) -> case a of
4642 StockStrategy -> do
47− txt " stock "
43+ txt "stock "
4844 instTypes False
4945 AnyclassStrategy -> do
50− txt " anyclass "
46+ txt "anyclass "
5147 instTypes False
5248 NewtypeStrategy -> do
53− txt " newtype "
49+ txt "newtype "
5450 instTypes False
5551 ViaStrategy HsIB {..} -> do
56− txt " via"
52+ txt "via"
5753 breakpoint
5854 inci (located hsib_body p_hsType)
5955 breakpoint
6056 instTypes True
61− ViaStrategy (XHsImplicitBndrs NoExt) ->
62− notImplemented "XHsImplicitBndrs"
63− newline
57+ ViaStrategy (XHsImplicitBndrs x) ->
58+ noExtCon x
6459p_standaloneDerivDecl (XDerivDecl _) = notImplemented "XDerivDecl"
6560
6661p_clsInstDecl :: ClsInstDecl GhcPs -> R ()
6762p_clsInstDecl = \case
6863 ClsInstDecl {..} -> do
69− txt "instance "
70− match_overlap_mode cid_overlap_mode space
64+ txt "instance"
7165 case cid_poly_ty of
72− HsIB {..} -> sitcc (located hsib_body p_hsType)
73− XHsImplicitBndrs NoExt -> notImplemented "XHsImplicitBndrs"
74− -- GHC's AST does not necessarily store each kind of element in source
75− -- location order. This happens because different declarations are stored in
76− -- different lists. Consequently, to get all the declarations in proper
77− -- order, they need to be manually sorted.
78− let binds = (getLoc &&& located' p_valDecl) <$> cid_binds
79− sigs = (getLoc &&& located' p_sigDecl) <$> cid_sigs
80− tyfam_insts =
81− (getLoc &&& located' (p_tyFamInstDecl Associated)) <$>
82− cid_tyfam_insts
83− datafam_insts =
84− (getLoc &&& located' (p_dataFamInstDecl Associated)) <$>
85− cid_datafam_insts
86− decls =
87− snd <$>
88− sortBy
89− (compare `on` fst)
90− (toList binds <> sigs <> tyfam_insts <> datafam_insts)
91− if not (null decls)
92− then do
93− txt " where"
94− newline
95− inci (sequence_ decls)
96− else do
97− newline
98− XClsInstDecl NoExt -> notImplemented "XClsInstDecl"
66+ HsIB {..} -> do
67+ -- GHC's AST does not necessarily store each kind of element in source
68+ -- location order. This happens because different declarations are stored in
69+ -- different lists. Consequently, to get all the declarations in proper
70+ -- 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+ tyFamInsts =
74+ ( getLoc &&& fmap (InstD NoExtField . TyFamInstD NoExtField)
75+ )
76+ <$> cid_tyfam_insts
77+ dataFamInsts =
78+ ( getLoc &&& fmap (InstD NoExtField . DataFamInstD NoExtField)
79+ )
80+ <$> cid_datafam_insts
81+ allDecls =
82+ snd <$> sortOn fst (sigs <> vals <> tyFamInsts <> dataFamInsts)
83+ located hsib_body $ \x -> do
84+ breakpoint
85+ inci $ do
86+ match_overlap_mode cid_overlap_mode breakpoint
87+ p_hsType x
88+ unless (null allDecls) $ do
89+ breakpoint
90+ 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
9997
10098p_tyFamInstDecl :: FamilyStyle -> TyFamInstDecl GhcPs -> R ()
10199p_tyFamInstDecl style = \case
@@ -105,14 +103,15 @@ p_tyFamInstDecl style = \case
105103 Free -> "type instance"
106104 breakpoint
107105 inci (p_tyFamInstEqn tfid_eqn)
108− newline
109106
110107p_dataFamInstDecl :: FamilyStyle -> DataFamInstDecl GhcPs -> R ()
111108p_dataFamInstDecl style = \case
112− DataFamInstDecl {..} -> do
113− let HsIB {..} = dfid_eqn
114− FamEqn {..} = hsib_body
115− p_dataDecl style feqn_tycon feqn_pats feqn_rhs
109+ DataFamInstDecl {dfid_eqn = HsIB {hsib_body = FamEqn {..}}} ->
110+ p_dataDecl style feqn_tycon (map typeArgToType feqn_pats) feqn_fixity feqn_rhs
111+ DataFamInstDecl {dfid_eqn = HsIB {hsib_body = XFamEqn {}}} ->
112+ notImplemented "XFamEqn"
113+ DataFamInstDecl {dfid_eqn = XHsImplicitBndrs {}} ->
114+ notImplemented "XHsImplicitBndrs"
116115
117116match_overlap_mode :: Maybe (Located OverlapMode) -> R () -> R ()
118117match_overlap_mode overlap_mode layoutStrategy =
src/Ormolu/Printer/Meat/Declaration/RoleAnnotation.hs+7−13
@@ -1,12 +1,10 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
43{-# LANGUAGE TypeFamilies #-}
54
65-- | Rendering of Role annotation declarations.
7−
86module Ormolu.Printer.Meat.Declaration.RoleAnnotation
9− ( p_roleAnnot
7+ ( p_roleAnnot,
108 )
119where
1210
@@ -14,25 +12,21 @@ import CoAxiom
1412import GHC
1513import Ormolu.Printer.Combinators
1614import Ormolu.Printer.Meat.Common
17−import Ormolu.Utils
18−import RdrName (RdrName (..))
19−import SrcLoc (Located)
2015
2116p_roleAnnot :: RoleAnnotDecl GhcPs -> R ()
2217p_roleAnnot = \case
23− RoleAnnotDecl NoExt l_name anns -> p_roleAnnot' l_name anns
24− XRoleAnnotDecl _ -> notImplemented "XRoleAnnotDecl"
18+ RoleAnnotDecl NoExtField l_name anns -> p_roleAnnot' l_name anns
19+ XRoleAnnotDecl x -> noExtCon x
2520
2621p_roleAnnot' :: Located RdrName -> [Located (Maybe Role)] -> R ()
27−p_roleAnnot' l_name anns = line $ do
22+p_roleAnnot' l_name anns = do
2823 txt "type role"
2924 breakpoint
3025 inci $ do
3126 p_rdrName l_name
3227 breakpoint
33− let
34− p_role' = maybe (txt "_") p_role
35− inci $ velt' $ (located' p_role') <$> anns
28+ let p_role' = maybe (txt "_") p_role
29+ inci . sitcc $ sep breakpoint (sitcc . located' p_role') anns
3630
3731p_role :: Role -> R ()
3832p_role = \case
src/Ormolu/Printer/Meat/Declaration/Rule.hsnew file+61
@@ -0,0 +1,61 @@
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+
4+module Ormolu.Printer.Meat.Declaration.Rule
5+ ( p_ruleDecls,
6+ )
7+where
8+
9+import BasicTypes
10+import Control.Monad (unless)
11+import GHC
12+import Ormolu.Printer.Combinators
13+import Ormolu.Printer.Meat.Common
14+import Ormolu.Printer.Meat.Declaration.Signature
15+import Ormolu.Printer.Meat.Declaration.Value
16+import Ormolu.Printer.Meat.Type
17+
18+p_ruleDecls :: RuleDecls GhcPs -> R ()
19+p_ruleDecls = \case
20+ HsRules NoExtField _ xs ->
21+ pragma "RULES" $
22+ sep breakpoint (sitcc . located' p_ruleDecl) xs
23+ XRuleDecls x -> noExtCon x
24+
25+p_ruleDecl :: RuleDecl GhcPs -> R ()
26+p_ruleDecl = \case
27+ HsRule NoExtField ruleName activation tyvars ruleBndrs lhs rhs -> do
28+ located ruleName p_ruleName
29+ space
30+ p_activation activation
31+ space
32+ case tyvars of
33+ Nothing -> return ()
34+ Just xs -> do
35+ p_forallBndrs ForallInvis p_hsTyVarBndr xs
36+ space
37+ -- It appears that there is no way to tell if there was an empty forall
38+ -- in the input or no forall at all. We do not want to add redundant
39+ -- foralls, so let's just skip the empty ones.
40+ unless (null ruleBndrs) $
41+ p_forallBndrs ForallInvis p_ruleBndr ruleBndrs
42+ breakpoint
43+ inci $ do
44+ located lhs p_hsExpr
45+ space
46+ equals
47+ inci $ do
48+ breakpoint
49+ located rhs p_hsExpr
50+ XRuleDecl x -> noExtCon x
51+
52+p_ruleName :: (SourceText, RuleName) -> R ()
53+p_ruleName (_, name) = atom $ (HsString NoSourceText name :: HsLit GhcPs)
54+
55+p_ruleBndr :: RuleBndr GhcPs -> R ()
56+p_ruleBndr = \case
57+ RuleBndr NoExtField x -> p_rdrName x
58+ RuleBndrSig NoExtField x hswc -> parens N $ do
59+ p_rdrName x
60+ p_typeAscription hswc
61+ XRuleBndr x -> noExtCon x
src/Ormolu/Printer/Meat/Declaration/Signature.hs+162−113
@@ -1,13 +1,13 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
44
55-- | Type signature declarations.
6−
76module Ormolu.Printer.Meat.Declaration.Signature
8− ( p_sigDecl
9− , p_sigDecl'
10− , p_typeAscription
7+ ( p_sigDecl,
8+ p_typeAscription,
9+ p_activation,
10+ p_standaloneKindSig,
1111 )
1212where
1313
@@ -21,69 +21,82 @@ import Ormolu.Printer.Meat.Type
2121import Ormolu.Utils
2222
2323p_sigDecl :: Sig GhcPs -> R ()
24−p_sigDecl = line . p_sigDecl'
25−
26−p_sigDecl' :: Sig GhcPs -> R ()
27−p_sigDecl' = \case
28− TypeSig NoExt names hswc -> p_typeSig names hswc
29− PatSynSig NoExt names hsib -> p_patSynSig names hsib
30− ClassOpSig NoExt def names hsib -> p_classOpSig def names hsib
31− FixSig NoExt sig -> p_fixSig sig
32− InlineSig NoExt name inlinePragma -> p_inlineSig name inlinePragma
33− SpecSig NoExt name ts inlinePragma -> p_specSig name ts inlinePragma
34− SpecInstSig NoExt _ hsib -> p_specInstSig hsib
35− MinimalSig NoExt _ booleanFormula -> p_minimalSig booleanFormula
36− CompleteMatchSig NoExt _sourceText cs ty -> p_completeSig cs ty
37− SCCFunSig NoExt _ name literal -> p_sccSig name literal
24+p_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
3835 _ -> notImplemented "certain types of signature declarations"
3936
40−p_typeSig
41− :: [Located RdrName] -- ^ Names (before @::@)
42− -> LHsSigWcType GhcPs -- ^ Type
43− -> R ()
44−p_typeSig [] _ = return () -- should not happen though
45−p_typeSig (n:ns) hswc = do
37+p_typeSig ::
38+ -- | Should the tail of the names be indented
39+ Bool ->
40+ -- | Names (before @::@)
41+ [Located RdrName] ->
42+ -- | Type
43+ LHsSigWcType GhcPs ->
44+ R ()
45+p_typeSig _ [] _ = return () -- should not happen though
46+p_typeSig indentTail (n : ns) hswc = do
4647 p_rdrName n
4748 if null ns
4849 then p_typeAscription hswc
49− else inci $ do
50− vlayout (return ()) newline
51− comma
52− velt (withSep comma p_rdrName ns)
50+ else inciIf indentTail $ do
51+ commaDel
52+ sep commaDel p_rdrName ns
5353 p_typeAscription hswc
5454
55−p_typeAscription
56− :: LHsSigWcType GhcPs
57− -> R ()
58−p_typeAscription HsWC {..} = do
59− breakpoint
60− inci $ do
61− txt ":: "
62− located (hsib_body hswc_body) p_hsType
63−p_typeAscription (XHsWildCardBndrs NoExt) = notImplemented "XHsWildCardBndrs"
64−
65−p_patSynSig
66− :: [Located RdrName]
67− -> HsImplicitBndrs GhcPs (LHsType GhcPs)
68− -> R ()
55+p_typeAscription ::
56+ LHsSigWcType GhcPs ->
57+ R ()
58+p_typeAscription HsWC {..} = inci $ do
59+ 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
67+
68+p_patSynSig ::
69+ [Located RdrName] ->
70+ HsImplicitBndrs GhcPs (LHsType GhcPs) ->
71+ R ()
6972p_patSynSig names hsib = do
70− txt "pattern "
71− p_typeSig names HsWC {hswc_ext = NoExt, hswc_body = hsib}
72−
73−p_classOpSig
74− :: Bool -- ^ Whether this is a \"default\" signature
75− -> [Located RdrName] -- ^ Names (before @::@)
76− -> HsImplicitBndrs GhcPs (LHsType GhcPs) -- ^ Type
77− -> R ()
78−p_classOpSig def names hsib = do
79− when def (txt "default ")
80− p_typeSig names HsWC {hswc_ext = NoExt, hswc_body = hsib}
81−
82−p_fixSig
83− :: FixitySig GhcPs
84− -> R ()
73+ txt "pattern"
74+ let body =
75+ p_typeSig
76+ False
77+ names
78+ HsWC {hswc_ext = NoExtField, hswc_body = hsib}
79+ if length names > 1
80+ then breakpoint >> inci body
81+ else space >> body
82+
83+p_classOpSig ::
84+ -- | Whether this is a \"default\" signature
85+ Bool ->
86+ -- | Names (before @::@)
87+ [Located RdrName] ->
88+ -- | Type
89+ HsImplicitBndrs GhcPs (LHsType GhcPs) ->
90+ R ()
91+p_classOpSig def names hsib = do
92+ when def (txt "default" >> space)
93+ p_typeSig True names HsWC {hswc_ext = NoExtField, hswc_body = hsib}
94+
95+p_fixSig ::
96+ FixitySig GhcPs ->
97+ R ()
8598p_fixSig = \case
86− FixitySig NoExt names (Fixity _ n dir) -> do
99+ FixitySig NoExtField names (Fixity _ n dir) -> do
87100 txt $ case dir of
88101 InfixL -> "infixl"
89102 InfixR -> "infixr"
@@ -91,40 +104,53 @@ p_fixSig = \case
91104 space
92105 atom n
93106 space
94− sequence_ (withSep comma p_rdrName names)
95− XFixitySig NoExt -> notImplemented "XFixitySig"
96−
97−p_inlineSig
98− :: Located RdrName -- ^ Name
99− -> InlinePragma -- ^ Inline pragma specification
100− -> R ()
107+ sitcc $ sep commaDel p_rdrName names
108+ XFixitySig x -> noExtCon x
109+
110+p_inlineSig ::
111+ -- | Name
112+ Located RdrName ->
113+ -- | Inline pragma specification
114+ InlinePragma ->
115+ R ()
101116p_inlineSig name InlinePragma {..} = pragmaBraces $ do
102− txt $ case inl_inline of
103− Inline -> "INLINE"
104− Inlinable -> "INLINEABLE"
105− NoInline -> "NOINLINE"
106− NoUserInline -> notImplemented "NoUserInline"
117+ p_inlineSpec inl_inline
118+ space
119+ case inl_rule of
120+ ConLike -> txt "CONLIKE"
121+ FunLike -> return ()
107122 space
108123 p_activation inl_act
124+ space
109125 p_rdrName name
110126
111−p_specSig
112− :: Located RdrName -- ^ Name
113− -> [LHsSigType GhcPs] -- ^ The types to specialize to
114− -> InlinePragma -- ^ For specialize inline
115− -> R ()
127+p_specSig ::
128+ -- | Name
129+ Located RdrName ->
130+ -- | The types to specialize to
131+ [LHsSigType GhcPs] ->
132+ -- | For specialize inline
133+ InlinePragma ->
134+ R ()
116135p_specSig name ts InlinePragma {..} = pragmaBraces $ do
117136 txt "SPECIALIZE"
118137 space
138+ p_inlineSpec inl_inline
139+ space
119140 p_activation inl_act
141+ space
120142 p_rdrName name
143+ space
144+ txt "::"
121145 breakpoint
122− inci $ do
123− txt ":: "
124− -- XXX Not at all sure why ts is a list of @LHsSigType GhcPs@ things, it
125− -- appears that we only can give one type to specialize to per pragma.
126− -- Maybe I'm mistaken.
127− located (hsib_body (head ts)) p_hsType
146+ inci $ sep commaDel (located' p_hsType . hsib_body) ts
147+
148+p_inlineSpec :: InlineSpec -> R ()
149+p_inlineSpec = \case
150+ Inline -> txt "INLINE"
151+ Inlinable -> txt "INLINEABLE"
152+ NoInline -> txt "NOINLINE"
153+ NoUserInline -> return ()
128154
129155p_activation :: Activation -> R ()
130156p_activation = \case
@@ -134,54 +160,77 @@ p_activation = \case
134160 txt "[~"
135161 atom n
136162 txt "]"
137− space
138163 ActiveAfter _ n -> do
139164 txt "["
140165 atom n
141166 txt "]"
142− space
143167
144168p_specInstSig :: LHsSigType GhcPs -> R ()
145−p_specInstSig hsib = pragma "SPECIALIZE instance" $
146− located (hsib_body hsib) p_hsType
147−
148−p_minimalSig
149− :: LBooleanFormula (Located RdrName) -- ^ Boolean formula
150− -> R ()
169+p_specInstSig hsib =
170+ pragma "SPECIALIZE instance" . inci $
171+ located (hsib_body hsib) p_hsType
172+
173+p_minimalSig ::
174+ -- | Boolean formula
175+ LBooleanFormula (Located RdrName) ->
176+ R ()
151177p_minimalSig =
152178 located' $ \booleanFormula ->
153− pragma "MINIMAL" (p_booleanFormula booleanFormula)
179+ pragma "MINIMAL" (inci $ p_booleanFormula booleanFormula)
154180
155−p_booleanFormula
156− :: BooleanFormula (Located RdrName) -- ^ Boolean formula
157− -> R ()
181+p_booleanFormula ::
182+ -- | Boolean formula
183+ BooleanFormula (Located RdrName) ->
184+ R ()
158185p_booleanFormula = \case
159186 Var name -> p_rdrName name
160− And xs -> velt $
161− withSep comma (located' p_booleanFormula) xs
162− Or xs -> velt $
163− withSep (vlayout space (return ()) >> txt "| ")
164− (located' p_booleanFormula)
165− xs
166− Parens l -> located l (parens . p_booleanFormula)
167−
168−p_completeSig
169− :: Located [Located RdrName] -- ^ Constructors\/patterns
170− -> Maybe (Located RdrName) -- ^ Type
171− -> R ()
187+ And xs ->
188+ sitcc $
189+ sep
190+ commaDel
191+ (located' p_booleanFormula)
192+ xs
193+ Or xs ->
194+ sitcc $
195+ sep
196+ (breakpoint >> txt "|" >> space)
197+ (located' p_booleanFormula)
198+ xs
199+ Parens l -> located l (parens N . p_booleanFormula)
200+
201+p_completeSig ::
202+ -- | Constructors\/patterns
203+ Located [Located RdrName] ->
204+ -- | Type
205+ Maybe (Located RdrName) ->
206+ R ()
172207p_completeSig cs' mty =
173208 located cs' $ \cs ->
174− pragma "COMPLETE" $ do
175− velt (withSep comma p_rdrName cs)
209+ pragma "COMPLETE" . inci $ do
210+ sep commaDel p_rdrName cs
176211 forM_ mty $ \ty -> do
212+ space
213+ txt "::"
177214 breakpoint
178− inci $ do
179− txt ":: "
180− p_rdrName ty
215+ inci (p_rdrName ty)
181216
182217p_sccSig :: Located (IdP GhcPs) -> Maybe (Located StringLiteral) -> R ()
183−p_sccSig loc literal = pragma "SCC" $ do
218+p_sccSig loc literal = pragma "SCC" . inci $ do
184219 p_rdrName loc
185220 forM_ literal $ \x -> do
186221 breakpoint
187222 atom x
223+
224+p_standaloneKindSig :: StandaloneKindSig GhcPs -> R ()
225+p_standaloneKindSig (StandaloneKindSig NoExtField name bndrs) = do
226+ txt "type"
227+ inci $ do
228+ space
229+ p_rdrName name
230+ space
231+ txt "::"
232+ breakpoint
233+ case bndrs of
234+ HsIB NoExtField sig -> located sig p_hsType
235+ XHsImplicitBndrs x -> noExtCon x
236+p_standaloneKindSig (XStandaloneKindSig c) = noExtCon c
src/Ormolu/Printer/Meat/Declaration/Splice.hs+3−4
@@ -1,16 +1,15 @@
11{-# LANGUAGE LambdaCase #-}
22
33module Ormolu.Printer.Meat.Declaration.Splice
4− ( p_spliceDecl
4+ ( p_spliceDecl,
55 )
66where
77
88import GHC
99import Ormolu.Printer.Combinators
1010import Ormolu.Printer.Meat.Declaration.Value (p_hsSplice)
11−import Ormolu.Utils
1211
1312p_spliceDecl :: SpliceDecl GhcPs -> R ()
1413p_spliceDecl = \case
15− SpliceDecl NoExt splice _explicit -> line $ located splice p_hsSplice
16− XSpliceDecl {} -> notImplemented "XSpliceDecl"
14+ SpliceDecl NoExtField splice _explicit -> located splice p_hsSplice
15+ XSpliceDecl x -> noExtCon x
src/Ormolu/Printer/Meat/Declaration/Type.hs+28−19
@@ -1,31 +1,40 @@
11{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE RecordWildCards #-}
2+{-# LANGUAGE RecordWildCards #-}
33
44-- | Rendering of type synonym declarations.
5−
65module Ormolu.Printer.Meat.Declaration.Type
7− ( p_synDecl
6+ ( p_synDecl,
87 )
98where
109
11−import Control.Monad
1210import GHC
1311import Ormolu.Printer.Combinators
1412import Ormolu.Printer.Meat.Common
1513import Ormolu.Printer.Meat.Type
16−import RdrName (RdrName (..))
17−import SrcLoc (Located)
1814
19−p_synDecl
20− :: Located RdrName -- ^ Type constructor
21− -> LHsQTyVars GhcPs -- ^ Type variables
22− -> LHsType GhcPs -- ^ RHS of type declaration
23− -> R ()
24−p_synDecl name tvars t = line $ do
25− txt "type "
26− p_rdrName name
27− let HsQTvs {..} = tvars
28− unless (null hsq_explicit) space
29− spaceSep (located' p_hsTyVarBndr) hsq_explicit
30− breakpoint
31− inci (txt "= " >> located t p_hsType)
15+p_synDecl ::
16+ -- | Type constructor
17+ Located RdrName ->
18+ -- | Fixity
19+ LexicalFixity ->
20+ -- | Type variables
21+ LHsQTyVars GhcPs ->
22+ -- | RHS of type declaration
23+ LHsType GhcPs ->
24+ R ()
25+p_synDecl name fixity HsQTvs {..} t = do
26+ txt "type"
27+ space
28+ switchLayout (getLoc name : map getLoc hsq_explicit) $
29+ p_infixDefHelper
30+ (case fixity of Infix -> True; _ -> False)
31+ True
32+ (p_rdrName name)
33+ (map (located' p_hsTyVarBndr) hsq_explicit)
34+ space
35+ equals
36+ if hasDocStrings (unLoc t)
37+ then newline
38+ else breakpoint
39+ inci (located t p_hsType)
40+p_synDecl _ _ (XLHsQTyVars x) _ = noExtCon x
src/Ormolu/Printer/Meat/Declaration/TypeFamily.hs+62−54
@@ -1,103 +1,111 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
44
55-- | Rendering of data\/type families.
6−
76module Ormolu.Printer.Meat.Declaration.TypeFamily
8− ( p_famDecl
9− , p_tyFamInstEqn
7+ ( p_famDecl,
8+ p_tyFamInstEqn,
109 )
1110where
1211
13−import BasicTypes (LexicalFixity (..))
1412import Control.Monad
15−import Data.List.NonEmpty (NonEmpty (..))
16−import Data.Maybe (isNothing, isJust)
13+import Data.Maybe (isNothing)
1714import GHC
1815import Ormolu.Printer.Combinators
1916import Ormolu.Printer.Meat.Common
2017import Ormolu.Printer.Meat.Type
2118import Ormolu.Utils
22−import SrcLoc (Located, GenLocated (..))
2319
2420p_famDecl :: FamilyStyle -> FamilyDecl GhcPs -> R ()
25−p_famDecl style FamilyDecl {..} = do
21+p_famDecl style FamilyDecl {fdTyVars = HsQTvs {..}, ..} = do
2622 mmeqs <- case fdInfo of
2723 DataFamily -> Nothing <$ txt "data"
2824 OpenTypeFamily -> Nothing <$ txt "type"
2925 ClosedTypeFamily eqs -> Just eqs <$ txt "type"
30− txt $ case style of
26+ txt $ case style of
3127 Associated -> mempty
3228 Free -> " family"
33− let HsQTvs {..} = fdTyVars
34− combinedSpans = combineSrcSpans' $
35− getLoc fdLName :| fmap getLoc hsq_explicit
3629 breakpoint
3730 inci $ do
38− switchLayout combinedSpans $ do
31+ switchLayout (getLoc fdLName : (getLoc <$> hsq_explicit)) $
3932 p_infixDefHelper
4033 (isInfix fdFixity)
41− inci
34+ True
4235 (p_rdrName fdLName)
4336 (located' p_hsTyVarBndr <$> hsq_explicit)
44− let rsig = p_familyResultSigL (isJust fdInjectivityAnn) fdResultSig
45− unless (isNothing rsig && isNothing fdInjectivityAnn) $
46− breakpoint
37+ let resultSig = p_familyResultSigL fdResultSig
38+ unless (isNothing resultSig && isNothing fdInjectivityAnn) space
4739 inci $ do
48− sequence_ rsig
49− when (isJust rsig && isJust fdInjectivityAnn) breakpoint
40+ sequence_ resultSig
41+ space
5042 forM_ fdInjectivityAnn (located' p_injectivityAnn)
5143 case mmeqs of
52− Nothing -> newline
44+ Nothing -> return ()
5345 Just meqs -> do
54− txt " where"
46+ inci $ do
47+ breakpoint
48+ txt "where"
5549 case meqs of
56− Nothing -> txt " .." >> newline
50+ Nothing -> do
51+ space
52+ txt ".."
5753 Just eqs -> do
5854 newline
59− forM_ eqs (located' (line . inci . p_tyFamInstEqn))
60−p_famDecl _ (XFamilyDecl NoExt) = notImplemented "XFamilyDecl"
55+ sep newline (located' (inci . p_tyFamInstEqn)) eqs
56+p_famDecl _ FamilyDecl {fdTyVars = XLHsQTyVars {}} =
57+ notImplemented "XLHsQTyVars"
58+p_famDecl _ (XFamilyDecl x) = noExtCon x
6159
62−p_familyResultSigL
63− :: Bool
64− -> Located (FamilyResultSig GhcPs)
65− -> Maybe (R ())
66−p_familyResultSigL injAnn l =
60+p_familyResultSigL ::
61+ Located (FamilyResultSig GhcPs) ->
62+ Maybe (R ())
63+p_familyResultSigL l =
6764 case l of
6865 L _ a -> case a of
69− NoSig NoExt -> Nothing
70− KindSig NoExt k -> Just $ do
71− if injAnn then txt "= " else txt ":: "
66+ NoSig NoExtField -> Nothing
67+ KindSig NoExtField k -> Just $ do
68+ txt "::"
69+ breakpoint
7270 located k p_hsType
73− TyVarSig NoExt bndr -> Just $ do
74− if injAnn then txt "= " else txt ":: "
71+ TyVarSig NoExtField bndr -> Just $ do
72+ equals
73+ breakpoint
7574 located bndr p_hsTyVarBndr
76− XFamilyResultSig NoExt ->
77− notImplemented "XFamilyResultSig"
75+ XFamilyResultSig x ->
76+ noExtCon x
7877
7978p_injectivityAnn :: InjectivityAnn GhcPs -> R ()
8079p_injectivityAnn (InjectivityAnn a bs) = do
81− txt "| "
80+ txt "|"
81+ space
8282 p_rdrName a
8383 space
84− txt "-> "
85− spaceSep p_rdrName bs
84+ txt "->"
85+ space
86+ sep space p_rdrName bs
8687
8788p_tyFamInstEqn :: TyFamInstEqn GhcPs -> R ()
88−p_tyFamInstEqn HsIB {..} = do
89− let FamEqn {..} = hsib_body
90− combinedSpans = combineSrcSpans' $
91− getLoc feqn_tycon :| fmap getLoc feqn_pats
92− switchLayout combinedSpans $ p_infixDefHelper
93− (isInfix feqn_fixity)
94− inci
95− (p_rdrName feqn_tycon)
96− (located' p_hsType <$> feqn_pats)
97− txt " ="
98− breakpoint
99− inci (located feqn_rhs p_hsType)
100−p_tyFamInstEqn (XHsImplicitBndrs NoExt) = notImplemented "XHsImplicitBndrs"
89+p_tyFamInstEqn HsIB {hsib_body = FamEqn {..}} = do
90+ case feqn_bndrs of
91+ Nothing -> return ()
92+ Just bndrs -> do
93+ p_forallBndrs ForallInvis p_hsTyVarBndr bndrs
94+ breakpoint
95+ inciIf (not $ null feqn_bndrs) $ do
96+ let famLhsSpn = getLoc feqn_tycon : fmap (getLoc . typeArgToType) feqn_pats
97+ switchLayout famLhsSpn $
98+ p_infixDefHelper
99+ (isInfix feqn_fixity)
100+ True
101+ (p_rdrName feqn_tycon)
102+ (located' p_hsType . typeArgToType <$> feqn_pats)
103+ space
104+ equals
105+ breakpoint
106+ inci (located feqn_rhs p_hsType)
107+p_tyFamInstEqn HsIB {hsib_body = XFamEqn x} = noExtCon x
108+p_tyFamInstEqn (XHsImplicitBndrs x) = noExtCon x
101109
102110----------------------------------------------------------------------------
103111-- Helpers
src/Ormolu/Printer/Meat/Declaration/Value.hs+1096−409
@@ -1,32 +1,43 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE MultiWayIf #-}
23{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
4+{-# LANGUAGE RecordWildCards #-}
5+{-# LANGUAGE TypeApplications #-}
46
57module Ormolu.Printer.Meat.Declaration.Value
6− ( p_valDecl
7− , p_pat
8− , p_hsExpr
9− , p_hsSplice
8+ ( p_valDecl,
9+ p_pat,
10+ p_hsExpr,
11+ p_hsSplice,
12+ p_stringLit,
1013 )
1114where
1215
1316import Bag (bagToList)
1417import BasicTypes
1518import Control.Monad
16−import Data.Data
19+import Ctype (is_space)
20+import Data.Bool (bool)
21+import Data.Char (isPunctuation, isSymbol)
22+import Data.Data hiding (Infix, Prefix)
23+import Data.Functor ((<&>))
1724import Data.List (intersperse, sortOn)
25+import Data.List.NonEmpty (NonEmpty (..), (<|))
26+import qualified Data.List.NonEmpty as NE
1827import Data.Text (Text)
28+import qualified Data.Text as Text
1929import GHC
30+import OccName (occNameString)
2031import Ormolu.Printer.Combinators
32+import Ormolu.Printer.Internal
2133import Ormolu.Printer.Meat.Common
34+import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration
2235import Ormolu.Printer.Meat.Declaration.Signature
2336import Ormolu.Printer.Meat.Type
37+import Ormolu.Printer.Operators
2438import Ormolu.Utils
25−import Outputable (Outputable (..))
26−import SrcLoc (combineSrcSpans, isOneLineSpan)
27−import qualified Data.List.NonEmpty as NE
28−import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration
2939
40+-- | Style of a group of equations.
3041data MatchGroupStyle
3142 = Function (Located RdrName)
3243 | PatternBind
@@ -34,588 +45,1062 @@ data MatchGroupStyle
3445 | Lambda
3546 | LambdaCase
3647
48+-- | Style of equations in a group.
3749data GroupStyle
3850 = EqualSign
3951 | RightArrow
4052
4153-- | Expression placement. This marks the places where expressions that
4254-- implement handing forms may use them.
43−
4455data Placement
45− = Normal -- ^ Multi-line layout should cause
46− -- insertion of a newline and indentation
47− -- bump
48− | Hanging -- ^ Expressions that have hanging form
49− -- should use it and avoid bumping one level
50− -- of indentation
56+ = -- | Multi-line layout should cause
57+ -- insertion of a newline and indentation
58+ -- bump
59+ Normal
60+ | -- | Expressions that have hanging form
61+ -- should use it and avoid bumping one level
62+ -- of indentation
63+ Hanging
64+ deriving (Eq, Show)
5165
5266p_valDecl :: HsBindLR GhcPs GhcPs -> R ()
53−p_valDecl = line . p_valDecl'
54−
55−p_valDecl' :: HsBindLR GhcPs GhcPs -> R ()
56−p_valDecl' = \case
57− FunBind NoExt funId funMatches _ _ -> p_funBind funId funMatches
58− PatBind NoExt pat grhss _ -> p_match PatternBind False [pat] grhss
67+p_valDecl = \case
68+ FunBind NoExtField funId funMatches _ _ -> p_funBind funId funMatches
69+ PatBind NoExtField pat grhss _ -> p_match PatternBind False NoSrcStrict [pat] grhss
5970 VarBind {} -> notImplemented "VarBinds" -- introduced by the type checker
6071 AbsBinds {} -> notImplemented "AbsBinds" -- introduced by the type checker
61− PatSynBind NoExt psb -> p_patSynBind psb
62− XHsBindsLR NoExt -> notImplemented "XHsBindsLR"
63−
64−p_funBind
65− :: Located RdrName
66− -> MatchGroup GhcPs (LHsExpr GhcPs)
67− -> R ()
68−p_funBind name mgroup =
69− p_matchGroup (Function name) mgroup
70−
71−p_matchGroup
72− :: MatchGroupStyle
73− -> MatchGroup GhcPs (LHsExpr GhcPs)
74− -> R ()
75−p_matchGroup style MG {..} =
76− locatedVia Nothing mg_alts $
77− newlineSep (located' (\m@Match {..} ->
78− p_match style (isInfixMatch m) m_pats m_grhss))
79−p_matchGroup _ (XMatchGroup NoExt) = notImplemented "XMatchGroup"
80−
81−p_match
82− :: MatchGroupStyle
83− -> Bool -- ^ Is this an infix match?
84− -> [LPat GhcPs]
85− -> GRHSs GhcPs (LHsExpr GhcPs)
86− -> R ()
87−p_match style isInfix m_pats m_grhss = do
88− -- NOTE Normally, since patterns may be placed in a multi-line layout, it
89− -- is necessary to bump indentation for the pattern group so it's more
72+ PatSynBind NoExtField psb -> p_patSynBind psb
73+ XHsBindsLR x -> noExtCon x
74+
75+p_funBind ::
76+ Located RdrName ->
77+ MatchGroup GhcPs (LHsExpr GhcPs) ->
78+ R ()
79+p_funBind name = p_matchGroup (Function name)
80+
81+p_matchGroup ::
82+ MatchGroupStyle ->
83+ MatchGroup GhcPs (LHsExpr GhcPs) ->
84+ R ()
85+p_matchGroup = p_matchGroup' exprPlacement p_hsExpr
86+
87+p_matchGroup' ::
88+ Data body =>
89+ -- | How to get body placement
90+ (body -> Placement) ->
91+ -- | How to print body
92+ (body -> R ()) ->
93+ -- | Style of this group of equations
94+ MatchGroupStyle ->
95+ -- | Match group
96+ MatchGroup GhcPs (Located body) ->
97+ R ()
98+p_matchGroup' placer render style MG {..} = do
99+ let ob = case style of
100+ Case -> id
101+ LambdaCase -> id
102+ _ -> dontUseBraces
103+ -- Since we are forcing braces on 'sepSemi' based on 'ob', we have to
104+ -- restore the brace state inside the sepsemi.
105+ ub <- bool dontUseBraces useBraces <$> canUseBraces
106+ ob $ sepSemi (located' (ub . p_Match)) (unLoc mg_alts)
107+ where
108+ p_Match m@Match {..} =
109+ p_match'
110+ placer
111+ render
112+ (adjustMatchGroupStyle m style)
113+ (isInfixMatch m)
114+ (matchStrictness m)
115+ m_pats
116+ m_grhss
117+ p_Match (XMatch x) = noExtCon x
118+p_matchGroup' _ _ _ (XMatchGroup x) = noExtCon x
119+
120+-- | Function id obtained through pattern matching on 'FunBind' should not
121+-- be used to print the actual equations because the different ‘RdrNames’
122+-- used in the equations may have different “decorations” (such as backticks
123+-- and paretheses) associated with them. It is necessary to use per-equation
124+-- names obtained from 'm_ctxt' of 'Match'. This function replaces function
125+-- name inside of 'Function' accordingly.
126+adjustMatchGroupStyle ::
127+ Match GhcPs body ->
128+ MatchGroupStyle ->
129+ MatchGroupStyle
130+adjustMatchGroupStyle m = \case
131+ Function _ -> (Function . mc_fun . m_ctxt) m
132+ style -> style
133+
134+matchStrictness :: Match id body -> SrcStrictness
135+matchStrictness match =
136+ case m_ctxt match of
137+ FunRhs {mc_strictness = s} -> s
138+ _ -> NoSrcStrict
139+
140+p_match ::
141+ -- | Style of the group
142+ MatchGroupStyle ->
143+ -- | Is this an infix match?
144+ Bool ->
145+ -- | Strictness prefix (FunBind)
146+ SrcStrictness ->
147+ -- | Argument patterns
148+ [LPat GhcPs] ->
149+ -- | Equations
150+ GRHSs GhcPs (LHsExpr GhcPs) ->
151+ R ()
152+p_match = p_match' exprPlacement p_hsExpr
153+
154+p_match' ::
155+ Data body =>
156+ -- | How to get body placement
157+ (body -> Placement) ->
158+ -- | How to print body
159+ (body -> R ()) ->
160+ -- | Style of this group of equations
161+ MatchGroupStyle ->
162+ -- | Is this an infix match?
163+ Bool ->
164+ -- | Strictness prefix (FunBind)
165+ SrcStrictness ->
166+ -- | Argument patterns
167+ [LPat GhcPs] ->
168+ -- | Equations
169+ GRHSs GhcPs (Located body) ->
170+ R ()
171+p_match' placer render style isInfix strictness m_pats GRHSs {..} = do
172+ -- Normally, since patterns may be placed in a multi-line layout, it is
173+ -- necessary to bump indentation for the pattern group so it's more
90174 -- indented than function name. This in turn means that indentation for
91175 -- the body should also be bumped. Normally this would mean that bodies
92176 -- would start with two indentation steps applied, which is ugly, so we
93177 -- need to be a bit more clever here and bump indentation level only when
94178 -- pattern group is multiline.
95− inci' <- case NE.nonEmpty m_pats of
96− Nothing -> id <$ case style of
97− Function name -> p_rdrName name
98− _ -> return ()
179+ case strictness of
180+ NoSrcStrict -> return ()
181+ SrcStrict -> txt "!"
182+ SrcLazy -> txt "~"
183+ indentBody <- case NE.nonEmpty m_pats of
184+ Nothing ->
185+ False <$ case style of
186+ Function name -> p_rdrName name
187+ _ -> return ()
99188 Just ne_pats -> do
100− let combinedSpans = combineSrcSpans' $
101− getLoc <$> ne_pats
102− inci' = if isOneLineSpan combinedSpans
103− then id
104− else inci
105− switchLayout combinedSpans $ do
106− let stdCase = velt' (located' p_pat <$> m_pats)
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)
194+ switchLayout [combinedSpans] $ do
195+ let stdCase = sep breakpoint (located' p_pat) m_pats
107196 case style of
108197 Function name ->
109198 p_infixDefHelper
110199 isInfix
111− inci'
200+ indentBody
112201 (p_rdrName name)
113202 (located' p_pat <$> m_pats)
114203 PatternBind -> stdCase
115204 Case -> stdCase
116205 Lambda -> do
206+ let needsSpace = case unLoc (NE.head ne_pats) of
207+ LazyPat _ _ -> True
208+ BangPat _ _ -> True
209+ SplicePat _ _ -> True
210+ _ -> False
117211 txt "\\"
118− stdCase
212+ when needsSpace space
213+ sitcc stdCase
119214 LambdaCase -> stdCase
120− return inci'
121−
122− let
123− -- Calculate a 'SrcSpan' that captures the end of the name\/pattern part
124− -- of the match. This is used to tell if we need to have the body on a
125− -- newline.
126− endOfPatsSpan = srcLocSpan . srcSpanEnd <$> case NE.nonEmpty m_pats of
127− Nothing -> case style of
128− Function name -> Just $ getLoc name
129− _ -> Nothing
130− Just pats -> Just . getLoc $ NE.last pats
131− isCase = \case
132− Case -> True
133− LambdaCase -> True
134− _ -> False
135− inci' $ do
136− let GRHSs {..} = m_grhss
137− hasGuards = withGuards grhssGRHSs
138− unless (length grhssGRHSs > 1) $ do
139− case style of
140− Function _ -> txt " ="
141− PatternBind -> txt " ="
142− s | isCase s && hasGuards -> return ()
143− _ -> txt " ->"
144− let grhssSpan = combineSrcSpans' $
215+ return indentBody
216+ let -- Calculate position of end of patterns. This is useful when we decide
217+ -- about putting certain constructions in hanging positions.
218+ endOfPats = case NE.nonEmpty m_pats of
219+ Nothing -> case style of
220+ Function name -> Just (getLoc name)
221+ _ -> Nothing
222+ Just pats -> (Just . getLoc . NE.last) pats
223+ isCase = \case
224+ Case -> True
225+ LambdaCase -> True
226+ _ -> False
227+ hasGuards = withGuards grhssGRHSs
228+ grhssSpan =
229+ combineSrcSpans' $
145230 getGRHSSpan . unLoc <$> NE.fromList grhssGRHSs
146− patGrhssSpan = maybe grhssSpan (combineSrcSpans grhssSpan) endOfPatsSpan
147− placement = blockPlacement grhssGRHSs
148− inciLocalBinds = case placement of
149− Normal -> id
150− Hanging -> inci
151− p_body = do
152− let groupStyle =
153− if isCase style && hasGuards
231+ patGrhssSpan =
232+ maybe
233+ grhssSpan
234+ (combineSrcSpans grhssSpan . srcLocSpan . srcSpanEnd)
235+ endOfPats
236+ placement =
237+ case endOfPats of
238+ Nothing -> blockPlacement placer grhssGRHSs
239+ Just spn ->
240+ if onTheSameLine spn grhssSpan
241+ then blockPlacement placer grhssGRHSs
242+ else Normal
243+ p_body = do
244+ let groupStyle =
245+ if isCase style && hasGuards
154246 then RightArrow
155247 else EqualSign
156− newlineSep (located' (p_grhs groupStyle)) grhssGRHSs
157− unless
158− (GHC.isEmptyLocalBindsPR (unLoc grhssLocalBinds))
159− (inciLocalBinds $ do
160− newline
161− line (txt "where")
162− inci (located grhssLocalBinds p_hsLocalBinds)
163− )
164− case style of
165− Lambda -> placeHanging placement $
166− switchLayout patGrhssSpan p_body
167− _ -> switchLayout patGrhssSpan $
168− placeHanging placement p_body
248+ sep newline (located' (p_grhs' placer render groupStyle)) grhssGRHSs
249+ p_where = do
250+ let whereIsEmpty = GHC.isEmptyLocalBindsPR (unLoc grhssLocalBinds)
251+ unless (GHC.eqEmptyLocalBinds (unLoc grhssLocalBinds)) $ do
252+ breakpoint
253+ txt "where"
254+ unless whereIsEmpty breakpoint
255+ 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 "->"
264+ switchLayout [patGrhssSpan] $
265+ placeHanging placement p_body
266+ inci p_where
267+p_match' _ _ _ _ _ _ (XGRHSs x) = noExtCon x
169268
170269p_grhs :: GroupStyle -> GRHS GhcPs (LHsExpr GhcPs) -> R ()
171−p_grhs style (GRHS NoExt guards body) =
270+p_grhs = p_grhs' exprPlacement p_hsExpr
271+
272+p_grhs' ::
273+ Data body =>
274+ -- | How to get body placement
275+ (body -> Placement) ->
276+ -- | How to print body
277+ (body -> R ()) ->
278+ GroupStyle ->
279+ GRHS GhcPs (Located body) ->
280+ R ()
281+p_grhs' placer render style (GRHS NoExtField guards body) =
172282 case guards of
173283 [] -> p_body
174284 xs -> do
175− txt "| "
176− velt $ withSep comma (located' p_stmt) xs
285+ txt "|"
177286 space
178− txt $ case style of
179− EqualSign -> "="
180− RightArrow -> "->"
181− breakpoint
182− inci p_body
287+ sitcc (sep commaDel (sitcc . located' p_stmt) xs)
288+ space
289+ inci $ case style of
290+ EqualSign -> equals
291+ RightArrow -> txt "->"
292+ placeHanging placement p_body
183293 where
184− p_body = located body p_hsExpr
185−p_grhs _ (XGRHS NoExt) = notImplemented "XGRHS"
294+ placement =
295+ case endOfGuards of
296+ Nothing -> placer (unLoc body)
297+ Just spn ->
298+ if onTheSameLine spn (getLoc body)
299+ then placer (unLoc body)
300+ else Normal
301+ endOfGuards =
302+ case NE.nonEmpty guards of
303+ Nothing -> Nothing
304+ Just gs -> (Just . getLoc . NE.last) gs
305+ p_body = located body render
306+p_grhs' _ _ _ (XGRHS x) = noExtCon x
307+
308+p_hsCmd :: HsCmd GhcPs -> R ()
309+p_hsCmd = \case
310+ HsCmdArrApp NoExtField body input arrType _ -> do
311+ 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
320+ located form p_hsExpr
321+ unless (null cmds) $ do
322+ breakpoint
323+ inci (sequence_ (intersperse breakpoint (located' p_hsCmdTop <$> cmds)))
324+ HsCmdArrForm NoExtField form Infix _ [left, right] -> do
325+ located left p_hsCmdTop
326+ space
327+ located form p_hsExpr
328+ placeHanging (cmdTopPlacement (unLoc right)) $
329+ located right p_hsCmdTop
330+ HsCmdArrForm NoExtField _ Infix _ _ -> notImplemented "HsCmdArrForm"
331+ HsCmdApp {} ->
332+ -- XXX Does this ever occur in the syntax tree? It does not seem like it
333+ -- does. Open an issue and ping @yumiova if this ever occurs in output.
334+ 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 ->
338+ p_case cmdPlacement p_hsCmd e mgroup
339+ HsCmdIf NoExtField _ if' then' else' ->
340+ p_if cmdPlacement p_hsCmd if' then' else'
341+ HsCmdLet NoExtField localBinds c ->
342+ p_let p_hsCmd localBinds c
343+ HsCmdDo NoExtField es -> do
344+ txt "do"
345+ newline
346+ inci . located es $
347+ sitcc . sep newline (sitcc . withSpacing (p_stmt' cmdPlacement p_hsCmd))
348+ HsCmdWrap {} -> notImplemented "HsCmdWrap"
349+ XCmd x -> noExtCon x
350+
351+p_hsCmdTop :: HsCmdTop GhcPs -> R ()
352+p_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)
186384
187385p_stmt :: Stmt GhcPs (LHsExpr GhcPs) -> R ()
188−p_stmt = \case
189− LastStmt NoExt body _ _ -> located body p_hsExpr
190− BindStmt NoExt l f _ _ -> do
191− located l p_pat
386+p_stmt = p_stmt' exprPlacement p_hsExpr
387+
388+p_stmt' ::
389+ Data body =>
390+ -- | Placer
391+ (body -> Placement) ->
392+ -- | Render
393+ (body -> R ()) ->
394+ -- | Statement to render
395+ Stmt GhcPs (Located body) ->
396+ R ()
397+p_stmt' placer render = \case
398+ LastStmt NoExtField body _ _ -> located body render
399+ BindStmt NoExtField p f _ _ -> do
400+ located p p_pat
192401 space
193402 txt "<-"
194− breakpoint
195− inci (located f p_hsExpr)
196− ApplicativeStmt {} -> notImplemented "ApplicativeStmt"
197− BodyStmt NoExt body _ _ -> located body p_hsExpr
198− LetStmt NoExt binds -> do
199− txt "let "
403+ let loc = getLoc p
404+ placement =
405+ case f of
406+ L l' x ->
407+ if isOneLineSpan
408+ (mkSrcSpan (srcSpanEnd loc) (srcSpanStart l'))
409+ then placer x
410+ else Normal
411+ switchLayout [loc, getLoc f] $
412+ placeHanging placement (located f render)
413+ ApplicativeStmt {} -> notImplemented "ApplicativeStmt" -- generated by renamer
414+ BodyStmt NoExtField body _ _ -> located body render
415+ LetStmt NoExtField binds -> do
416+ txt "let"
417+ space
200418 sitcc $ located binds p_hsLocalBinds
201− ParStmt NoExt stmts _ _ ->
202− sequence_ $ intersperse breakpoint $
203− withSep (txt "| ") p_parStmtBlock stmts
204− TransStmt {} -> notImplemented "TransStmt"
205− RecStmt {} -> notImplemented "RecStmt"
206− XStmtLR {} -> notImplemented "XStmtLR"
207−
208−p_parStmtBlock :: ParStmtBlock GhcPs GhcPs -> R ()
209−p_parStmtBlock = \case
210− ParStmtBlock NoExt stmts _ _ ->
211− velt $ withSep comma (located' (sitcc . p_stmt)) stmts
212− XParStmtBlock {} -> notImplemented "XParStmtBlock"
419+ ParStmt {} ->
420+ -- 'ParStmt' should always be eliminated in 'gatherStmt' already, such
421+ -- that it never occurs in 'p_stmt''. Consequently, handling it here
422+ -- would be redundant.
423+ notImplemented "ParStmt"
424+ TransStmt {..} ->
425+ -- 'TransStmt' only needs to account for render printing itself, since
426+ -- pretty printing of relevant statements (e.g., in 'trS_stmts') is
427+ -- handled through 'gatherStmt'.
428+ case (trS_form, trS_by) of
429+ (ThenForm, Nothing) -> do
430+ txt "then"
431+ breakpoint
432+ inci $ located trS_using p_hsExpr
433+ (ThenForm, Just e) -> do
434+ txt "then"
435+ breakpoint
436+ inci $ located trS_using p_hsExpr
437+ breakpoint
438+ txt "by"
439+ breakpoint
440+ inci $ located e p_hsExpr
441+ (GroupForm, Nothing) -> do
442+ txt "then group using"
443+ breakpoint
444+ inci $ located trS_using p_hsExpr
445+ (GroupForm, Just e) -> do
446+ txt "then group by"
447+ breakpoint
448+ inci $ located e p_hsExpr
449+ breakpoint
450+ txt "using"
451+ breakpoint
452+ inci $ located trS_using p_hsExpr
453+ RecStmt {..} -> do
454+ txt "rec"
455+ space
456+ sitcc $ sepSemi (withSpacing (p_stmt' placer render)) recS_stmts
457+ XStmtLR c -> noExtCon c
458+
459+gatherStmt :: ExprLStmt GhcPs -> [[ExprLStmt GhcPs]]
460+gatherStmt (L _ (ParStmt NoExtField block _ _)) =
461+ foldr ((<>) . gatherStmtBlock) [] block
462+gatherStmt (L s stmt@TransStmt {..}) =
463+ foldr liftAppend [] ((gatherStmt <$> trS_stmts) <> pure [[L s stmt]])
464+gatherStmt stmt = [[stmt]]
465+
466+gatherStmtBlock :: ParStmtBlock GhcPs GhcPs -> [[ExprLStmt GhcPs]]
467+gatherStmtBlock (ParStmtBlock _ stmts _ _) =
468+ foldr (liftAppend . gatherStmt) [] stmts
469+gatherStmtBlock (XParStmtBlock x) = noExtCon x
213470
214471p_hsLocalBinds :: HsLocalBindsLR GhcPs GhcPs -> R ()
215472p_hsLocalBinds = \case
216− HsValBinds NoExt (ValBinds NoExt bag lsigs) -> do
217− let ssStart = either
218− (srcSpanStart . getLoc)
219− (srcSpanStart . getLoc)
220− items =
221− (Left <$> bagToList bag) ++ (Right <$> lsigs)
222− p_item (Left x) = located x p_valDecl'
223− p_item (Right x) = located x p_sigDecl'
224− newlineSep p_item (sortOn ssStart items)
225− HsValBinds NoExt _ -> notImplemented "HsValBinds"
226− HsIPBinds NoExt _ -> notImplemented "HsIPBinds"
227− EmptyLocalBinds NoExt -> return ()
228− XHsLocalBindsLR _ -> notImplemented "XHsLocalBindsLR"
229−
230−p_hsRecField
231− :: (Data id, Outputable id)
232− => HsRecField' id (LHsExpr GhcPs)
233− -> R ()
234−p_hsRecField = \HsRecField {..} -> do
235− located hsRecFieldLbl atom
236− unless hsRecPun $ do
237− txt " = "
238− located hsRecFieldArg p_hsExpr
239−
240−p_hsTupArg :: HsTupArg GhcPs -> R ()
241−p_hsTupArg = \case
242− Present NoExt x -> located x p_hsExpr
243− Missing NoExt -> pure ()
244− XTupArg {} -> notImplemented "XTupArg"
473+ HsValBinds NoExtField (ValBinds NoExtField bag lsigs) -> do
474+ -- When in a single-line layout, there is a chance that the inner
475+ -- elements will also contain semicolons and they will confuse the
476+ -- parser. so we request braces around every element except the last.
477+ 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) ->
494+ -- Second argument of IPBind is always Left before type-checking.
495+ let p_ipBind (IPBind NoExtField (Left name) expr) = do
496+ atom name
497+ space
498+ equals
499+ breakpoint
500+ 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
505+ in sepSemi (located' p_ipBind) xs
506+ HsIPBinds NoExtField _ -> notImplemented "HsIpBinds"
507+ EmptyLocalBinds NoExtField -> return ()
508+ XHsLocalBindsLR x -> noExtCon x
509+
510+p_hsRecField ::
511+ HsRecField' RdrName (LHsExpr GhcPs) ->
512+ R ()
513+p_hsRecField HsRecField {..} = do
514+ p_rdrName hsRecFieldLbl
515+ unless hsRecPun $ do
516+ space
517+ equals
518+ let placement =
519+ if onTheSameLine (getLoc hsRecFieldLbl) (getLoc hsRecFieldArg)
520+ then exprPlacement (unLoc hsRecFieldArg)
521+ else Normal
522+ placeHanging placement (located hsRecFieldArg p_hsExpr)
245523
246524p_hsExpr :: HsExpr GhcPs -> R ()
247−p_hsExpr = \case
248− HsVar NoExt name -> p_rdrName name
249− HsUnboundVar NoExt _ -> notImplemented "HsUnboundVar"
250− HsConLikeOut NoExt _ -> notImplemented "HsConLikeOut"
251− HsRecFld NoExt x ->
525+p_hsExpr = p_hsExpr' N
526+
527+p_hsExpr' :: BracketStyle -> HsExpr GhcPs -> R ()
528+p_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 ->
252533 case x of
253− Unambiguous NoExt name -> p_rdrName name
254− Ambiguous NoExt name -> p_rdrName name
255− XAmbiguousFieldOcc NoExt -> notImplemented "XAmbiguousFieldOcc"
256− HsOverLabel NoExt _ v -> do
534+ Unambiguous NoExtField name -> p_rdrName name
535+ Ambiguous NoExtField name -> p_rdrName name
536+ XAmbiguousFieldOcc xx -> noExtCon xx
537+ HsOverLabel NoExtField _ v -> do
257538 txt "#"
258539 atom v
259− HsIPVar NoExt (HsIPName name) -> do
540+ HsIPVar NoExtField (HsIPName name) -> do
260541 txt "?"
261542 atom name
262− HsOverLit NoExt v -> atom (ol_val v)
263− HsLit NoExt lit -> atom lit
264− HsLam NoExt mgroup ->
543+ HsOverLit NoExtField v -> atom (ol_val v)
544+ HsLit NoExtField lit ->
545+ case lit of
546+ HsString (SourceText stxt) _ -> p_stringLit stxt
547+ HsStringPrim (SourceText stxt) _ -> p_stringLit stxt
548+ r -> atom r
549+ HsLam NoExtField mgroup ->
265550 p_matchGroup Lambda mgroup
266− HsLamCase NoExt mgroup -> do
551+ HsLamCase NoExtField mgroup -> do
267552 txt "\\case"
268− newline
269− inci (p_matchGroup LambdaCase mgroup)
270− HsApp NoExt f x -> do
271− located f p_hsExpr
272553 breakpoint
273− inci (located x p_hsExpr)
274− HsAppType a e -> do
554+ inci (p_matchGroup LambdaCase mgroup)
555+ HsApp NoExtField f x -> do
556+ let -- In order to format function applications with multiple parameters
557+ -- nicer, traverse the AST to gather the function and all the
558+ -- parameters together.
559+ gatherArgs f' knownArgs =
560+ case f' of
561+ L _ (HsApp _ l r) -> gatherArgs l (r <| knownArgs)
562+ _ -> (f', knownArgs)
563+ (func, args) = gatherArgs f (x :| [])
564+ -- We need to handle the last argument specially if it is a
565+ -- hanging construct, so separate it from the rest.
566+ (initp, lastp) = (NE.init args, NE.last args)
567+ initSpan =
568+ combineSrcSpans' $
569+ getLoc f :| [(srcLocSpan . srcSpanStart . getLoc) lastp]
570+ -- Hang the last argument only if the initial arguments span one
571+ -- line.
572+ placement =
573+ if isOneLineSpan initSpan
574+ then exprPlacement (unLoc lastp)
575+ else Normal
576+ -- If the last argument is not hanging, just separate every argument as
577+ -- usual. If it is hanging, print the initial arguments and hang the
578+ -- last one. Also, use braces around the every argument except the last
579+ -- one.
580+ case placement of
581+ Normal -> do
582+ let -- Usually we want to bump indentation for arguments for the
583+ -- sake of readability. However, when the function itself is a
584+ -- do-block or case expression it is not a good idea. It seems
585+ -- to be safe to always bump indentation when the function
586+ -- expression is parenthesised.
587+ doIndent =
588+ case func of
589+ L _ (HsPar NoExtField _) -> True
590+ L _ (HsAppType NoExtField _ _) -> True
591+ L _ (HsMultiIf NoExtField _) -> True
592+ L spn _ -> isOneLineSpan spn
593+ ub <-
594+ getLayout <&> \case
595+ SingleLine -> useBraces
596+ MultiLine -> id
597+ ub $ do
598+ located func (p_hsExpr' s)
599+ breakpoint
600+ inciIf doIndent $ sep breakpoint (located' p_hsExpr) initp
601+ inciIf doIndent $ do
602+ unless (null initp) breakpoint
603+ located lastp p_hsExpr
604+ Hanging -> do
605+ useBraces . switchLayout [initSpan] $ do
606+ located func (p_hsExpr' s)
607+ breakpoint
608+ sep breakpoint (located' p_hsExpr) initp
609+ placeHanging placement $
610+ located lastp p_hsExpr
611+ HsAppType NoExtField e a -> do
275612 located e p_hsExpr
276613 breakpoint
277614 inci $ do
278615 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 ()
279621 located (hswc_body a) p_hsType
280− OpApp NoExt x op y -> do
281− located x p_hsExpr
282− space
283− located op p_hsExpr
284− placeHanging (exprPlacement (unLoc y)) $
285− located y p_hsExpr
286− NegApp NoExt e _ -> do
622+ OpApp NoExtField x op y -> do
623+ let opTree = OpBranch (exprOpTree x) op (exprOpTree y)
624+ p_exprOpTree s (reassociateOpTree getOpName opTree)
625+ NegApp NoExtField e _ -> do
287626 txt "-"
627+ space
288628 located e p_hsExpr
289− HsPar NoExt e -> parens (located e p_hsExpr)
290− SectionL NoExt x op -> do
629+ HsPar NoExtField e ->
630+ parens s (located e (dontUseBraces . p_hsExpr))
631+ SectionL NoExtField x op -> do
291632 located x p_hsExpr
292633 breakpoint
293634 inci (located op p_hsExpr)
294− SectionR NoExt op x -> do
635+ SectionR NoExtField op x -> do
295636 located op p_hsExpr
296− breakpoint
637+ useRecordDot' <- useRecordDot
638+ let isRecordDot' = isRecordDot (unLoc op) (getLoc x)
639+ unless (useRecordDot' && isRecordDot') breakpoint
297640 inci (located x p_hsExpr)
298− ExplicitTuple NoExt args boxity -> do
641+ ExplicitTuple NoExtField args boxity ->
299642 let isSection = any (isMissing . unLoc) args
300643 isMissing = \case
301− Missing NoExt -> True
644+ Missing NoExtField -> True
302645 _ -> False
303− let parens' =
646+ p_arg = \case
647+ Present NoExtField x -> located x p_hsExpr
648+ Missing NoExtField -> pure ()
649+ XTupArg x -> noExtCon x
650+ p_larg = sitcc . located' p_arg
651+ parens' =
304652 case boxity of
305653 Boxed -> parens
306654 Unboxed -> parensHash
307− parens' $ if isSection
308− then sequence_ (withSep (txt ",") (located' p_hsTupArg) args)
309− else velt (withSep comma (located' p_hsTupArg) args)
310− ExplicitSum NoExt tag arity e -> do
311− let before = tag - 1
312− after = arity - before - 1
313− args = replicate before Nothing <> [Just e] <> replicate after Nothing
314− f (x,i) = do
315− let isFirst = i == 0
316− isLast = i == arity - 1
317− case x of
318− Nothing ->
319− unless (isFirst || isLast) space
320− Just l -> do
321− unless isFirst space
322− located l p_hsExpr
323− unless isLast space
324− parensHash $ sequence_ (withSep (txt "|") f (zip args [0..]))
325− HsCase NoExt e mgroup -> do
326− txt "case "
327− located e p_hsExpr
328− txt " of"
329− breakpoint
330− inci (p_matchGroup Case mgroup)
331− HsIf NoExt _ if' then' else' -> do
332− txt "if "
333− located if' p_hsExpr
334− breakpoint
335− txt "then"
336− located then' $ \x -> do
337− breakpoint
338− inci (p_hsExpr x)
339− breakpoint
340− txt "else"
341− located else' $ \x -> do
342− breakpoint
343− inci (p_hsExpr x)
344− HsMultiIf NoExt guards -> do
345− txt "if "
346− sitcc $ newlineSep (located' (p_grhs RightArrow)) guards
347− HsLet NoExt localBinds e -> do
348− txt "let "
349− sitcc (located localBinds p_hsLocalBinds)
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 ->
663+ p_unboxedSum N tag arity (located e p_hsExpr)
664+ HsCase NoExtField e mgroup ->
665+ p_case exprPlacement p_hsExpr e mgroup
666+ HsIf NoExtField _ if' then' else' ->
667+ p_if exprPlacement p_hsExpr if' then' else'
668+ HsMultiIf NoExtField guards -> do
669+ txt "if"
350670 breakpoint
351− txt "in "
352− sitcc (located e p_hsExpr)
353− HsDo NoExt ctx es -> do
671+ inci . inci $ sep newline (located' (p_grhs RightArrow)) guards
672+ HsLet NoExtField localBinds e ->
673+ p_let p_hsExpr localBinds e
674+ HsDo NoExtField ctx es -> do
354675 let doBody header = do
355676 txt header
356− newline
357− inci $ located es (newlineSep (located' (sitcc . p_stmt)))
358− compBody = brackets $ located es $ \xs -> do
359− let stmts = init xs
677+ breakpoint
678+ ub <- layoutToBraces <$> getLayout
679+ inci $
680+ sepSemi
681+ (ub . withSpacing (p_stmt' exprPlacement (p_hsExpr' S)))
682+ (unLoc es)
683+ compBody = brackets N . located es $ \xs -> do
684+ let p_parBody =
685+ sep
686+ (breakpoint >> txt "|" >> space)
687+ p_seqBody
688+ p_seqBody =
689+ sitcc
690+ . sep
691+ commaDel
692+ (located' (sitcc . p_stmt))
693+ stmts = init xs
360694 yield = last xs
695+ lists = foldr (liftAppend . gatherStmt) [] stmts
361696 located yield p_stmt
362697 breakpoint
363− txt "| "
364− case stmts of
365− [stmt] | ParStmt {} <- unLoc stmt -> located stmt p_stmt
366− _ -> velt $ withSep comma (located' (sitcc . p_stmt)) stmts
698+ txt "|"
699+ space
700+ p_parBody lists
367701 case ctx of
368702 DoExpr -> doBody "do"
369703 MDoExpr -> doBody "mdo"
370704 ListComp -> compBody
371705 MonadComp -> notImplemented "MonadComp"
372− ArrowExpr -> notImplemented "ArrowExpr"
706+ ArrowExpr -> notImplemented "ArrowExpr"
373707 GhciStmtCtxt -> notImplemented "GhciStmtCtxt"
374708 PatGuard _ -> notImplemented "PatGuard"
375709 ParStmtCtxt _ -> notImplemented "ParStmtCtxt"
376710 TransStmtCtxt _ -> notImplemented "TransStmtCtxt"
377711 ExplicitList _ _ xs ->
378− brackets $ velt (withSep comma (located' p_hsExpr) xs)
712+ brackets s $
713+ sep commaDel (sitcc . located' p_hsExpr) xs
379714 RecordCon {..} -> do
380715 located rcon_con_name atom
381716 breakpoint
382717 let HsRecFields {..} = rcon_flds
383− fields = located' p_hsRecField <$> rec_flds
718+ updName f =
719+ (f :: HsRecField GhcPs (LHsExpr GhcPs))
720+ { hsRecFieldLbl = case unLoc $ hsRecFieldLbl f of
721+ FieldOcc _ n -> n
722+ XFieldOcc x -> noExtCon x
723+ }
724+ fields = located' (p_hsRecField . updName) <$> rec_flds
384725 dotdot =
385726 case rec_dotdot of
386727 Just {} -> [txt ".."]
387728 Nothing -> []
388− inci $ braces $ velt (withSep comma id (fields <> dotdot))
729+ inci . braces N $
730+ sep commaDel sitcc (fields <> dotdot)
389731 RecordUpd {..} -> do
390732 located rupd_expr p_hsExpr
391− breakpoint
392− inci $ braces $ velt (withSep comma (located' p_hsRecField) rupd_flds)
393− ExprWithTySig affix x -> sitcc $ do
733+ useRecordDot' <- useRecordDot
734+ let mrs sp = case getLoc sp of
735+ RealSrcSpan r -> Just r
736+ _ -> Nothing
737+ let isPluginForm =
738+ ((1 +) . srcSpanEndCol <$> mrs rupd_expr)
739+ == (srcSpanStartCol <$> mrs (head rupd_flds))
740+ unless (useRecordDot' && isPluginForm) breakpoint
741+ let updName f =
742+ (f :: HsRecUpdField GhcPs)
743+ { hsRecFieldLbl = case unLoc $ hsRecFieldLbl f of
744+ Ambiguous _ n -> n
745+ Unambiguous _ n -> n
746+ XAmbiguousFieldOcc x -> noExtCon x
747+ }
748+ inci . braces N $
749+ sep
750+ commaDel
751+ (sitcc . located' (p_hsRecField . updName))
752+ rupd_flds
753+ ExprWithTySig NoExtField x HsWC {hswc_body = HsIB {..}} -> sitcc $ do
394754 located x p_hsExpr
755+ space
756+ txt "::"
395757 breakpoint
396− inci $ do
397− txt ":: "
398− let HsWC {..} = affix
399− HsIB {..} = hswc_body
400− located hsib_body p_hsType
401− ArithSeq NoExt _ x -> do
758+ 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 ->
402762 case x of
403− From from -> brackets $ do
763+ From from -> brackets s $ do
404764 located from p_hsExpr
405− breakpoint'
765+ breakpoint
406766 txt ".."
407− FromThen from next -> brackets $ do
408− velt (withSep comma (located' p_hsExpr) [from, next])
409− breakpoint'
767+ FromThen from next -> brackets s $ do
768+ sep commaDel (located' p_hsExpr) [from, next]
769+ breakpoint
410770 txt ".."
411− FromTo from to -> brackets $ do
771+ FromTo from to -> brackets s $ do
412772 located from p_hsExpr
413− breakpoint'
414− txt ".. "
773+ breakpoint
774+ txt ".."
775+ space
415776 located to p_hsExpr
416− FromThenTo from next to -> brackets $ do
417− velt (withSep comma (located' p_hsExpr) [from, next])
418− breakpoint'
419− txt ".. "
777+ FromThenTo from next to -> brackets s $ do
778+ sep commaDel (located' p_hsExpr) [from, next]
779+ breakpoint
780+ txt ".."
781+ space
420782 located to p_hsExpr
421− HsSCC NoExt _ name x -> do
783+ HsSCC NoExtField _ name x -> do
422784 txt "{-# SCC "
423785 atom name
424786 txt " #-}"
425787 breakpoint
426788 located x p_hsExpr
427− HsCoreAnn NoExt _ value x -> do
789+ HsCoreAnn NoExtField _ value x -> do
428790 txt "{-# CORE "
429791 atom value
430792 txt " #-}"
431793 breakpoint
432794 located x p_hsExpr
433− HsBracket NoExt x -> p_hsBracket x
795+ HsBracket NoExtField x -> p_hsBracket x
434796 HsRnBracketOut {} -> notImplemented "HsRnBracketOut"
435797 HsTcBracketOut {} -> notImplemented "HsTcBracketOut"
436− HsSpliceE NoExt splice -> p_hsSplice splice
437− HsProc {} -> notImplemented "HsProc"
438− HsStatic _ e -> do
798+ HsSpliceE NoExtField splice -> p_hsSplice splice
799+ HsProc NoExtField p e -> do
800+ txt "proc"
801+ located p $ \x -> do
802+ breakpoint
803+ inci (p_pat x)
804+ breakpoint
805+ txt "->"
806+ placeHanging (cmdTopPlacement (unLoc e)) $
807+ located e p_hsCmdTop
808+ HsStatic _ e -> do
439809 txt "static"
440810 breakpoint
441811 inci (located e p_hsExpr)
442− HsArrApp {} -> notImplemented "HsArrApp"
443− HsArrForm {} -> notImplemented "HsArrForm"
444812 HsTick {} -> notImplemented "HsTick"
445813 HsBinTick {} -> notImplemented "HsBinTick"
446814 HsTickPragma {} -> notImplemented "HsTickPragma"
447− EWildPat NoExt -> txt "_"
448− EAsPat {} -> notImplemented "EAsPat"
449− EViewPat {} -> notImplemented "EViewPat"
450− ELazyPat {} -> notImplemented "ELazyPat"
451815 HsWrap {} -> notImplemented "HsWrap"
452− XExpr {} -> notImplemented "XExpr"
816+ XExpr x -> noExtCon x
453817
454818p_patSynBind :: PatSynBind GhcPs GhcPs -> R ()
455819p_patSynBind PSB {..} = do
456− txt "pattern "
457− case psb_dir of
458− Unidirectional -> do
459− p_rdrName psb_id
820+ let rhs = do
821+ space
822+ case psb_dir of
823+ Unidirectional -> do
824+ txt "<-"
825+ breakpoint
826+ located psb_def p_pat
827+ ImplicitBidirectional -> do
828+ equals
829+ breakpoint
830+ located psb_def p_pat
831+ ExplicitBidirectional mgroup -> do
832+ txt "<-"
833+ breakpoint
834+ located psb_def p_pat
835+ newline
836+ txt "where"
837+ newline
838+ inci (p_matchGroup (Function psb_id) mgroup)
839+ txt "pattern"
840+ case psb_args of
841+ PrefixCon xs -> do
460842 space
461− p_patSynDetails psb_args
462− txt " <-"
463− breakpoint
464− inci (located psb_def p_pat)
465− ImplicitBidirectional -> do
466843 p_rdrName psb_id
844+ inci $ do
845+ switchLayout (getLoc <$> xs) $ do
846+ unless (null xs) breakpoint
847+ sitcc (sep breakpoint p_rdrName xs)
848+ rhs
849+ RecCon xs -> do
467850 space
468− p_patSynDetails psb_args
469− txt " ="
470− breakpoint
471− located psb_def p_pat
472− ExplicitBidirectional mgroup -> do
473851 p_rdrName psb_id
474− space
475− p_patSynDetails psb_args
476− txt " <-"
477− breakpoint
478− inci (located psb_def p_pat)
479− newline
480852 inci $ do
481− line (txt "where")
482− inci (p_matchGroup (Function psb_id) mgroup)
483−p_patSynBind (XPatSynBind NoExt) = notImplemented "XPatSynBind"
484−
485−p_patSynDetails :: HsPatSynDetails (Located RdrName) -> R ()
486−p_patSynDetails = \case
487− PrefixCon xs ->
488− velt' (p_rdrName <$> xs)
489− RecCon xs ->
490− velt' (p_rdrName . recordPatSynPatVar <$> xs)
491− InfixCon _ _ -> notImplemented "InfixCon"
853+ switchLayout (getLoc . recordPatSynPatVar <$> xs) $ do
854+ unless (null xs) breakpoint
855+ braces N $
856+ sep commaDel (p_rdrName . recordPatSynPatVar) xs
857+ rhs
858+ InfixCon l r -> do
859+ switchLayout [getLoc l, getLoc r] $ do
860+ space
861+ p_rdrName l
862+ breakpoint
863+ inci $ do
864+ p_rdrName psb_id
865+ space
866+ p_rdrName r
867+ inci rhs
868+p_patSynBind (XPatSynBind x) = noExtCon x
869+
870+p_case ::
871+ Data body =>
872+ -- | Placer
873+ (body -> Placement) ->
874+ -- | Render
875+ (body -> R ()) ->
876+ -- | Expression
877+ LHsExpr GhcPs ->
878+ -- | Match group
879+ MatchGroup GhcPs (Located body) ->
880+ R ()
881+p_case placer render e mgroup = do
882+ txt "case"
883+ space
884+ located e p_hsExpr
885+ space
886+ txt "of"
887+ breakpoint
888+ inci (p_matchGroup' placer render Case mgroup)
889+
890+p_if ::
891+ Data body =>
892+ -- | Placer
893+ (body -> Placement) ->
894+ -- | Render
895+ (body -> R ()) ->
896+ -- | If
897+ LHsExpr GhcPs ->
898+ -- | Then
899+ Located body ->
900+ -- | Else
901+ Located body ->
902+ R ()
903+p_if placer render if' then' else' = do
904+ txt "if"
905+ space
906+ located if' p_hsExpr
907+ breakpoint
908+ inci $ do
909+ txt "then"
910+ space
911+ located then' $ \x ->
912+ placeHanging (placer x) (render x)
913+ breakpoint
914+ txt "else"
915+ space
916+ located else' $ \x ->
917+ placeHanging (placer x) (render x)
918+
919+p_let ::
920+ Data body =>
921+ -- | Render
922+ (body -> R ()) ->
923+ Located (HsLocalBindsLR GhcPs GhcPs) ->
924+ Located body ->
925+ R ()
926+p_let render localBinds e = sitcc $ do
927+ txt "let"
928+ space
929+ dontUseBraces $ sitcc (located localBinds p_hsLocalBinds)
930+ vlayout space (newline >> txt " ")
931+ txt "in"
932+ space
933+ sitcc (located e render)
492934
493935p_pat :: Pat GhcPs -> R ()
494936p_pat = \case
495− WildPat NoExt -> txt "_"
496− VarPat NoExt name -> p_rdrName name
497− LazyPat NoExt pat -> do
937+ WildPat NoExtField -> txt "_"
938+ VarPat NoExtField name -> p_rdrName name
939+ LazyPat NoExtField pat -> do
498940 txt "~"
499941 located pat p_pat
500− AsPat NoExt name pat -> do
942+ AsPat NoExtField name pat -> do
501943 p_rdrName name
502944 txt "@"
503945 located pat p_pat
504− ParPat NoExt pat ->
505− located pat (parens . p_pat)
506− BangPat NoExt pat -> do
946+ ParPat NoExtField pat ->
947+ located pat (parens S . p_pat)
948+ BangPat NoExtField pat -> do
507949 txt "!"
508950 located pat p_pat
509− ListPat NoExt pats -> do
510− brackets $ velt (withSep comma (located' p_pat) pats)
511− TuplePat NoExt pats boxing -> do
512− let f =
951+ ListPat NoExtField pats ->
952+ brackets S $ sep commaDel (located' p_pat) pats
953+ TuplePat NoExtField pats boxing -> do
954+ let parens' =
513955 case boxing of
514− Boxed -> parens
515− Unboxed -> parensHash
516− f $ velt (withSep comma (located' p_pat) pats)
517− SumPat NoExt pat _ _ -> do
518− -- XXX I'm not sure about this one.
519− located pat p_pat
956+ Boxed -> parens S
957+ 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)
520961 ConPatIn pat details ->
521962 case details of
522963 PrefixCon xs -> sitcc $ do
523964 p_rdrName pat
524965 unless (null xs) $ do
525966 breakpoint
526− inci $ velt' (located' p_pat <$> xs)
967+ inci . sitcc $ sep breakpoint (sitcc . located' p_pat) xs
527968 RecCon (HsRecFields fields dotdot) -> do
528969 p_rdrName pat
529970 breakpoint
530971 let f = \case
531972 Nothing -> txt ".."
532973 Just x -> located x p_pat_hsRecField
533− inci . braces . velt . withSep comma f $ case dotdot of
534− Nothing -> Just <$> fields
535− Just n -> (Just <$> take n fields) ++ [Nothing]
536− InfixCon x y -> do
537− located x p_pat
538− space
539− p_rdrName pat
540− breakpoint
541− inci (located y p_pat)
974+ inci . braces N . sep commaDel f $
975+ case dotdot of
976+ 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
542986 ConPatOut {} -> notImplemented "ConPatOut" -- presumably created by renamer?
543− ViewPat NoExt expr pat -> sitcc $ do
987+ ViewPat NoExtField expr pat -> sitcc $ do
544988 located expr p_hsExpr
545− txt " ->"
989+ space
990+ txt "->"
546991 breakpoint
547992 inci (located pat p_pat)
548− SplicePat NoExt splice -> p_hsSplice splice
549− LitPat NoExt p -> atom p
550− NPat NoExt v _ _ -> located v (atom . ol_val)
551− NPlusKPat NoExt n k _ _ _ -> sitcc $ do
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
552997 p_rdrName n
553998 breakpoint
554999 inci $ do
555− txt "+ "
1000+ txt "+"
1001+ space
5561002 located k (atom . ol_val)
557− SigPat hswc pat -> do
1003+ SigPat NoExtField pat hswc -> do
5581004 located pat p_pat
5591005 p_typeAscription hswc
5601006 CoPat {} -> notImplemented "CoPat" -- apparently created at some later stage
561− XPat NoExt -> notImplemented "XPat"
1007+ XPat x -> noExtCon x
5621008
5631009p_pat_hsRecField :: HsRecField' (FieldOcc GhcPs) (LPat GhcPs) -> R ()
5641010p_pat_hsRecField HsRecField {..} = do
5651011 located hsRecFieldLbl $ \x ->
5661012 p_rdrName (rdrNameFieldOcc x)
5671013 unless hsRecPun $ do
568− txt " ="
1014+ space
1015+ equals
5691016 breakpoint
5701017 inci (located hsRecFieldArg p_pat)
5711018
1019+p_unboxedSum :: BracketStyle -> ConTag -> Arity -> R () -> R ()
1020+p_unboxedSum s tag arity m = do
1021+ let before = tag - 1
1022+ after = arity - before - 1
1023+ args = replicate before Nothing <> [Just m] <> replicate after Nothing
1024+ f x =
1025+ case x :: Maybe (R ()) of
1026+ Nothing ->
1027+ space
1028+ Just m' -> do
1029+ space
1030+ m'
1031+ space
1032+ parensHash s $ sep (txt "|") f args
1033+
5721034p_hsSplice :: HsSplice GhcPs -> R ()
5731035p_hsSplice = \case
574− HsTypedSplice NoExt deco _ expr -> p_hsSpliceTH True expr deco
575− HsUntypedSplice NoExt deco _ expr -> p_hsSpliceTH False expr deco
576− HsQuasiQuote NoExt _ quoterName srcSpan str -> do
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
5771039 txt "["
5781040 p_rdrName (L srcSpan quoterName)
5791041 txt "|"
580− -- NOTE QuasiQuoters often rely on precise custom strings. We cannot do
581− -- any formatting here without potentially breaking someone's code.
1042+ -- QuasiQuoters often rely on precise custom strings. We cannot do any
1043+ -- formatting here without potentially breaking someone's code.
5821044 atom str
5831045 txt "|]"
5841046 HsSpliced {} -> notImplemented "HsSpliced"
585− XSplice {} -> notImplemented "XSplice"
1047+ HsSplicedT {} -> notImplemented "HsSplicedT"
1048+ XSplice x -> noExtCon x
5861049
587−p_hsSpliceTH
588− :: Bool -- ^ Typed splice?
589− -> LHsExpr GhcPs -- ^ Splice expression
590− -> SpliceDecoration -- ^ Splice decoration
591− -> R ()
1050+p_hsSpliceTH ::
1051+ -- | Typed splice?
1052+ Bool ->
1053+ -- | Splice expression
1054+ LHsExpr GhcPs ->
1055+ -- | Splice decoration
1056+ SpliceDecoration ->
1057+ R ()
5921058p_hsSpliceTH isTyped expr = \case
5931059 HasParens -> do
5941060 txt decoSymbol
595− parens (located expr (sitcc . p_hsExpr))
1061+ parens N (located expr (sitcc . p_hsExpr))
5961062 HasDollar -> do
5971063 txt decoSymbol
5981064 located expr (sitcc . p_hsExpr)
599− NoParens -> do
1065+ NoParens ->
6001066 located expr (sitcc . p_hsExpr)
6011067 where
6021068 decoSymbol = if isTyped then "$$" else "$"
6031069
6041070p_hsBracket :: HsBracket GhcPs -> R ()
6051071p_hsBracket = \case
606− ExpBr NoExt expr -> quote "e" (located expr p_hsExpr)
607− PatBr NoExt pat -> quote "p" (located pat p_pat)
608− DecBrL NoExt decls -> quote "d" (p_hsDecls decls)
609− DecBrG NoExt _ -> notImplemented "DecBrG" -- result of renamer
610− TypBr NoExt ty -> quote "t" (located ty p_hsType)
611− VarBr NoExt _ _ -> notImplemented "VarBr"
612− TExpBr NoExt expr -> do
1072+ ExpBr NoExtField expr -> do
1073+ anns <- getEnclosingAnns
1074+ let name = case anns of
1075+ AnnOpenEQ : _ -> ""
1076+ _ -> "e"
1077+ quote name (located expr p_hsExpr)
1078+ PatBr NoExtField pat -> located pat (quote "p" . p_pat)
1079+ DecBrL NoExtField decls -> quote "d" (p_hsDecls Free decls)
1080+ DecBrG NoExtField _ -> notImplemented "DecBrG" -- result of renamer
1081+ TypBr NoExtField ty -> quote "t" (located ty p_hsType)
1082+ VarBr NoExtField isSingleQuote name -> do
1083+ txt (bool "''" "'" isSingleQuote)
1084+ -- HACK As you can see we use 'noLoc' here to be able to pass name into
1085+ -- 'p_rdrName' since the latter expects a "located" thing. The problem
1086+ -- is that 'VarBr' doesn't provide us with location of the name. This in
1087+ -- turn makes it impossible to detect if there are parentheses around
1088+ -- it, etc. So we have to add parentheses manually assuming they are
1089+ -- necessary for all operators.
1090+ let isOperator =
1091+ all
1092+ (\i -> isPunctuation i || isSymbol i)
1093+ (showOutputable (rdrNameOcc name))
1094+ && not (doesNotNeedExtraParens name)
1095+ wrapper = if isOperator then parens N else id
1096+ wrapper $ p_rdrName (noLoc name)
1097+ TExpBr NoExtField expr -> do
6131098 txt "[||"
6141099 breakpoint'
6151100 located expr p_hsExpr
6161101 breakpoint'
6171102 txt "||]"
618− XBracket {} -> notImplemented "XBracket"
1103+ XBracket x -> noExtCon x
6191104 where
6201105 quote :: Text -> R () -> R ()
6211106 quote name body = do
@@ -623,23 +1108,86 @@ p_hsBracket = \case
6231108 txt name
6241109 txt "|"
6251110 breakpoint'
626− body
627− breakpoint'
628− txt "|]"
1111+ inci $ do
1112+ dontUseBraces body
1113+ breakpoint'
1114+ txt "|]"
1115+
1116+-- Print the source text of a string literal while indenting
1117+-- gaps correctly.
1118+
1119+p_stringLit :: String -> R ()
1120+p_stringLit src =
1121+ let s = splitGaps src
1122+ singleLine =
1123+ txt $ Text.pack (mconcat s)
1124+ multiLine =
1125+ sitcc $ sep breakpoint (txt . Text.pack) (backslashes s)
1126+ in vlayout singleLine multiLine
1127+ where
1128+ -- Split a string on gaps (backslash delimited whitespaces)
1129+ --
1130+ -- > splitGaps "bar\\ \\fo\\&o" == ["bar", "fo\\&o"]
1131+ splitGaps :: String -> [String]
1132+ splitGaps "" = []
1133+ splitGaps s =
1134+ let -- A backslash and a whitespace starts a "gap"
1135+ p (Just '\\', _, _) = True
1136+ p (_, '\\', Just c) | ghcSpace c = False
1137+ p _ = True
1138+ in case span p (zipPrevNext s) of
1139+ (l, r) ->
1140+ let -- drop the initial '\', any amount of 'ghcSpace', and another '\'
1141+ r' = drop 1 . dropWhile ghcSpace . drop 1 $ map orig r
1142+ in map orig l : splitGaps r'
1143+ -- GHC's definition of whitespaces in strings
1144+ -- See: https://gitlab.haskell.org/ghc/ghc/blob/86753475/compiler/parser/Lexer.x#L1653
1145+ ghcSpace :: Char -> Bool
1146+ ghcSpace c = c <= '\x7f' && is_space c
1147+ -- Add backslashes to the inner side of the strings
1148+ --
1149+ -- > backslashes ["a", "b", "c"] == ["a\\", "\\b\\", "\\c"]
1150+ backslashes :: [String] -> [String]
1151+ backslashes (x : y : xs) = (x ++ "\\") : backslashes (('\\' : y) : xs)
1152+ backslashes xs = xs
1153+ -- Attaches previous and next items to each list element
1154+ zipPrevNext :: [a] -> [(Maybe a, a, Maybe a)]
1155+ zipPrevNext xs =
1156+ let z =
1157+ zip
1158+ (zip (Nothing : map Just xs) xs)
1159+ (map Just (tail xs) ++ repeat Nothing)
1160+ in map (\((p, x), n) -> (p, x, n)) z
1161+ orig (_, x, _) = x
6291162
6301163----------------------------------------------------------------------------
6311164-- Helpers
6321165
633−getGRHSSpan :: GRHS GhcPs (LHsExpr GhcPs) -> SrcSpan
634−getGRHSSpan (GRHS NoExt _ body) = getLoc body
635−getGRHSSpan (XGRHS NoExt) = notImplemented "XGRHS"
1166+-- | Return the wrapping function controlling the use of braces according to
1167+-- the current layout.
1168+layoutToBraces :: Layout -> R () -> R ()
1169+layoutToBraces = \case
1170+ SingleLine -> useBraces
1171+ MultiLine -> id
1172+
1173+-- | Append each element in both lists with semigroups. If one list is shorter
1174+-- than the other, return the rest of the longer list unchanged.
1175+liftAppend :: Semigroup a => [a] -> [a] -> [a]
1176+liftAppend [] [] = []
1177+liftAppend [] (y : ys) = y : ys
1178+liftAppend (x : xs) [] = x : xs
1179+liftAppend (x : xs) (y : ys) = x <> y : liftAppend xs ys
1180+
1181+getGRHSSpan :: GRHS GhcPs (Located body) -> SrcSpan
1182+getGRHSSpan (GRHS NoExtField guards body) =
1183+ combineSrcSpans' $ getLoc body :| map getLoc guards
1184+getGRHSSpan (XGRHS x) = noExtCon x
6361185
6371186-- | Place a thing that may have a hanging form. This function handles how
6381187-- to separate it from preceding expressions and whether to bump indentation
6391188-- depending on what sort of expression we have.
640−
6411189placeHanging :: Placement -> R () -> R ()
642−placeHanging placement m = do
1190+placeHanging placement m =
6431191 case placement of
6441192 Hanging -> do
6451193 space
@@ -650,26 +1198,165 @@ placeHanging placement m = do
6501198
6511199-- | Check if given block contains single expression which has a hanging
6521200-- form.
1201+blockPlacement ::
1202+ (body -> Placement) ->
1203+ [LGRHS GhcPs (Located body)] ->
1204+ Placement
1205+blockPlacement placer [L _ (GRHS NoExtField _ (L _ x))] = placer x
1206+blockPlacement _ _ = Normal
6531207
654−blockPlacement :: [LGRHS GhcPs (LHsExpr GhcPs)] -> Placement
655−blockPlacement [(L _ (GRHS NoExt _ (L _ e)))] = exprPlacement e
656−blockPlacement _ = Normal
1208+-- | Check if given command has a hanging form.
1209+cmdPlacement :: HsCmd GhcPs -> Placement
1210+cmdPlacement = \case
1211+ HsCmdLam NoExtField _ -> Hanging
1212+ HsCmdCase NoExtField _ _ -> Hanging
1213+ HsCmdDo NoExtField _ -> Hanging
1214+ _ -> Normal
6571215
658−-- | Check if given expression has hinging a form.
1216+cmdTopPlacement :: HsCmdTop GhcPs -> Placement
1217+cmdTopPlacement = \case
1218+ HsCmdTop NoExtField (L _ x) -> cmdPlacement x
1219+ XCmdTop x -> noExtCon x
6591220
1221+-- | Check if given expression has a hanging form.
6601222exprPlacement :: HsExpr GhcPs -> Placement
6611223exprPlacement = \case
662− HsLam NoExt _ -> Hanging
663− HsLamCase NoExt _ -> Hanging
664− HsCase NoExt _ _ -> Hanging
665− HsDo NoExt DoExpr _ -> Hanging
666− HsDo NoExt MDoExpr _ -> Hanging
667− RecordCon NoExt _ _ -> Hanging
1224+ -- Only hang lambdas with single line parameter lists
1225+ HsLam NoExtField mg -> case mg of
1226+ MG _ (L _ [L _ (Match NoExtField _ (x : xs) _)]) _
1227+ | isOneLineSpan (combineSrcSpans' $ fmap getLoc (x :| xs)) ->
1228+ Hanging
1229+ _ -> 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
6681245 _ -> Normal
6691246
670−withGuards :: [LGRHS GhcPs (LHsExpr GhcPs)] -> Bool
1247+withGuards :: [LGRHS GhcPs (Located body)] -> Bool
6711248withGuards = any (checkOne . unLoc)
6721249 where
673− checkOne :: GRHS GhcPs (LHsExpr GhcPs) -> Bool
674− checkOne (GRHS NoExt [] _) = False
1250+ checkOne :: GRHS GhcPs (Located body) -> Bool
1251+ checkOne (GRHS NoExtField [] _) = False
6751252 checkOne _ = True
1253+
1254+exprOpTree :: LHsExpr GhcPs -> OpTree (LHsExpr GhcPs) (LHsExpr GhcPs)
1255+exprOpTree (L _ (OpApp NoExtField x op y)) = OpBranch (exprOpTree x) op (exprOpTree y)
1256+exprOpTree n = OpNode n
1257+
1258+getOpName :: HsExpr GhcPs -> Maybe RdrName
1259+getOpName = \case
1260+ HsVar NoExtField (L _ a) -> Just a
1261+ _ -> Nothing
1262+
1263+getOpNameStr :: RdrName -> String
1264+getOpNameStr = occNameString . rdrNameOcc
1265+
1266+p_exprOpTree ::
1267+ -- | Bracket style to use
1268+ BracketStyle ->
1269+ OpTree (LHsExpr GhcPs) (LHsExpr GhcPs) ->
1270+ R ()
1271+p_exprOpTree s (OpNode x) = located x (p_hsExpr' s)
1272+p_exprOpTree s (OpBranch x op y) = do
1273+ -- If the beginning of the first argument and the second argument are on
1274+ -- the same line, and the second argument has a hanging form, use hanging
1275+ -- placement.
1276+ let placement =
1277+ if isOneLineSpan
1278+ (mkSrcSpan (srcSpanStart (opTreeLoc x)) (srcSpanStart (opTreeLoc y)))
1279+ then case y of
1280+ OpNode (L _ n) -> exprPlacement n
1281+ _ -> Normal
1282+ else Normal
1283+ -- Distinguish holes used in infix notation.
1284+ -- eg. '1 _foo 2' and '1 `_foo` 2'
1285+ opWrapper = case unLoc op of
1286+ HsUnboundVar NoExtField _ -> backticks
1287+ _ -> id
1288+ layout <- getLayout
1289+ let ub = case layout of
1290+ SingleLine -> useBraces
1291+ MultiLine -> case placement of
1292+ Hanging -> useBraces
1293+ Normal -> dontUseBraces
1294+ opNameStr = (fmap getOpNameStr . getOpName . unLoc) op
1295+ gotDollar = opNameStr == Just "$"
1296+ gotColon = opNameStr == Just ":"
1297+ gotRecordDot = isRecordDot (unLoc op) (opTreeLoc y)
1298+ lhs =
1299+ switchLayout [opTreeLoc x] $
1300+ p_exprOpTree s x
1301+ p_op = located op (opWrapper . p_hsExpr)
1302+ p_y = switchLayout [opTreeLoc y] (p_exprOpTree N y)
1303+ isSection = case (opTreeLoc x, getLoc op) of
1304+ (RealSrcSpan treeSpan, RealSrcSpan opSpan) ->
1305+ srcSpanEndCol treeSpan /= srcSpanStartCol opSpan
1306+ _ -> False
1307+ isDoBlock = \case
1308+ OpNode (L _ HsDo {}) -> True
1309+ _ -> False
1310+ useRecordDot' <- useRecordDot
1311+ if
1312+ | gotColon -> do
1313+ lhs
1314+ space
1315+ p_op
1316+ case placement of
1317+ Hanging -> do
1318+ space
1319+ p_y
1320+ Normal -> do
1321+ breakpoint
1322+ inciIf (isDoBlock y) p_y
1323+ | gotDollar
1324+ && isOneLineSpan (opTreeLoc x)
1325+ && placement == Normal -> do
1326+ useBraces lhs
1327+ space
1328+ p_op
1329+ breakpoint
1330+ inci p_y
1331+ | useRecordDot' && gotRecordDot -> do
1332+ lhs
1333+ when isSection space
1334+ p_op
1335+ p_y
1336+ | otherwise -> do
1337+ ub lhs
1338+ placeHanging placement $ do
1339+ p_op
1340+ space
1341+ p_y
1342+
1343+-- | Return 'True' if given expression is a record-dot operator expression.
1344+isRecordDot ::
1345+ -- | Operator expression
1346+ HsExpr GhcPs ->
1347+ -- | Span of the expression on the right-hand side of the operator
1348+ SrcSpan ->
1349+ Bool
1350+isRecordDot op (RealSrcSpan ySpan) = case op of
1351+ HsVar NoExtField (L (RealSrcSpan opSpan) opName) ->
1352+ (getOpNameStr opName == ".") && (srcSpanEndCol opSpan == srcSpanStartCol ySpan)
1353+ _ -> False
1354+isRecordDot _ _ = False
1355+
1356+-- | Get annotations for the enclosing element.
1357+getEnclosingAnns :: R [AnnKeywordId]
1358+getEnclosingAnns = do
1359+ e <- getEnclosingSpan (const True)
1360+ case e of
1361+ Nothing -> return []
1362+ Just e' -> getAnns (RealSrcSpan e')
src/Ormolu/Printer/Meat/Declaration/Value.hs-bootnew file+17
@@ -0,0 +1,17 @@
1+module Ormolu.Printer.Meat.Declaration.Value
2+ ( p_valDecl,
3+ p_pat,
4+ p_hsExpr,
5+ p_hsSplice,
6+ p_stringLit,
7+ )
8+where
9+
10+import GHC
11+import Ormolu.Printer.Combinators
12+
13+p_valDecl :: HsBindLR GhcPs GhcPs -> R ()
14+p_pat :: Pat GhcPs -> R ()
15+p_hsExpr :: HsExpr GhcPs -> R ()
16+p_hsSplice :: HsSplice GhcPs -> R ()
17+p_stringLit :: String -> R ()
src/Ormolu/Printer/Meat/Declaration/Warning.hsnew file+49
@@ -0,0 +1,49 @@
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+
4+module Ormolu.Printer.Meat.Declaration.Warning
5+ ( p_warnDecls,
6+ p_moduleWarning,
7+ )
8+where
9+
10+import BasicTypes
11+import Data.Foldable
12+import Data.Text (Text)
13+import GHC
14+import Ormolu.Printer.Combinators
15+import Ormolu.Printer.Meat.Common
16+
17+p_warnDecls :: WarnDecls GhcPs -> R ()
18+p_warnDecls (Warnings NoExtField _ warnings) =
19+ traverse_ (located' p_warnDecl) warnings
20+p_warnDecls (XWarnDecls x) = noExtCon x
21+
22+p_warnDecl :: WarnDecl GhcPs -> R ()
23+p_warnDecl (Warning NoExtField functions warningTxt) =
24+ p_topLevelWarning functions warningTxt
25+p_warnDecl (XWarnDecl x) = noExtCon x
26+
27+p_moduleWarning :: WarningTxt -> R ()
28+p_moduleWarning wtxt = do
29+ let (pragmaText, lits) = warningText wtxt
30+ inci $ pragma pragmaText $ inci $ p_lits lits
31+
32+p_topLevelWarning :: [Located RdrName] -> WarningTxt -> R ()
33+p_topLevelWarning fnames wtxt = do
34+ 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+ breakpoint
39+ p_lits lits
40+
41+warningText :: WarningTxt -> (Text, [Located StringLiteral])
42+warningText = \case
43+ WarningTxt _ lits -> ("WARNING", lits)
44+ DeprecatedTxt _ lits -> ("DEPRECATED", lits)
45+
46+p_lits :: [Located StringLiteral] -> R ()
47+p_lits = \case
48+ [l] -> atom l
49+ ls -> brackets N $ sep commaDel atom ls
src/Ormolu/Printer/Meat/ImportExport.hs+100−54
@@ -1,21 +1,19 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
44
55-- | Rendering of import and export lists.
6−
76module Ormolu.Printer.Meat.ImportExport
8− ( p_hsmodExports
9− , p_hsmodImport
7+ ( p_hsmodExports,
8+ p_hsmodImport,
109 )
1110where
1211
1312import Control.Monad
1413import GHC
15−import HsImpExp (IE (..))
1614import Ormolu.Printer.Combinators
1715import Ormolu.Printer.Meat.Common
18−import Ormolu.Utils
16+import Ormolu.Utils (RelativePos (..), attachRelativePos)
1917
2018p_hsmodExports :: [LIE GhcPs] -> R ()
2119p_hsmodExports [] = do
@@ -23,58 +21,106 @@ p_hsmodExports [] = do
2321 breakpoint'
2422 txt ")"
2523p_hsmodExports xs =
26− parens . velt $ withSep comma (sitcc . located' p_lie) xs
24+ parens N $ do
25+ layout <- getLayout
26+ sep
27+ breakpoint
28+ (\(p, l) -> sitcc (located l (p_lie layout p)))
29+ (attachRelativePos xs)
2730
28−p_hsmodImport :: ImportDecl GhcPs -> R ()
29−p_hsmodImport ImportDecl {..} = line $ do
30− txt "import "
31− when ideclSource $
32− txt "{-# SOURCE #-} "
33− when ideclSafe $
34− txt "safe "
35− when ideclQualified $
36− txt "qualified "
31+p_hsmodImport :: Bool -> ImportDecl GhcPs -> R ()
32+p_hsmodImport useQualifiedPost ImportDecl {..} = do
33+ txt "import"
34+ space
35+ when ideclSource (txt "{-# SOURCE #-}")
36+ space
37+ when ideclSafe (txt "safe")
38+ space
39+ when
40+ (isImportDeclQualified ideclQualified && not useQualifiedPost)
41+ (txt "qualified")
42+ space
3743 case ideclPkgQual of
3844 Nothing -> return ()
39− Just slit -> do
40− atom slit
41− space
42− located ideclName atom
43− case ideclAs of
44− Nothing -> return ()
45− Just l -> do
46− txt " as "
47− located l atom
48− case ideclHiding of
49− Nothing -> return ()
50− Just (hiding, _) ->
51− when hiding $
52− txt " hiding"
53− case ideclHiding of
54− Nothing -> return ()
55− Just (_, l) -> do
56− breakpoint
57− inci . locatedVia Nothing l $
58− parens . velt . withSep comma (located' p_lie)
59−p_hsmodImport (XImportDecl NoExt) = notImplemented "XImportDecl"
45+ Just slit -> atom slit
46+ space
47+ inci $ do
48+ located ideclName atom
49+ when
50+ (isImportDeclQualified ideclQualified && useQualifiedPost)
51+ (space >> txt "qualified")
52+ case ideclAs of
53+ Nothing -> return ()
54+ Just l -> do
55+ space
56+ txt "as"
57+ space
58+ located l atom
59+ space
60+ case ideclHiding of
61+ Nothing -> return ()
62+ Just (hiding, _) ->
63+ when hiding (txt "hiding")
64+ case ideclHiding of
65+ Nothing -> return ()
66+ Just (_, L _ xs) -> do
67+ breakpoint
68+ parens N $ do
69+ layout <- getLayout
70+ sep
71+ breakpoint
72+ (\(p, l) -> sitcc (located l (p_lie layout p)))
73+ (attachRelativePos xs)
74+ newline
75+p_hsmodImport _ (XImportDecl x) = noExtCon x
6076
61−p_lie :: IE GhcPs -> R ()
62−p_lie = \case
63− IEVar NoExt l1 -> located l1 p_ieWrappedName
64− IEThingAbs NoExt l1 -> located l1 p_ieWrappedName
65− IEThingAll NoExt l1 -> do
77+p_lie :: Layout -> RelativePos -> IE GhcPs -> R ()
78+p_lie encLayout relativePos = \case
79+ IEVar NoExtField l1 -> do
80+ located l1 p_ieWrappedName
81+ p_comma
82+ IEThingAbs NoExtField l1 -> do
83+ located l1 p_ieWrappedName
84+ p_comma
85+ IEThingAll NoExtField l1 -> do
6686 located l1 p_ieWrappedName
67− txt " (..)"
68− IEThingWith NoExt l1 w xs _ -> sitcc $ do
87+ space
88+ txt "(..)"
89+ p_comma
90+ IEThingWith NoExtField l1 w xs _ -> sitcc $ do
6991 located l1 p_ieWrappedName
7092 breakpoint
71− -- XXX I have no idea what field labels are in this context.
7293 inci $ do
73− p_ieWildcard w
74− parens . velt $ withSep comma (located' p_ieWrappedName) xs
75− IEModuleContents NoExt l1 -> located l1 p_hsmodName
76− -- XXX I have no idea what these things are for.
77− IEGroup NoExt _ _ -> return ()
78− IEDoc NoExt _ -> return ()
79− IEDocNamed NoExt _ -> return ()
80− XIE NoExt -> notImplemented "XIE"
94+ let names :: [R ()]
95+ names = located' p_ieWrappedName <$> xs
96+ parens N . sep commaDel sitcc $
97+ case w of
98+ NoIEWildcard -> names
99+ IEWildcard n ->
100+ let (before, after) = splitAt n names
101+ in before ++ [txt ".."] ++ after
102+ p_comma
103+ IEModuleContents NoExtField l1 -> do
104+ located l1 p_hsmodName
105+ p_comma
106+ IEGroup NoExtField n str -> do
107+ case relativePos of
108+ SinglePos -> return ()
109+ FirstPos -> return ()
110+ MiddlePos -> newline
111+ LastPos -> newline
112+ p_hsDocString (Asterisk n) False (noLoc str)
113+ IEDoc NoExtField str ->
114+ p_hsDocString Pipe False (noLoc str)
115+ IEDocNamed NoExtField str -> p_hsDocName str
116+ XIE x -> noExtCon x
117+ where
118+ p_comma =
119+ case encLayout of
120+ SingleLine ->
121+ case relativePos of
122+ SinglePos -> return ()
123+ FirstPos -> comma
124+ MiddlePos -> comma
125+ LastPos -> return ()
126+ MultiLine -> comma
src/Ormolu/Printer/Meat/Module.hs+57−55
@@ -1,75 +1,77 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
44
55-- | Rendering of modules.
6−
76module Ormolu.Printer.Meat.Module
8− ( p_hsModule
7+ ( p_hsModule,
98 )
109where
1110
12−import BasicTypes hiding (InlinePragma)
1311import Control.Monad
14−import Data.Maybe (isJust)
15−import Data.Text (Text)
12+import qualified Data.Text as T
1613import GHC
17−import Ormolu.Imports
14+import Ormolu.Imports (normalizeImports)
15+import Ormolu.Parser.CommentStream
16+import Ormolu.Parser.Pragma
17+import Ormolu.Parser.Shebang
1818import Ormolu.Printer.Combinators
1919import Ormolu.Printer.Comments
2020import Ormolu.Printer.Meat.Common
2121import Ormolu.Printer.Meat.Declaration
22+import Ormolu.Printer.Meat.Declaration.Warning
2223import Ormolu.Printer.Meat.ImportExport
23−import Ormolu.Utils
24−import SrcLoc (combineSrcSpans)
25−import qualified Data.List.NonEmpty as NE
24+import Ormolu.Printer.Meat.Pragma
2625
27−p_hsModule :: ParsedSource -> R ()
28−p_hsModule loc@(L moduleSpan hsModule) = do
29− -- NOTE If span of exports in multiline, the whole thing is multiline.
30− -- This is especially important because span of module itself always seems
31− -- to have length zero, so it's not reliable for layout selection.
32− let spn =
33− case hsmodExports hsModule of
34− Nothing -> moduleSpan
35− Just (L exportsSpan _) -> combineSrcSpans moduleSpan exportsSpan
36− locatedVia (Just spn) loc $ \HsModule {..} -> do
26+-- | Render a module.
27+p_hsModule ::
28+ -- | Stack header
29+ Maybe (RealLocated Comment) ->
30+ -- | Shebangs
31+ [Shebang] ->
32+ -- | Pragmas and the associated comments
33+ [([RealLocated Comment], Pragma)] ->
34+ -- | Whether to use postfix qualified imports
35+ Bool ->
36+ -- | AST to print
37+ HsModule GhcPs ->
38+ R ()
39+p_hsModule mstackHeader shebangs pragmas qualifiedPost HsModule {..} = do
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) ->
44+ located x $ \shebang -> do
45+ txt (T.pack shebang)
46+ newline
47+ forM_ mstackHeader $ \(L spn comment) -> do
48+ spitCommentNow spn comment
49+ newline
50+ newline
51+ p_pragmas pragmas
52+ newline
3753 case hsmodName of
38− Nothing -> pure ()
39− Just hsmodName' -> line $ do
40− located hsmodName' p_hsmodName
41− forM_ hsmodDeprecMessage (located' p_warningTxt)
54+ Nothing -> return ()
55+ Just hsmodName' -> do
56+ located hsmodName' $ \name -> do
57+ forM_ hsmodHaddockModHeader (p_hsDocString Pipe True)
58+ p_hsmodName name
59+ breakpoint
60+ forM_ hsmodDeprecMessage $ \w -> do
61+ located' p_moduleWarning w
62+ breakpoint
4263 case hsmodExports of
4364 Nothing -> return ()
44− Just hsmodExports' -> do
65+ Just l -> do
66+ located l $ \exports -> do
67+ inci (p_hsmodExports exports)
4568 breakpoint
46− inci (locatedVia Nothing hsmodExports' p_hsmodExports)
47− breakpoint
4869 txt "where"
49− when (not (null hsmodImports) || not (null hsmodDecls)) newline
50− forM_ (sortImports hsmodImports) (located' p_hsmodImport)
51− when (not (null hsmodImports) && not (null hsmodDecls)) newline
52− p_hsDecls hsmodDecls
53− trailingComments <- hasMoreComments
54− when (trailingComments && isJust hsmodName) newline
55− spitRemainingComments
56−
57−-- | Layout the WARNING\/DEPRECATED pragmas in the module head.
58−
59−p_warningTxt :: WarningTxt -> R ()
60−p_warningTxt = \case
61− WarningTxt _ lits -> p_pragma "WARNING" lits
62− DeprecatedTxt _ lits -> p_pragma "DEPRECATED" lits
63− where
64− p_pragma :: Text -> [Located StringLiteral] -> R ()
65− p_pragma pragmaText lits = switchLayout (litsSpan lits) $ do
66− breakpoint
67− inci $ pragma pragmaText (p_lits lits)
68−
69− litsSpan :: [Located StringLiteral] -> SrcSpan
70− litsSpan lits = combineSrcSpans' (getLoc <$> NE.fromList lits)
71−
72− p_lits :: [Located StringLiteral] -> R ()
73− p_lits = \case
74− [l] -> atom l
75− ls -> brackets . velt $ withSep comma atom ls
70+ newline
71+ newline
72+ forM_ (normalizeImports hsmodImports) (located' (p_hsmodImport qualifiedPost))
73+ newline
74+ switchLayout (getLoc <$> hsmodDecls) $ do
75+ p_hsDecls Free hsmodDecls
76+ newline
77+ spitRemainingComments
src/Ormolu/Printer/Meat/Pragma.hsnew file+91
@@ -0,0 +1,91 @@
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE TupleSections #-}
4+
5+-- | Pretty-printing of language pragmas.
6+module Ormolu.Printer.Meat.Pragma
7+ ( p_pragmas,
8+ )
9+where
10+
11+import Control.Monad
12+import Data.Char (isUpper)
13+import qualified Data.List as L
14+import Data.Maybe (listToMaybe)
15+import qualified Data.Text as T
16+import Ormolu.Parser.CommentStream
17+import Ormolu.Parser.Pragma (Pragma (..))
18+import Ormolu.Printer.Combinators
19+import Ormolu.Printer.Comments
20+import SrcLoc
21+
22+-- | Pragma classification.
23+data PragmaTy
24+ = Language LanguagePragmaClass
25+ | OptionsGHC
26+ | OptionsHaddock
27+ deriving (Eq, Ord)
28+
29+-- | Language pragma classification.
30+--
31+-- The order in which language pragmas are put in the input sometimes
32+-- matters. This is because some language extensions can enable other
33+-- extensions, yet the extensions coming later in the list have the ability
34+-- to change it. So here we classify all extensions by assigning one of the
35+-- four groups to them. Then we only sort inside of the groups.
36+--
37+-- 'Ord' instance of this data type is what affects the sorting.
38+--
39+-- See also: <https://github.com/tweag/ormolu/issues/404>
40+data LanguagePragmaClass
41+ = -- | All other extensions
42+ Normal
43+ | -- | Extensions starting with "No"
44+ Disabling
45+ | -- | Extensions that should go after everything else
46+ Final
47+ deriving (Eq, Ord)
48+
49+-- | Print a collection of 'Pragma's with their associated comments.
50+p_pragmas :: [([RealLocated Comment], Pragma)] -> R ()
51+p_pragmas ps = do
52+ let prepare = L.sortOn snd . L.nub . concatMap analyze
53+ analyze = \case
54+ (cs, PragmaLanguage xs) ->
55+ let f x = (cs, (Language (classifyLanguagePragma x), x))
56+ in f <$> xs
57+ (cs, PragmaOptionsGHC x) -> [(cs, (OptionsGHC, x))]
58+ (cs, PragmaOptionsHaddock x) -> [(cs, (OptionsHaddock, x))]
59+ forM_ (prepare ps) $ \(cs, (pragmaTy, x)) ->
60+ p_pragma cs pragmaTy x
61+
62+p_pragma :: [RealLocated Comment] -> PragmaTy -> String -> R ()
63+p_pragma comments ty x = do
64+ forM_ comments $ \(L l comment) -> do
65+ spitCommentNow l comment
66+ newline
67+ txt "{-# "
68+ txt $ case ty of
69+ Language _ -> "LANGUAGE"
70+ OptionsGHC -> "OPTIONS_GHC"
71+ OptionsHaddock -> "OPTIONS_HADDOCK"
72+ space
73+ txt (T.pack x)
74+ txt " #-}"
75+ newline
76+
77+-- | Classify a 'LanguagePragma'.
78+classifyLanguagePragma :: String -> LanguagePragmaClass
79+classifyLanguagePragma = \case
80+ "ImplicitPrelude" -> Final
81+ "CUSKs" -> Final
82+ str ->
83+ case splitAt 2 str of
84+ ("No", rest) ->
85+ case listToMaybe rest of
86+ Nothing -> Normal
87+ Just x ->
88+ if isUpper x
89+ then Disabling
90+ else Normal
91+ _ -> Normal
src/Ormolu/Printer/Meat/Type.hs+213−93
@@ -1,155 +1,275 @@
1−{-# LANGUAGE LambdaCase #-}
1+{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
3+{-# LANGUAGE RecordWildCards #-}
44
55-- | Rendering of types.
6−
76module Ormolu.Printer.Meat.Type
8− ( p_hsType
9− , p_hsContext
10− , p_hsTyVarBndr
11− , p_conDeclFields
12− , tyVarsToTypes
7+ ( p_hsType,
8+ p_hsTypePostDoc,
9+ hasDocStrings,
10+ p_hsContext,
11+ p_hsTyVarBndr,
12+ p_forallBndrs,
13+ p_conDeclFields,
14+ tyVarsToTypes,
1315 )
1416where
1517
16−import GHC
18+import Data.Data (Data)
19+import GHC hiding (isPromoted)
1720import Ormolu.Printer.Combinators
1821import Ormolu.Printer.Meat.Common
22+import {-# SOURCE #-} Ormolu.Printer.Meat.Declaration.Value (p_hsSplice, p_stringLit)
23+import Ormolu.Printer.Operators
1924import Ormolu.Utils
2025
2126p_hsType :: HsType GhcPs -> R ()
22−p_hsType = \case
23− HsForAllTy NoExt bndrs t -> do
24− txt "forall "
25− spaceSep (located' p_hsTyVarBndr) bndrs
26− txt ". "
27− locatedVia Nothing t p_hsType
28− HsQualTy NoExt qs t -> do
27+p_hsType t = p_hsType' (hasDocStrings t) PipeStyle t
28+
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
41+ interArgBreak
42+ p_hsTypeR (unLoc t)
43+ HsQualTy NoExtField qs t -> do
2944 located qs p_hsContext
30− breakpoint
31− txt "=> "
32− locatedVia Nothing t p_hsType
33− HsTyVar NoExt p n -> do
45+ space
46+ txt "=>"
47+ interArgBreak
48+ case unLoc t of
49+ HsQualTy {} -> p_hsTypeR (unLoc t)
50+ HsFunTy {} -> p_hsTypeR (unLoc t)
51+ _ -> located t p_hsTypeR
52+ HsTyVar NoExtField p n -> do
3453 case p of
35− Promoted -> txt "'"
54+ IsPromoted -> do
55+ txt "'"
56+ case showOutputable (unLoc n) of
57+ _ : '\'' : _ -> space
58+ _ -> return ()
3659 NotPromoted -> return ()
3760 p_rdrName n
38− HsAppTy NoExt f x -> sitcc $ do
39− located f p_hsType
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
75+ HsAppKindTy _ ty kd -> sitcc $ do
76+ -- The first argument is the location of the "@..." part. Not 100% sure,
77+ -- but I think we can ignore it as long as we use 'located' on both the
78+ -- type and the kind.
79+ located ty p_hsType
4080 breakpoint
41− inci (located x p_hsType)
42− HsFunTy NoExt x y@(L _ y') -> do
81+ inci $ do
82+ txt "@"
83+ located kd p_hsType
84+ HsFunTy NoExtField x y@(L _ y') -> do
4385 located x p_hsType
44− breakpoint
45− txt "-> "
86+ space
87+ txt "->"
88+ interArgBreak
4689 case y' of
47− HsFunTy{} -> p_hsType y'
48− _ -> located y p_hsType
49− HsListTy NoExt t -> located t (brackets . p_hsType)
50− HsTupleTy NoExt tsort xs ->
90+ HsFunTy {} -> p_hsTypeR y'
91+ _ -> located y p_hsTypeR
92+ HsListTy NoExtField t ->
93+ located t (brackets N . p_hsType)
94+ HsTupleTy NoExtField tsort xs ->
5195 let parens' =
5296 case tsort of
53− HsUnboxedTuple -> parensHash
54− HsBoxedTuple -> parens
55− HsConstraintTuple -> parens
56− HsBoxedOrConstraintTuple -> parens
57− in parens' . velt $ withSep comma (located' p_hsType) xs
58− HsSumTy NoExt xs ->
59− parensHash . velt $ withSep (txt "| ") (located' p_hsType) xs
60− HsOpTy NoExt x op y -> do
61− located x p_hsType
62− breakpoint
63− inci $ do
64− p_rdrName op
65− space
66− located y p_hsType
67− HsParTy NoExt t ->
68− parens (located t p_hsType)
69− HsIParamTy NoExt n t -> do
97+ HsUnboxedTuple -> parensHash N
98+ HsBoxedTuple -> parens N
99+ HsConstraintTuple -> parens N
100+ HsBoxedOrConstraintTuple -> parens N
101+ in parens' $ sep commaDel (sitcc . located' p_hsType) xs
102+ HsSumTy NoExtField xs ->
103+ parensHash N $
104+ sep (txt "|" >> breakpoint) (sitcc . located' p_hsType) xs
105+ HsOpTy NoExtField x op y ->
106+ sitcc $
107+ let opTree = OpBranch (tyOpTree x) op (tyOpTree y)
108+ in p_tyOpTree (reassociateOpTree Just opTree)
109+ HsParTy NoExtField t ->
110+ parens N (located t p_hsType)
111+ HsIParamTy NoExtField n t -> sitcc $ do
70112 located n atom
113+ space
114+ txt "::"
71115 breakpoint
72− inci $ do
73− txt ":: "
74− located t p_hsType
75− HsStarTy NoExt _ -> txt "*"
76− HsKindSig NoExt t k -> do
116+ inci (located t p_hsType)
117+ HsStarTy NoExtField _ -> txt "*"
118+ HsKindSig NoExtField t k -> sitcc $ do
77119 located t p_hsType
78− inci $ do
79− txt ":: "
80− located k p_hsType
81− HsSpliceTy _ _ -> error "HsSpliceTy"
82− HsDocTy NoExt _ _ -> error "HsDocTy"
83− HsBangTy NoExt (HsSrcBang _ u s) t -> do
120+ space
121+ txt "::"
122+ breakpoint
123+ inci (located k p_hsType)
124+ HsSpliceTy NoExtField splice -> p_hsSplice splice
125+ HsDocTy NoExtField t str ->
126+ case docStyle of
127+ PipeStyle -> do
128+ p_hsDocString Pipe True str
129+ located t p_hsType
130+ CaretStyle -> do
131+ located t p_hsType
132+ newline
133+ p_hsDocString Caret False str
134+ HsBangTy NoExtField (HsSrcBang _ u s) t -> do
84135 case u of
85− SrcUnpack -> txt "{-# UNPACK #-} "
86− SrcNoUnpack -> txt "{-# NOUNPACK #-} "
136+ SrcUnpack -> txt "{-# UNPACK #-}" >> space
137+ SrcNoUnpack -> txt "{-# NOUNPACK #-}" >> space
87138 NoSrcUnpack -> return ()
88139 case s of
89140 SrcLazy -> txt "~"
90141 SrcStrict -> txt "!"
91142 NoSrcStrict -> return ()
92143 located t p_hsType
93− HsRecTy NoExt fields ->
144+ HsRecTy NoExtField fields ->
94145 p_conDeclFields fields
95− HsExplicitListTy NoExt p xs -> do
146+ HsExplicitListTy NoExtField p xs -> do
96147 case p of
97− Promoted -> txt "'"
148+ IsPromoted -> txt "'"
98149 NotPromoted -> return ()
99− brackets . velt $ withSep comma (located' p_hsType) xs
100− HsExplicitTupleTy NoExt xs -> do
150+ brackets N $ do
151+ -- If both this list itself and the first element is promoted,
152+ -- we need to put a space in between or it fails to parse.
153+ case (p, xs) of
154+ (IsPromoted, L _ t : _) | isPromoted t -> space
155+ _ -> return ()
156+ sep commaDel (sitcc . located' p_hsType) xs
157+ HsExplicitTupleTy NoExtField xs -> do
101158 txt "'"
102− parens . velt $ withSep comma (located' p_hsType) xs
103− HsTyLit NoExt t -> atom t
104− HsWildCardTy NoExt -> txt "_"
159+ parens N $ do
160+ case xs of
161+ L _ t : _ | isPromoted t -> space
162+ _ -> return ()
163+ sep commaDel (located' p_hsType) xs
164+ HsTyLit NoExtField t ->
165+ case t of
166+ HsStrTy (SourceText s) _ -> p_stringLit s
167+ a -> atom a
168+ HsWildCardTy NoExtField -> txt "_"
105169 XHsType (NHsCoreTy t) -> atom t
170+ where
171+ isPromoted = \case
172+ HsTyVar _ IsPromoted _ -> True
173+ HsExplicitTupleTy {} -> True
174+ HsExplicitListTy {} -> True
175+ _ -> False
176+ interArgBreak =
177+ if multilineArgs
178+ then newline
179+ else breakpoint
180+ p_hsTypeR = p_hsType' multilineArgs docStyle
181+
182+-- | Return 'True' if at least one argument in 'HsType' has a doc string
183+-- attached to it.
184+hasDocStrings :: HsType GhcPs -> Bool
185+hasDocStrings = \case
186+ HsDocTy {} -> True
187+ HsFunTy _ (L _ x) (L _ y) -> hasDocStrings x || hasDocStrings y
188+ _ -> False
106189
107190p_hsContext :: HsContext GhcPs -> R ()
108191p_hsContext = \case
109192 [] -> txt "()"
110193 [x] -> located x p_hsType
111− xs -> parens . velt $ withSep comma (located' p_hsType) xs
194+ xs -> parens N $ sep commaDel (sitcc . located' p_hsType) xs
112195
113196p_hsTyVarBndr :: HsTyVarBndr GhcPs -> R ()
114197p_hsTyVarBndr = \case
115− UserTyVar NoExt x ->
198+ UserTyVar NoExtField x ->
116199 p_rdrName x
117− KindedTyVar NoExt l k -> parens $ do
200+ KindedTyVar NoExtField l k -> parens N $ do
118201 located l atom
202+ space
203+ txt "::"
204+ breakpoint
205+ inci (located k p_hsType)
206+ XTyVarBndr x -> noExtCon x
207+
208+-- | Render several @forall@-ed variables.
209+p_forallBndrs :: Data a => ForallVisFlag -> (a -> R ()) -> [Located a] -> R ()
210+p_forallBndrs ForallInvis _ [] = txt "forall."
211+p_forallBndrs ForallVis _ [] = txt "forall ->"
212+p_forallBndrs vis p tyvars =
213+ switchLayout (getLoc <$> tyvars) $ do
214+ txt "forall"
119215 breakpoint
120216 inci $ do
121− txt ":: "
122− located k p_hsType
123− XTyVarBndr NoExt -> notImplemented "XTyVarBndr"
217+ sitcc $ sep breakpoint (sitcc . located' p) tyvars
218+ case vis of
219+ ForallInvis -> txt "."
220+ ForallVis -> space >> txt "->"
124221
125222p_conDeclFields :: [LConDeclField GhcPs] -> R ()
126−p_conDeclFields =
127− braces . velt . withSep comma (sitcc . located' p_conDeclField)
223+p_conDeclFields xs =
224+ braces N $ sep commaDel (sitcc . located' p_conDeclField) xs
128225
129226p_conDeclField :: ConDeclField GhcPs -> R ()
130227p_conDeclField ConDeclField {..} = do
131− sitcc . velt $ withSep
132− comma
133− (located' (p_rdrName . rdrNameFieldOcc))
134− cd_fld_names
228+ mapM_ (p_hsDocString Pipe True) cd_fld_doc
229+ sitcc $
230+ sep
231+ commaDel
232+ (located' (p_rdrName . rdrNameFieldOcc))
233+ cd_fld_names
234+ space
235+ txt "::"
236+ breakpoint
237+ sitcc . inci $ p_hsType (unLoc cd_fld_type)
238+p_conDeclField (XConDeclField x) = noExtCon x
239+
240+tyOpTree :: LHsType GhcPs -> OpTree (LHsType GhcPs) (Located RdrName)
241+tyOpTree (L _ (HsOpTy NoExtField l op r)) =
242+ OpBranch (tyOpTree l) op (tyOpTree r)
243+tyOpTree n = OpNode n
244+
245+p_tyOpTree :: OpTree (LHsType GhcPs) (Located RdrName) -> R ()
246+p_tyOpTree (OpNode n) = located n p_hsType
247+p_tyOpTree (OpBranch l op r) = do
248+ switchLayout [opTreeLoc l] $
249+ p_tyOpTree l
135250 breakpoint
136− sitcc . inci $ do
137− txt ":: "
138− locatedVia Nothing cd_fld_type p_hsType
139−p_conDeclField (XConDeclField NoExt) = notImplemented "XConDeclField"
251+ inci . switchLayout [opTreeLoc r] $ do
252+ p_rdrName op
253+ space
254+ p_tyOpTree r
140255
141256----------------------------------------------------------------------------
142−-- Convertion functions
257+-- Conversion functions
143258
144259tyVarsToTypes :: LHsQTyVars GhcPs -> [LHsType GhcPs]
145260tyVarsToTypes = \case
146− HsQTvs {..} -> fmap tyVarToType <$> hsq_explicit
147− XLHsQTyVars {} -> notImplemented "XLHsQTyVars"
261+ HsQTvs {..} -> fmap tyVarToType <$> hsq_explicit
262+ XLHsQTyVars x -> noExtCon x
148263
149264tyVarToType :: HsTyVarBndr GhcPs -> HsType GhcPs
150265tyVarToType = \case
151− UserTyVar NoExt tvar -> HsTyVar NoExt NotPromoted tvar
152− KindedTyVar NoExt tvar kind ->
153− HsParTy NoExt $ noLoc $
154− HsKindSig NoExt (noLoc (HsTyVar NoExt NotPromoted tvar)) kind
155− XTyVarBndr {} -> notImplemented "XTyVarBndr"
266+ UserTyVar NoExtField tvar -> HsTyVar NoExtField NotPromoted tvar
267+ KindedTyVar NoExtField tvar kind ->
268+ -- Note: we always add parentheses because for whatever reason GHC does
269+ -- not use HsParTy for left-hand sides of declarations. Please see
270+ -- <https://gitlab.haskell.org/ghc/ghc/issues/17404>. This is fine as
271+ -- long as 'tyVarToType' does not get applied to right-hand sides of
272+ -- declarations.
273+ HsParTy NoExtField . noLoc $
274+ HsKindSig NoExtField (noLoc (HsTyVar NoExtField NotPromoted tvar)) kind
275+ XTyVarBndr x -> noExtCon x
src/Ormolu/Printer/Operators.hsnew file+177
@@ -0,0 +1,177 @@
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE ScopedTypeVariables #-}
3+
4+-- | This module helps handle operator chains composed of different
5+-- operators that may have different precedence and fixities.
6+module Ormolu.Printer.Operators
7+ ( OpTree (..),
8+ opTreeLoc,
9+ reassociateOpTree,
10+ )
11+where
12+
13+import Data.Function (on)
14+import qualified Data.List as L
15+import Data.Map.Strict (Map)
16+import qualified Data.Map.Strict as M
17+import Data.Maybe (fromMaybe, mapMaybe)
18+import GHC
19+import OccName (occNameString)
20+import Ormolu.Utils (unSrcSpan)
21+
22+-- | Intermediate representation of operator trees. It has two type
23+-- parameters: @ty@ is the type of sub-expressions, while @op@ is the type
24+-- of operators.
25+data OpTree ty op
26+ = OpNode ty
27+ | OpBranch
28+ (OpTree ty op)
29+ op
30+ (OpTree ty op)
31+
32+-- | Return combined 'SrcSpan's of all elements in this 'OpTree'.
33+opTreeLoc :: OpTree (Located a) b -> SrcSpan
34+opTreeLoc (OpNode (L l _)) = l
35+opTreeLoc (OpBranch l _ r) = combineSrcSpans (opTreeLoc l) (opTreeLoc r)
36+
37+-- | Re-associate an 'OpTree' taking into account automagically inferred
38+-- relative precedence of operators. Users are expected to first construct
39+-- an initial 'OpTree', then re-associate it using this function before
40+-- printing.
41+reassociateOpTree ::
42+ -- | How to get name of an operator
43+ (op -> Maybe RdrName) ->
44+ -- | Original 'OpTree'
45+ OpTree (Located ty) (Located op) ->
46+ -- | Re-associated 'OpTree'
47+ OpTree (Located ty) (Located op)
48+reassociateOpTree getOpName opTree =
49+ reassociateOpTreeWith
50+ (buildFixityMap getOpName normOpTree)
51+ (getOpName . unLoc)
52+ normOpTree
53+ where
54+ normOpTree = normalizeOpTree opTree
55+
56+-- | Re-associate an 'OpTree' given the map with operator fixities.
57+reassociateOpTreeWith ::
58+ forall ty op.
59+ -- | Fixity map for operators
60+ Map String Fixity ->
61+ -- | How to get the name of an operator
62+ (op -> Maybe RdrName) ->
63+ -- | Original 'OpTree'
64+ OpTree ty op ->
65+ -- | Re-associated 'OpTree'
66+ OpTree ty op
67+reassociateOpTreeWith fixityMap getOpName = go
68+ where
69+ fixityOf :: op -> Fixity
70+ fixityOf op = fromMaybe defaultFixity $ do
71+ s <- occNameString . rdrNameOcc <$> getOpName op
72+ M.lookup s fixityMap
73+ -- Here, left branch is already associated and the root alongside with
74+ -- the right branch is right-associated. This function picks up one item
75+ -- from the right and inserts it correctly to the left.
76+ --
77+ -- Also, we are using the 'compareFixity' function which tells if the
78+ -- expression should associate to right.
79+ go :: OpTree ty op -> OpTree ty op
80+ -- base cases
81+ go t@(OpNode _) = t
82+ go t@(OpBranch (OpNode _) _ (OpNode _)) = t
83+ -- shift one operator to the left at the beginning
84+ go (OpBranch l@(OpNode _) op (OpBranch l' op' r')) =
85+ go (OpBranch (OpBranch l op l') op' r')
86+ -- at the last operator, place the operator and don't recurse
87+ go (OpBranch (OpBranch l op r) op' r'@(OpNode _)) =
88+ if snd $ compareFixity (fixityOf op) (fixityOf op')
89+ then OpBranch l op (go $ OpBranch r op' r')
90+ else OpBranch (OpBranch l op r) op' r'
91+ -- else, shift one operator to left and recurse.
92+ go (OpBranch (OpBranch l op r) op' (OpBranch l' op'' r')) =
93+ if snd $ compareFixity (fixityOf op) (fixityOf op')
94+ then go $ OpBranch (OpBranch l op (go $ OpBranch r op' l')) op'' r'
95+ else go $ OpBranch (OpBranch (OpBranch l op r) op' l') op'' r'
96+
97+-- | A score assigned to an operator.
98+data Score
99+ = -- | The operator was placed at the beginning of a line
100+ AtBeginning Int
101+ | -- | The operator was placed at the end of a line
102+ AtEnd
103+ | -- | The operator was placed in between arguments on a single line
104+ InBetween
105+ deriving (Eq, Ord)
106+
107+-- | Build a map of inferred 'Fixity's from an 'OpTree'.
108+buildFixityMap ::
109+ forall ty op.
110+ -- | How to get the name of an operator
111+ (op -> Maybe RdrName) ->
112+ -- | Operator tree
113+ OpTree (Located ty) (Located op) ->
114+ -- | Fixity map
115+ Map String Fixity
116+buildFixityMap getOpName opTree =
117+ addOverrides
118+ . M.fromList
119+ . concatMap (\(i, ns) -> map (\(n, _) -> (n, fixity i InfixL)) ns)
120+ . zip [2 ..]
121+ . L.groupBy ((==) `on` snd)
122+ . selectScores
123+ $ score opTree
124+ where
125+ addOverrides :: Map String Fixity -> Map String Fixity
126+ addOverrides m =
127+ M.fromList
128+ [ ("$", fixity 0 InfixR),
129+ (":", fixity 1 InfixR),
130+ (".", fixity 100 InfixL)
131+ ]
132+ `M.union` m
133+ fixity = Fixity NoSourceText
134+ score :: OpTree (Located ty) (Located op) -> [(String, Score)]
135+ score (OpNode _) = []
136+ score (OpBranch l o r) = fromMaybe (score r) $ do
137+ -- If we fail to get any of these, 'defaultFixity' will be used by
138+ -- 'reassociateOpTreeWith'.
139+ le <- srcSpanEndLine <$> unSrcSpan (opTreeLoc l) -- left end
140+ ob <- srcSpanStartLine <$> unSrcSpan (getLoc o) -- operator begin
141+ oe <- srcSpanEndLine <$> unSrcSpan (getLoc o) -- operator end
142+ rb <- srcSpanStartLine <$> unSrcSpan (opTreeLoc r) -- right begin
143+ oc <- srcSpanStartCol <$> unSrcSpan (getLoc o) -- operator column
144+ opName <- occNameString . rdrNameOcc <$> getOpName (unLoc o)
145+ let s
146+ | le < ob = AtBeginning oc
147+ | oe < rb = AtEnd
148+ | otherwise = InBetween
149+ return $ (opName, s) : score r
150+ selectScores :: [(String, Score)] -> [(String, Score)]
151+ selectScores =
152+ L.sortOn snd
153+ . mapMaybe
154+ ( \case
155+ [] -> Nothing
156+ xs@((n, _) : _) -> Just (n, selectScore $ map snd xs)
157+ )
158+ . L.groupBy ((==) `on` fst)
159+ . L.sort
160+ selectScore :: [Score] -> Score
161+ selectScore xs =
162+ case filter (/= InBetween) xs of
163+ [] -> InBetween
164+ xs' -> maximum xs'
165+
166+----------------------------------------------------------------------------
167+-- Helpers
168+
169+-- | Convert an 'OpTree' to with all operators having the same fixity and
170+-- associativity (left infix).
171+normalizeOpTree :: OpTree ty op -> OpTree ty op
172+normalizeOpTree (OpNode n) =
173+ OpNode n
174+normalizeOpTree (OpBranch (OpNode l) lop r) =
175+ OpBranch (OpNode l) lop (normalizeOpTree r)
176+normalizeOpTree (OpBranch (OpBranch l' lop' r') lop r) =
177+ normalizeOpTree (OpBranch l' lop' (OpBranch r' lop r))
src/Ormolu/SpanStream.hs → src/Ormolu/Printer/SpanStream.hsrenamed+19−21
@@ -1,46 +1,44 @@
1−{-# LANGUAGE DeriveDataTypeable #-}
1+{-# LANGUAGE DeriveDataTypeable #-}
22{-# LANGUAGE GeneralizedNewtypeDeriving #-}
33
44-- | Build span stream from AST.
5−
6−module Ormolu.SpanStream
7− ( SpanStream (..)
8− , mkSpanStream
5+module Ormolu.Printer.SpanStream
6+ ( SpanStream (..),
7+ mkSpanStream,
98 )
109where
1110
1211import Data.DList (DList)
12+import qualified Data.DList as D
1313import Data.Data (Data)
1414import Data.Generics (everything, ext2Q)
1515import Data.List (sortOn)
1616import Data.Typeable (cast)
1717import SrcLoc
18−import qualified Data.DList as D
1918
2019-- | A stream of 'RealSrcSpan's in ascending order. This allows us to tell
2120-- e.g. whether there is another \"located\" element of AST between current
2221-- element and comment we're considering for printing.
23−
2422newtype SpanStream = SpanStream [RealSrcSpan]
2523 deriving (Eq, Show, Data, Semigroup, Monoid)
2624
2725-- | Create 'SpanStream' from a data structure containing \"located\"
2826-- elements.
29−
30−mkSpanStream
31− :: Data a
32− => a -- ^ Data structure to inspect (AST)
33− -> SpanStream
34−mkSpanStream a
35− = SpanStream
36− . sortOn realSrcSpanStart
37− . D.toList
38− $ everything mappend (const mempty `ext2Q` queryLocated) a
27+mkSpanStream ::
28+ Data a =>
29+ -- | Data structure to inspect (AST)
30+ a ->
31+ SpanStream
32+mkSpanStream a =
33+ SpanStream
34+ . sortOn realSrcSpanStart
35+ . D.toList
36+ $ everything mappend (const mempty `ext2Q` queryLocated) a
3937 where
40− queryLocated
41− :: (Data e0, Data e1)
42− => GenLocated e0 e1
43− -> DList RealSrcSpan
38+ queryLocated ::
39+ (Data e0) =>
40+ GenLocated e0 e1 ->
41+ DList RealSrcSpan
4442 queryLocated (L mspn _) =
4543 case cast mspn :: Maybe SrcSpan of
4644 Nothing -> mempty
src/Ormolu/Processing/Common.hsnew file+27
@@ -0,0 +1,27 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+
3+-- | Common definitions for pre- and post- processing.
4+module Ormolu.Processing.Common
5+ ( OrmoluState (..),
6+ startDisabling,
7+ endDisabling,
8+ )
9+where
10+
11+import Data.String (IsString (..))
12+
13+-- | Ormolu state.
14+data OrmoluState
15+ = -- | Enabled
16+ OrmoluEnabled
17+ | -- | Disabled
18+ OrmoluDisabled
19+ deriving (Eq, Show)
20+
21+-- | Marker for the beginning of the region where Ormolu should be disabled.
22+startDisabling :: IsString s => s
23+startDisabling = "{- ORMOLU_DISABLE_START"
24+
25+-- | Marker for the end of the region where Ormolu should be disabled.
26+endDisabling :: IsString s => s
27+endDisabling = "ORMOLU_DISABLE_END -}"
src/Ormolu/Processing/Cpp.hsnew file+70
@@ -0,0 +1,70 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+
3+-- | Support for CPP.
4+module Ormolu.Processing.Cpp
5+ ( State (..),
6+ processLine,
7+ unmaskLine,
8+ )
9+where
10+
11+import Control.Monad
12+import Data.Char (isSpace)
13+import qualified Data.List as L
14+import Data.Maybe (isJust)
15+import Data.String
16+import Data.Text (Text)
17+import qualified Data.Text as T
18+
19+-- | State of the CPP processor.
20+data State
21+ = -- | Outside of CPP directives
22+ Outside
23+ | -- | In a conditional expression
24+ InConditional
25+ | -- | In a continuation (after @\\@)
26+ InContinuation
27+ deriving (Eq, Show)
28+
29+-- | Automatically mask the line when needed and update the 'State'.
30+processLine :: String -> State -> (String, State)
31+processLine line state
32+ | for "define " = (masked, state')
33+ | for "include " = (masked, state')
34+ | for "undef " = (masked, state')
35+ | for "ifdef " = (masked, InConditional)
36+ | for "ifndef " = (masked, InConditional)
37+ | for "if " = (masked, InConditional)
38+ | for "else" = (masked, InConditional)
39+ | for "elif" = (masked, InConditional)
40+ | for "endif" = (masked, state')
41+ | otherwise =
42+ case state of
43+ Outside -> (line, Outside)
44+ InConditional -> (masked, InConditional)
45+ InContinuation -> (masked, state')
46+ where
47+ for directive = isJust $ do
48+ s <- dropWhile isSpace <$> L.stripPrefix "#" line
49+ void (L.stripPrefix directive s)
50+ masked = maskLine line
51+ state' =
52+ if "\\" `L.isSuffixOf` line
53+ then InContinuation
54+ else Outside
55+
56+-- | Mask the given line.
57+maskLine :: String -> String
58+maskLine x = maskPrefix ++ x
59+
60+-- | If the given line is masked, unmask it. Otherwise return the line
61+-- unchanged.
62+unmaskLine :: Text -> Text
63+unmaskLine x =
64+ case T.stripPrefix maskPrefix (T.stripStart x) of
65+ Nothing -> x
66+ Just x' -> x'
67+
68+-- | Mask prefix for CPP.
69+maskPrefix :: IsString s => s
70+maskPrefix = "-- ORMOLU_CPP_MASK"
src/Ormolu/Processing/Postprocess.hsnew file+31
@@ -0,0 +1,31 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+{-# LANGUAGE ViewPatterns #-}
3+
4+-- | Postprocessing for the results of printing.
5+module Ormolu.Processing.Postprocess
6+ ( postprocess,
7+ )
8+where
9+
10+import Data.Text (Text)
11+import qualified Data.Text as T
12+import Ormolu.Processing.Common
13+import qualified Ormolu.Processing.Cpp as Cpp
14+
15+-- | Postprocess output of the formatter.
16+postprocess ::
17+ -- | Desired indentation level
18+ Int ->
19+ -- | Input to process
20+ Text ->
21+ Text
22+postprocess indent =
23+ T.unlines
24+ . fmap indentLine
25+ . fmap Cpp.unmaskLine
26+ . filter (not . magicComment)
27+ . T.lines
28+ where
29+ magicComment (T.stripStart -> x) =
30+ x == startDisabling || x == endDisabling
31+ indentLine x = T.replicate indent " " <> x
src/Ormolu/Processing/Preprocess.hsnew file+149
@@ -0,0 +1,149 @@
1+{-# LANGUAGE BangPatterns #-}
2+{-# LANGUAGE LambdaCase #-}
3+{-# LANGUAGE RecordWildCards #-}
4+
5+-- | Preprocessing for input source code.
6+module Ormolu.Processing.Preprocess
7+ ( preprocess,
8+ )
9+where
10+
11+import Control.Monad
12+import Data.Char (isSpace)
13+import qualified Data.List as L
14+import Data.Maybe (isJust, maybeToList)
15+import FastString
16+import Ormolu.Config (RegionDeltas (..))
17+import Ormolu.Parser.Shebang (isShebang)
18+import Ormolu.Processing.Common
19+import qualified Ormolu.Processing.Cpp as Cpp
20+import SrcLoc
21+
22+-- | Transform given input possibly returning comments extracted from it.
23+-- This handles LINE pragmas, CPP, shebangs, and the magic comments for
24+-- enabling\/disabling of Ormolu.
25+preprocess ::
26+ -- | File name, just to use in the spans
27+ FilePath ->
28+ -- | Input to process
29+ String ->
30+ -- | Region deltas
31+ RegionDeltas ->
32+ -- | Literal prefix, pre-processed input, literal suffix, extra comments
33+ (String, String, String, [Located String])
34+preprocess path input RegionDeltas {..} =
35+ go 1 OrmoluEnabled Cpp.Outside id id regionLines
36+ where
37+ (prefixLines, otherLines) = splitAt regionPrefixLength (lines input)
38+ (regionLines, suffixLines) =
39+ let regionLength = length otherLines - regionSuffixLength
40+ in splitAt regionLength otherLines
41+ go !n ormoluState cppState inputSoFar csSoFar = \case
42+ [] ->
43+ let input' = unlines (inputSoFar [])
44+ in ( unlines prefixLines,
45+ case ormoluState of
46+ OrmoluEnabled -> input'
47+ OrmoluDisabled -> input' ++ endDisabling,
48+ unlines suffixLines,
49+ csSoFar []
50+ )
51+ (x : xs) ->
52+ let (x', ormoluState', cppState', cs) =
53+ processLine path n ormoluState cppState x
54+ in go
55+ (n + 1)
56+ ormoluState'
57+ cppState'
58+ (inputSoFar . (x' :))
59+ (csSoFar . (maybeToList cs ++))
60+ xs
61+
62+-- | Transform a given line possibly returning a comment extracted from it.
63+processLine ::
64+ -- | File name, just to use in the spans
65+ FilePath ->
66+ -- | Line number of this line
67+ Int ->
68+ -- | Whether Ormolu is currently enabled
69+ OrmoluState ->
70+ -- | CPP state
71+ Cpp.State ->
72+ -- | The actual line
73+ String ->
74+ -- | Adjusted line and possibly a comment extracted from it
75+ (String, OrmoluState, Cpp.State, Maybe (Located String))
76+processLine path n ormoluState Cpp.Outside line
77+ | "{-# LINE" `L.isPrefixOf` line =
78+ let (pragma, res) = getPragma line
79+ size = length pragma
80+ ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (size + 1))
81+ in (res, ormoluState, Cpp.Outside, Just (L ss pragma))
82+ | isOrmoluEnable line =
83+ case ormoluState of
84+ OrmoluEnabled ->
85+ (enableMarker, OrmoluEnabled, Cpp.Outside, Nothing)
86+ OrmoluDisabled ->
87+ (endDisabling ++ enableMarker, OrmoluEnabled, Cpp.Outside, Nothing)
88+ | isOrmoluDisable line =
89+ case ormoluState of
90+ OrmoluEnabled ->
91+ (disableMarker ++ startDisabling, OrmoluDisabled, Cpp.Outside, Nothing)
92+ OrmoluDisabled ->
93+ (disableMarker, OrmoluDisabled, Cpp.Outside, Nothing)
94+ | isShebang line =
95+ let ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (length line))
96+ in ("", ormoluState, Cpp.Outside, Just (L ss line))
97+ | otherwise =
98+ let (line', cppState') = Cpp.processLine line Cpp.Outside
99+ in (line', ormoluState, cppState', Nothing)
100+ where
101+ mkSrcLoc' = mkSrcLoc (mkFastString path) n
102+processLine _ _ ormoluState cppState line =
103+ let (line', cppState') = Cpp.processLine line cppState
104+ in (line', ormoluState, cppState', Nothing)
105+
106+-- | Take a line pragma and output its replacement (where line pragma is
107+-- replaced with spaces) and the contents of the pragma itself.
108+getPragma ::
109+ -- | Pragma line to analyze
110+ String ->
111+ -- | Contents of the pragma and its replacement line
112+ (String, String)
113+getPragma [] = error "Ormolu.Preprocess.getPragma: input must not be empty"
114+getPragma s@(x : xs)
115+ | "#-}" `L.isPrefixOf` s = ("#-}", " " ++ drop 3 s)
116+ | otherwise =
117+ let (prag, remline) = getPragma xs
118+ in (x : prag, ' ' : remline)
119+
120+-- | Canonical enable marker.
121+enableMarker :: String
122+enableMarker = "{- ORMOLU_ENABLE -}"
123+
124+-- | Canonical disable marker.
125+disableMarker :: String
126+disableMarker = "{- ORMOLU_DISABLE -}"
127+
128+-- | Return 'True' if the given string is an enabling marker.
129+isOrmoluEnable :: String -> Bool
130+isOrmoluEnable = magicComment "ORMOLU_ENABLE"
131+
132+-- | Return 'True' if the given string is a disabling marker.
133+isOrmoluDisable :: String -> Bool
134+isOrmoluDisable = magicComment "ORMOLU_DISABLE"
135+
136+-- | Construct a function for whitespace-insensitive matching of string.
137+magicComment ::
138+ -- | What to expect
139+ String ->
140+ -- | String to test
141+ String ->
142+ -- | Whether or not the two strings watch
143+ Bool
144+magicComment expected s0 = isJust $ do
145+ let trim = dropWhile isSpace
146+ s1 <- trim <$> L.stripPrefix "{-" (trim s0)
147+ s2 <- trim <$> L.stripPrefix expected s1
148+ s3 <- L.stripPrefix "-}" s2
149+ guard (all isSpace s3)
src/Ormolu/Utils.hs+142−14
@@ -1,27 +1,155 @@
1−-- | Random utilities used by the code.
1+{-# LANGUAGE LambdaCase #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE ViewPatterns #-}
24
5+-- | Random utilities used by the code.
36module Ormolu.Utils
4− ( combineSrcSpans'
5− , isModule
6− , notImplemented
7+ ( RelativePos (..),
8+ attachRelativePos,
9+ combineSrcSpans',
10+ notImplemented,
11+ showOutputable,
12+ splitDocString,
13+ typeArgToType,
14+ unSrcSpan,
15+ incSpanLine,
16+ separatedByBlank,
17+ separatedByBlankNE,
18+ onTheSameLine,
19+ removeIndentation,
720 )
821where
922
10−import Data.Data (Data, showConstr, toConstr)
23+import Data.Char (isSpace)
24+import Data.List (dropWhileEnd)
1125import Data.List.NonEmpty (NonEmpty (..))
12−import SrcLoc
26+import qualified Data.List.NonEmpty as NE
27+import Data.Maybe (fromMaybe)
28+import Data.Text (Text)
29+import qualified Data.Text as T
30+import GHC
31+import GHC.DynFlags (baseDynFlags)
32+import qualified Outputable as GHC
1333
14−-- | Combine all source spans from the given list.
15−
16−combineSrcSpans' :: NonEmpty SrcSpan -> SrcSpan
17−combineSrcSpans' (x:|xs) = foldr combineSrcSpans x xs
34+-- | Relative positions in a list.
35+data RelativePos
36+ = SinglePos
37+ | FirstPos
38+ | MiddlePos
39+ | LastPos
40+ deriving (Eq, Show)
1841
19−-- | Return 'True' if given element of AST is module.
42+-- | Attach 'RelativePos'es to elements of a given list.
43+attachRelativePos :: [a] -> [(RelativePos, a)]
44+attachRelativePos = \case
45+ [] -> []
46+ [x] -> [(SinglePos, x)]
47+ (x : xs) -> (FirstPos, x) : markLast xs
48+ where
49+ markLast [] = []
50+ markLast [x] = [(LastPos, x)]
51+ markLast (x : xs) = (MiddlePos, x) : markLast xs
2052
21−isModule :: Data a => a -> Bool
22−isModule x = showConstr (toConstr x) == "HsModule"
53+-- | Combine all source spans from the given list.
54+combineSrcSpans' :: NonEmpty SrcSpan -> SrcSpan
55+combineSrcSpans' (x :| xs) = foldr combineSrcSpans x xs
2356
2457-- | Placeholder for things that are not yet implemented.
25−
2658notImplemented :: String -> a
2759notImplemented msg = error $ "not implemented yet: " ++ msg
60+
61+-- | Pretty-print an 'GHC.Outputable' thing.
62+showOutputable :: GHC.Outputable o => o -> String
63+showOutputable = GHC.showSDoc baseDynFlags . GHC.ppr
64+
65+-- | Split and normalize a doc string. The result is a list of lines that
66+-- make up the comment.
67+splitDocString :: HsDocString -> [Text]
68+splitDocString docStr =
69+ case r of
70+ [] -> [""]
71+ _ -> r
72+ where
73+ r =
74+ fmap escapeLeadingDollar
75+ . dropPaddingSpace
76+ . dropWhileEnd T.null
77+ . fmap (T.stripEnd . T.pack)
78+ . lines
79+ $ unpackHDS docStr
80+ -- We cannot have the first character to be a dollar because in that
81+ -- case it'll be a parse error (apparently collides with named docs
82+ -- syntax @-- $name@ somehow).
83+ escapeLeadingDollar txt =
84+ case T.uncons txt of
85+ Just ('$', _) -> T.cons '\\' txt
86+ _ -> txt
87+ dropPaddingSpace xs =
88+ case dropWhile T.null xs of
89+ [] -> []
90+ (x : _) ->
91+ let leadingSpace txt = case T.uncons txt of
92+ Just (' ', _) -> True
93+ _ -> False
94+ dropSpace txt =
95+ if leadingSpace txt
96+ then T.drop 1 txt
97+ else txt
98+ in if leadingSpace x
99+ then dropSpace <$> xs
100+ else xs
101+
102+-- | Get 'LHsType' out of 'LHsTypeArg'.
103+typeArgToType :: LHsTypeArg p -> LHsType p
104+typeArgToType = \case
105+ HsValArg tm -> tm
106+ HsTypeArg _ ty -> ty
107+ HsArgPar _ -> notImplemented "HsArgPar"
108+
109+-- | Get 'RealSrcSpan' out of 'SrcSpan' if the span is “helpful”.
110+unSrcSpan :: SrcSpan -> Maybe RealSrcSpan
111+unSrcSpan = \case
112+ RealSrcSpan r -> Just r
113+ UnhelpfulSpan _ -> Nothing
114+
115+-- | Increment line number in a 'SrcSpan'.
116+incSpanLine :: Int -> SrcSpan -> SrcSpan
117+incSpanLine i = \case
118+ RealSrcSpan s ->
119+ let start = realSrcSpanStart s
120+ end = realSrcSpanEnd s
121+ incLine x =
122+ let file = srcLocFile x
123+ line = srcLocLine x
124+ col = srcLocCol x
125+ in mkRealSrcLoc file (line + i) col
126+ in RealSrcSpan (mkRealSrcSpan (incLine start) (incLine end))
127+ UnhelpfulSpan x -> UnhelpfulSpan x
128+
129+-- | Do two declarations have a blank between them?
130+separatedByBlank :: (a -> SrcSpan) -> a -> a -> Bool
131+separatedByBlank loc a b =
132+ fromMaybe False $ do
133+ endA <- srcSpanEndLine <$> unSrcSpan (loc a)
134+ startB <- srcSpanStartLine <$> unSrcSpan (loc b)
135+ pure (startB - endA >= 2)
136+
137+-- | Do two declaration groups have a blank between them?
138+separatedByBlankNE :: (a -> SrcSpan) -> NonEmpty a -> NonEmpty a -> Bool
139+separatedByBlankNE loc a b = separatedByBlank loc (NE.last a) (NE.head b)
140+
141+-- | Return 'True' if one span ends on the same line the second one starts.
142+onTheSameLine :: SrcSpan -> SrcSpan -> Bool
143+onTheSameLine a b =
144+ isOneLineSpan (mkSrcSpan (srcSpanEnd a) (srcSpanStart b))
145+
146+-- | Remove indentation from a given 'String'. Return the input with
147+-- indentation removed and the detected indentation level.
148+removeIndentation :: String -> (String, Int)
149+removeIndentation (lines -> xs) = (unlines (drop n <$> xs), n)
150+ where
151+ n = minimum (getIndent <$> xs)
152+ getIndent y =
153+ if all isSpace y
154+ then 0
155+ else length (takeWhile isSpace y)
tests/Ormolu/Parser/PragmaSpec.hsnew file+26
@@ -0,0 +1,26 @@
1+module Ormolu.Parser.PragmaSpec (spec) where
2+
3+import Ormolu.Parser.Pragma
4+import Test.Hspec
5+
6+spec :: Spec
7+spec =
8+ describe "parsePragma" $ do
9+ stdTest "{-# LANGUAGE Foo #-}" (Just (PragmaLanguage ["Foo"]))
10+ stdTest "{-# language Foo #-}" (Just (PragmaLanguage ["Foo"]))
11+ stdTest "{-#LANGUAGE Foo#-}" (Just (PragmaLanguage ["Foo"]))
12+ stdTest "{-# LANGUAGE Foo#-}" (Just (PragmaLanguage ["Foo"]))
13+ stdTest "{-#language Foo#-}" (Just (PragmaLanguage ["Foo"]))
14+ stdTest "{-# lAngUAGe Foo #-}" (Just (PragmaLanguage ["Foo"]))
15+ stdTest "{-# LANGUAGE Foo, Bar #-}" (Just (PragmaLanguage ["Foo", "Bar"]))
16+ stdTest "{-# LANGUAGE Foo Bar #-}" Nothing
17+ stdTest "{-# BOO Foo #-}" Nothing
18+ stdTest "something" Nothing
19+ stdTest "{-# LANGUAGE foo, Bar #-}" Nothing
20+ stdTest "{-# OPTIONS_GHC foo bar baz #-}" (Just $ PragmaOptionsGHC "foo bar baz")
21+ stdTest "{-#OPTIONS_HADDOCK foo, bar, baz #-}" (Just $ PragmaOptionsHaddock "foo, bar, baz")
22+
23+stdTest :: String -> Maybe Pragma -> Spec
24+stdTest input result =
25+ it input $
26+ parsePragma input `shouldBe` result
tests/Ormolu/Printer/CombinatorsSpec.hsdeleted−110
@@ -1,110 +0,0 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−
3−module Ormolu.Printer.CombinatorsSpec (spec) where
4−
5−import Ormolu.Anns
6−import Ormolu.Printer.Combinators
7−import Ormolu.Printer.Internal
8−import Test.Hspec
9−import qualified Data.Text.IO as T
10−
11−-- NOTE Testing combinators in separation is easy, but it's not very useful
12−-- either because interesting things happen only when combinators are used
13−-- together. However, there are too many combinations to test, so we test
14−-- just a few things here and expect new tests to be added on demand when
15−-- particularly tricky or problematic use cases are discovered.
16−--
17−-- The printing logic is indirectly tested in the main bulk of reformatting
18−-- tests.
19−
20−spec :: Spec
21−spec = do
22− stdTest "simple signature" rSimpleSig "ssig"
23− stdTest "list" rList0 "list0"
24− stdTest "list with annotated name in it" rList1 "list1"
25− stdTest "module header" rModuleHeader "mhdr"
26−
27−-- | Do a standard test prodedure testing both single-line and multi-line
28−-- layouts.
29−
30−stdTest
31− :: String -- ^ Test name
32− -> R () -- ^ Computation to test
33− -> FilePath -- ^ Base file name where expected result is stored
34− -> Spec
35−stdTest name m path = describe name $ do
36− let spath = "data/printer/" ++ path ++ "-single.hs"
37− mpath = "data/printer/" ++ path ++ "-multi.hs"
38− it "single-line works" $
39− singleLine m `shouldRender` spath
40− it "multi-line works" $
41− multiLine m `shouldRender` mpath
42−
43−----------------------------------------------------------------------------
44−-- Test computations
45−
46−rSimpleSig :: R ()
47−rSimpleSig = line rFn
48−
49−rList0 :: R ()
50−rList0 = line . brackets $
51− velt
52− [ txt "foo"
53− , comma >> txt "bar"
54− , comma >> txt "baz"
55− ]
56−
57−rList1 :: R ()
58−rList1 = line . brackets $
59− velt
60− [ txt "foo"
61− , comma >> txt "bar"
62− , comma >> rFn
63− ]
64−
65−rFn :: R ()
66−rFn = velt'
67− [ txt "foo"
68− , inci $ velt'
69− [ do txt ":: "
70− parens $ velt'
71− [ txt "Int"
72− , txt "-> " >> txt "Int"
73− ]
74− , txt "-> " >> txt "Bool"
75− ]
76− ]
77−
78−rModuleHeader :: R ()
79−rModuleHeader = do
80− line $ do
81− txt "module "
82− txt "MyModule"
83− line . inci . parens . velt $
84− [ txt "R"
85− , comma >> txt "runR"
86− , comma >> txt "txt"
87− , comma >> txt "blah"
88− ]
89− line (txt "where")
90−
91−----------------------------------------------------------------------------
92−-- Helpers
93−
94−-- | Run given computation in @'R' ()@ monad and compare result of rendering
95−-- with contents of a given file.
96−
97−shouldRender :: R () -> FilePath -> Expectation
98−shouldRender m path = do
99− expected <- T.readFile path
100− runR False m mempty mempty emptyAnns `shouldBe` expected
101−
102−-- | Render using single-line layout.
103−
104−singleLine :: R () -> R ()
105−singleLine = enterLayout SingleLine
106−
107−-- | Render using multi-line layout.
108−
109−multiLine :: R () -> R ()
110−multiLine = enterLayout MultiLine
tests/Ormolu/PrinterSpec.hs+32−22
@@ -2,17 +2,18 @@
22
33module Ormolu.PrinterSpec (spec) where
44
5+import Control.Exception
56import Control.Monad
67import Control.Monad.IO.Class
78import Data.List (isSuffixOf)
89import Data.Text (Text)
10+import qualified Data.Text as T
11+import qualified Data.Text.IO as T
912import Ormolu
1013import Path
1114import Path.IO
12−import System.FilePath (addExtension, dropExtensions, splitExtensions)
15+import qualified System.FilePath as F
1316import Test.Hspec
14−import qualified Data.Text as T
15−import qualified Data.Text.IO as T
1617
1718spec :: Spec
1819spec = do
@@ -20,9 +21,8 @@ spec = do
2021 forM_ es checkExample
2122
2223-- | Check a single given example.
23−
2424checkExample :: Path Rel File -> Spec
25−checkExample srcPath' = it (fromRelFile srcPath' ++ " works") $ do
25+checkExample srcPath' = it (fromRelFile srcPath' ++ " works") . withNiceExceptions $ do
2626 let srcPath = examplesDir </> srcPath'
2727 expectedOutputPath <- deriveOutput srcPath
2828 -- 1. Given input snippet of source code parse it and pretty print it.
@@ -32,6 +32,7 @@ checkExample srcPath' = it (fromRelFile srcPath' ++ " works") $ do
3232 formatted0 <- ormoluFile defaultConfig (fromRelFile srcPath)
3333 -- 3. Check the output against expected output. Thus all tests should
3434 -- include two files: input and expected output.
35+ -- T.writeFile (fromRelFile expectedOutputPath) formatted0
3536 expected <- (liftIO . T.readFile . fromRelFile) expectedOutputPath
3637 shouldMatch False formatted0 expected
3738 -- 4. Check that running the formatter on the output produces the same
@@ -40,42 +41,51 @@ checkExample srcPath' = it (fromRelFile srcPath' ++ " works") $ do
4041 shouldMatch True formatted1 formatted0
4142
4243-- | Build list of examples for testing.
43−
4444locateExamples :: IO [Path Rel File]
4545locateExamples =
4646 filter isInput . snd <$> listDirRecurRel examplesDir
4747
4848-- | Does given path look like input path (as opposed to expected output
4949-- path)?
50−
5150isInput :: Path Rel File -> Bool
5251isInput path =
5352 let s = fromRelFile path
54− (s', exts) = splitExtensions s
55− in exts == ".hs" && not ("-out" `isSuffixOf` s')
53+ (s', exts) = F.splitExtensions s
54+ in exts == ".hs" && not ("-out" `isSuffixOf` s')
5655
5756-- | For given path of input file return expected name of output.
58−
5957deriveOutput :: Path Rel File -> IO (Path Rel File)
60−deriveOutput path = parseRelFile $
61− addExtension (dropExtensions (fromRelFile path) ++ "-out") "hs"
58+deriveOutput path =
59+ parseRelFile $
60+ F.addExtension (F.dropExtensions (fromRelFile path) ++ "-out") "hs"
6261
6362-- | A version of 'shouldBe' that is specialized to comparing 'Text' values.
6463-- It also prints multi-line snippets in a more readable form.
65−
6664shouldMatch :: Bool -> Text -> Text -> Expectation
67−shouldMatch idempotencyTest actual expected =
68− when (actual /= expected) . expectationFailure $ unlines
69− [ ">>>>>>>>>>>>>>>>>>>>>> expected (" ++ pass ++ "):"
70− , T.unpack expected
71− , ">>>>>>>>>>>>>>>>>>>>>> but got:"
72− , T.unpack actual
73− ]
65+shouldMatch idempotenceTest actual expected =
66+ when (actual /= expected) . expectationFailure $
67+ unlines
68+ [ ">>>>>>>>>>>>>>>>>>>>>> expected (" ++ pass ++ "):",
69+ T.unpack expected,
70+ ">>>>>>>>>>>>>>>>>>>>>> but got:",
71+ T.unpack actual
72+ ]
7473 where
7574 pass =
76− if idempotencyTest
77− then "idempotency pass"
75+ if idempotenceTest
76+ then "idempotence pass"
7877 else "first pass"
7978
8079examplesDir :: Path Rel Dir
8180examplesDir = $(mkRelDir "data/examples")
81+
82+-- | Inside this wrapper 'OrmoluException' will be caught and displayed
83+-- nicely using 'displayException'.
84+withNiceExceptions ::
85+ -- | Action that may throw the exception
86+ Expectation ->
87+ Expectation
88+withNiceExceptions m = m `catch` h
89+ where
90+ h :: OrmoluException -> IO ()
91+ h = expectationFailure . displayException