tweag / ormolu

A formatter for Haskell source code
https://ormolu-live.tweag.io
Other
958 stars 83 forks source link

Multi-line example with do block and lambda causing Ormolu to produce a different AST #381

Closed mrkkrp closed 5 years ago

mrkkrp commented 5 years ago

Here is an example extracted (simplified) from capability (not even capability itself, but from one of the examples):

foo = catch
  do
     bar
     baz
  \e -> putStrLn $ "Too bad: " ++ show e

Ormolu fails to render something that parses to the same AST and instead outputs:

foo =
  catch do
    bar
    baz \e -> putStrLn $ "Too bad: " ++ show e

...which is obviously a totally different expression.

When this is fixed, also add capability to the list of packages we check on CI, because it contains particularly fancy and hairy Haskell, so it makes for a good testing case.

utdemir commented 5 years ago

A similar example:

Before:

foo = catch
  do
     bar
     baz
  end

After:

foo =
  catch do
    bar
    baz
    end

The issue happens because we hang the second argument of a function application, however this breaks when there is a third argument.

The problem is that at the point we're printing the second argument we do not know whether there is a third argument or not, since the AST looks like ((f arg1) arg2). So we have to pass some information from the parent nodes to the child nodes to fix this.