Should the compiler help with inserting end-markes?

Background -rewrite

The awesome Scala 3 compiler can help with rewriting from old syntax to new syntax if ... then .. else, for ... do, while do. It can also “de-brace” my code. This is done with these handy sbt commands as a one time job when migrating from Scala 2:

sbt> set Compile/scalacOptions := Seq("-rewrite","-new-syntax")
sbt> clean;compile
sbt> set Compile/scalacOptions := Seq("-rewrite","-indent")
sbt> clean;compile

There are corresponding settings "-no-indent" and "-old-syntax" that reverse the above rewritings (if used in that order).

Proposal -rewrite -end-markers

I’m opening this thread to discuss the possibility that the Scala 3 compiler also could automatically insert end markers with something like:

sbt> set Compile/scalacOptions := Seq("-rewrite","-end-markers")

And it could be possible to remove end markers with a corresponding "-no-end-markers" in the spirit of the already existing rewritings.

I’d also like to discuss which out-of-the-box rules for auto-inserting end markers that the compiler should use. One possibility is that end markers are introduced if:

  • a method/class/object has more than N lines, or
  • a method/class/object has more than B blank lines in-between blocks of code, or
  • a method/class/object has indentation depth more than D

where e.g. N >= 10 || B >= 3 || D >=3
then end <name> is inserted marking the end of the named method/class/object.

I think that could be helpful, as I have during my migration gotten used to rewriting with sbt and the easy rewrite compiler settings.

Alternative solutions

An alternative could be to leave this for formatters, linting or IDEs. But even if such tools would include this cool functionality, preferably with a high degree of customization options, I still think it would be useful to also have “batteries included” in the compiler with an out-of-the-box rewriting with sane defaults for easy migration; if I’m not happy with some inserted/missing end markers I can always fix those instances manually, while getting the bulk done “for free”. Then when I develop new Scala 3 code I can turn on formatters, linting or IDE functions for automatic end markers if I like.

Conclusion

I think end-markers are great for readability, but sometimes its easy to get a bit lazy when migrating and the total happiness in the world could perhaps increase by some easy automation using rewrite. :slight_smile:

What do you think?

5 Likes

Automatic insertion of end-markers would be super useful! I see end markers as a better alternative to closing-braces in the instances where those are actually useful i.e long and deeply nested blocks of code.

Some good compiler-level defaults for when end-markers are auto-inserted are REALLY needed because:

  1. They would serve as a standard convention about how these things are done and avoid lengthy arguments.
  2. Based on this standard convention, IDEs and scalafmt would have a great starting point to build additional functionality (e.g. inserting end-markers as-you-type).
  3. They would encourage skeptics to switch away from braces.

I really hope the compiler provides this functionality!

3 Likes

I think this might be a good topic for scalafix. It would likely require configuration and scalafix is a natural for that. The compiler, not so much.

2 Likes

I really like the idea, but as long as the rules are purely syntactic (number of lines, presence of white lines, indentation level and so on) and the semantics are not affected, I think the most natural place for such a rewrite would be Scalafmt. After all the optional end marking are essentially a formatting construct

4 Likes

The “default option” is the strongest force in the world. Most of the C# community inserts a newline before opening braces just because that’s the Visual Studio default. In the US only 40% of people are organ donors as opposed to the UK where it’s 60% JUST because the US form is Opt-In vs Opt-Out.

Robust end-marker insertion is THE feature that will likely make optional whitespace win in the Scala community but that can only happen if it’s the Default Option. That means there has to be a very strong, and very clear convention for end-marker placement. Compiler-level insertion would obviously be the ideal. Scalafmt would be less ideal but still doable. Anything else would be much, much worse.

3 Likes

I found the compiler settings with -rewrite very handy. I want to write the end markers myself in new code, but for my legacy code it would save me work with a one-time rewrite.

On one hand, the rewrites of indent and new-syntax have perhaps bigger impact on migration work, as the old syntax will be deprecated (when?) and indentation seems to be the new idiom, while end-markers are more of a readability boost that is perhaps less salient than indent and new-syntax.

On the other hand I think end markers should be encouraged for deeply nested and long structures and if it is in the compiler as a first-class rewrite citizen, like the others already there, then it is more likely to be promoted as an idiom.

1 Like

I like the idea of a simple -rewrite where the only option is to opt out.

A recent ticket shows that opinions probably diverge quickly. Other tools such as Scalafix are in a better position to cater to preferences.

2 Likes

Yes @som-snytt – a simple, sane default -rewrite is exactly what I meant. I’m happy if e.g. Martin @odersky just selects a good default and then the output can be manually tweaked if some chunks have a bad ending. Rewrite is a one-time thing anyway during migration.

Just for the record, related IJ Scala Plugin tickets:
scala3: automatic end marker insertion/deletion on typing
scala3 formatter: enforce end markers
scala3 end marker completion

5 Likes

I created a follow up issue in scalafmt, which should benefit both Metals and Intellij. I am not sure however how hard it would be to implement nor whether anyone will be able to work on it any time soon.

5 Likes

@unkarjedy @tgodzik This is really cool!! :heart:

We’ve just released Scalafmt 3.0.0-RC4, which introduces support for automatically adding end markers. The exact configuration can be found here

All you need to do is specify the threshold that should make Scalafmt add the end marker. Please try it out and report any issues!

13 Likes