Ormolu can be turned on and off via the special comments:
{- ORMOLU_DISABLE -}
and
{- ORMOLU_ENABLE -}
This allows us to disable formatting selectively for code between these
markers or disable it for the entire file. To achieve the latter, just put
{- ORMOLU_DISABLE -} at the very top. Note that the source code should still
be parseable even without the “excluded” part. Because of that the magic
comments cannot be placed arbitrary, but should rather enclose independent
top-level definitions.
It is tempting to enable ‘ImportQualifiedPost’ automatically for all files,
but in that case we won't be able to tell when to format in the
classical (prefix) style vs the new postfix style. Checking the list of
pragmas on per-file basis is not good enough because the extension can be
enabled in other ways, such as via the --ghc-opt flag.
GHC 8.10.1 comes with some changes to the AST, which works great for
Ormolu, but causes this commit to be a bit large:
* Trees That Grow extension points for new constructors are now statically
proven to be uninhabited, via noExtCon :: NoExtCon -> a. Thanks to this
change I got rid of many notImplemented calls.
* LPat constructor is now a lot more usable, so we don't need to use
the locatedPat combinator and can remove some boilerplate code.
Also it comes with ImportQualifiedPost and StandaloneKindSignatures
we should support. I did not implement them in this commit, they'll
be merged in later on.
It causes one behaviour change, where the ordering of qualified and
non-qualified imports of the same module is changed. This is due to
our usage of gcompare resulting a different ordering because of the
AST change caused by the ImportQualifiedPost extension. I think this is
acceptable and we shouldn't try to keep backwards compatibility there.
Another behaviour change is that previously HsExpr had a few extra
constructors for arrows and patterns used in expression context. Those
programs were syntactically incorrect, but refused on a later stage. But
we nonetheless formatted those constructs so Ormolu didn't fail there
while keeping the source code intact. However, now those constructors
are removed, so Ormolu fails with a parse error in this case (same as
GHC). I also removed some tests exhibiting this behaviour.
Preserve user-added newlines with the following normalizations:
* No newlines below where
* Consecutive newlines are compressed into a single newline
* Always surround documented declarations with blank lines
Previously we hanged record constructors but not record updates. It looks
like unlike other hanging constructions (lambdas, case expressions, and
do-blocks), record constructors and updates should rather be placed
normally. Indeed, when we stop hanging them, many constructions start to
look more reasonable and predictable (see the updated test cases).
Yet the change is not enough to fix the problem in general case: it is
enough to replace the record with a e.g. do-block to get the same failure.
To correct that we adjust what should fit in one line for hanging placement
to fire: now we consider the span between beginning of function and the
start of potentially-hanging construction.
This supports the two forms of ‘RecordDotSyntax’ that are likely to be
upstreamed ‘expr.lbl’ and ‘(.lbl)/ .lbl’.
We detect -fplugin=RecordDotPreprocessor and -pgmF=record-dot-preprocessor
in -o arguments or pragmas in files and just do the right thing.
Usually we want to bump indentation for arguments for the sake of
readability. However, when the function itself is a do-block or case
expression it is not a good idea. It seems to be safe to always bump
indentation when the function expression is parenthesised.
The order in which language pragmas are put in the input sometimes matters.
This is because some language extensions can enable other extensions, yet
the extensions coming later in the list have the ability to change it. So
here we classify all extensions by assigning one of the four groups to them.
Then we only sort inside of the groups.
I originally thought it's a good idea to prevent this, but it looks like it
makes things arguably worse in certain cases even though the Haddocks end up
not associated with their declarations (but they are not associated with
them in the input either, so it's OK).
When deciding on the fixity of an operator, we assign a score based on some
heuristics. When an operator is used multiple times in an operator chain, we
used to calculate the mean of its scores to decide on the final fixity.
However, this was prone to outliers.
In an example like this:
b & c .~ d
& e
%~ f
g
The first use of & is surrounded by other values, so we assign it a higher
score (binds tighter). However the second occurence is at the beginning of a
line, and this has a lower score. In the end, when we average those two
values the result binds tighter than %~, which is not what we want.
This PR replaces the average method with a mode operation instead, so it is
less prone to outliers.
This PR fixes this specific issue, and does not cause any change on other
test cases, but it might cause some diffs in the wild.
This change modifies the ‘HsApp’ printer to handle all function parameters
at once instead of following the AST order.
This allows us to consistently put each function argument on separate lines.
Previously, when printing the function f a b c, the AST would look like (((f
a) b) c), which would cause inconsistencies regarding to newlines (imagine f
a\n b).
Otherwise I tried to preserve the same behaviour as the previous printer,
and added a few tests.
This only changes the ‘p_hsExpr’ function, rest of the changes are caused by
the formatting change.
The commit changes how type signatures are printed. The new style looks like
this:
foo ::
Int ->
Char ->
String
This works better with foralls and other features of the type system that
will be added in the near future, like linear arrows.
In order to print Haddocks nicely (this seems to be the only acceptable
placement):
foo ::
-- | First argument
Int ->
-- | Second argument
Char ->
-- | Result
String
It is often necessary to re-arrange them completely and use the “pipe style”
instead of “caret style”. It proved to be a very hard task with our older
comment-handling system, if not impossible.
Here we start parsing Haddocks so that they are treated as components of AST
and we now render them as part of rendering of those components. The
existing framework for handling comments only prints non-Haddock comments
now.
The change caused a fair number of new problems and failures which I added
new tests for.
Haskell strings can have "gaps", where any amount of whitespace between
two backslashes are ignored. This allows writing multi-line strings. As
an example, all strings below are the same:
```
"foobar"
"foo\ \bar"
"foo\
\bar"
```
When parsing a string literal, lexer usually produces two fields, one
of them is the actual string user wrote as a 'SourceText', the other one
is the sanitized version where gaps and other special characters removed.
While printing the string, GHC's Outputable instance uses the 'SourceText'
field, however since that text contains gaps as-is, we can not change
the original indentation. In order to fix this, this commit splits the
strings by the gaps and print each line separately applying the layout
rules.
Also, it applies the same logic to type-level strings.