eclipse-archived / ceylon.formatter

A formatter for the Ceylon programming language, written in Ceylon.
Apache License 2.0
14 stars 11 forks source link

Ugly output #115

Closed tombentley closed 9 years ago

tombentley commented 9 years ago

I tried for format https://github.com/ceylon/ceylon.language/blob/0f144124206213e2151c4a9a426329649eaea2b4/src/ceylon/language/meta/model/ClassOrInterface.ceylon with ceylon format --maxLineLength=100 src/ceylon/language/meta/model/ClassOrInterface.ceylon and all got some very ugly output: https://gist.github.com/tombentley/74c8ce5e817cf57c9e0d

lucaswerkmeister commented 9 years ago

To clarify what exactly the bug is:

lucaswerkmeister commented 9 years ago

As it turns out, the first problem (annotations being pulled up) is due to a special case in DefaultLineBreaks for multi-line tokens, so the last problem (blank lines between methods removed) can’t be the same problem, since those don’t have multi-line tokens.

lucaswerkmeister commented 9 years ago

However, the underlying problem is that DefaultLineBreaks barely uses the existing LineBreaks (only as fallbacks when it can’t do better), which is wrong. Pre-existing LineBreaks should always be preferred to new ones. So the fix will probably still fix both problems at once.

lucaswerkmeister commented 9 years ago

Should be much better now, doc comments being pulled up and lines between methods being removed are both fixed now. See gist.

Remaining differences:

Comments? (Not necessarily just @tombentley, everyone can pitch in!)

gavinking commented 9 years ago
lucaswerkmeister commented 9 years ago

Actually, both of these are configurable: spaceAfterTypeArgOrParamListComma and spaceBeforeAnnotationPositionalArgumentList. I guess for the type argument problem, spacing around the = also needs to be configurable and/or depend on spaceAfterTypeArgOrParamListComma.

On 29.09.2015 00:21, Gavin King wrote:

  • Spaces after commas in type arg/parameter lists should be configurable.
  • Most days I prefer spaces before annotation arg lists, but perhaps it should also be configgable.

— Reply to this email directly or view it on GitHub https://github.com/ceylon/ceylon.formatter/issues/115#issuecomment-143890545.

tombentley commented 9 years ago

That is much better @lucaswerkmeister. One thing I would say (though I'm not sure if it's in scope or part of the more general line break problem) is that

throws (`class IncompatibleTypeException`, "If the specified `Container`, `Type` or `Arguments` type arguments are not compatible with the actual result, 
                                            or if the corresponding member is not a `MemberClass`.")

is a bit of a dogs breakfast, and I'd much rather see the parameter list broken than the doc string, even if the doc string gets nicely indented.

lucaswerkmeister commented 9 years ago
  • The formatter doesn’t think blank lines between imports are okay. The thing is, there’s no way to specify that zero to two line breaks are okay, but the default if there’s no token stream is one line break. So I think that’ll stay that way.

Turns out, that’s rubbish, it’s totally possible. Fixed in #119.

lucaswerkmeister commented 9 years ago

So the problem with the annotation string line breaking is that currently, there’s just no way for a LineBreakStrategy to signal that a line break needs to happen before a multi-line string. Long ago, to make multi-line strings work at all, I added a gross hacky special case to the return value of lineBreakLocation, which changes its meaning if the token on that location is multi-line. A special case for such tokens is indeed necessary – you need to signal that a line ends there, even though there’s no explicit line break – but it needs to be done differently, so that an explicit new line break can also be signaled.

I pushed a partial improvement of this on branch wip-115, where the return value is now interpreted differently, in what’s hopefully a more reasonable manner. However, it’s not done yet, and DefaultLineBreaks doesn’t yet break these lines correctly. I won’t have time to work on this until next Thursday (2015-10-15).

lucaswerkmeister commented 9 years ago

Alright, that took a while, but line breaks around multi-line string literals should now fully work.

lucaswerkmeister commented 9 years ago

Another gist with the differences.

lucaswerkmeister commented 9 years ago
  • sealed forces line break

✔ done in 7004a3d

  • bad spacing around type parameters

I’ve settled on splitting up spaceAfterTypeArgOrParamListComma into spaceAfterTypeParamListComma and spaceAfterTypeArgListComma and adding another option spaceAroundTypeParamListEqualsSign. These allow you to separately control:

That is, the default now produces

void foo<Param1=Default1, Param2=Default2>() {}
foo<Arg1,Arg2>();

whereas it previously produced

void foo<Param1 = Default1,Param2=Default2>() {}
foo<Arg1,Arg2>();

which you could only change to

void foo<Param1 = Default1, Param2 = Default2>() {}
foo<Arg1, Arg2>();

However, these option changes require matching changes in the IDE preferences code, so I haven’t pushed them yet.

lucaswerkmeister commented 9 years ago

Spacing around type params now also ✔ done in 10e09d695361860cdf4401a4fb8c55355504fd7f.

Note: the old option is still accepted (…TypeArgOrParamList… sets both …TypeArgList… and …TypeParamList…), so you don’t need to manually update your config files.

lucaswerkmeister commented 9 years ago

Fixed a few more things. Final comparison: gist.

I’m happy with the formatted code now, so I’m going to close this issue. @tombentley feel free to reopen it or open another issue if there’s something still wrong with it.