Axxes IT Consultancy

Fantomas 3.0: over-and-above

Prologue

Fantomas is a tool that can format F# code, like how Prettier for JavaScript works. The project was in rough shape when I first came across it and wasn’t actively maintained anymore. My F# mentor and I picked it up and started with some minor bugfixes and the port to .NET Core.

I asked Jindřich Ivánek to become co-maintainer due to his numerous contributions to the project. Last year at FableConf in Berlin, I had the opportunity to meet Jindřich in person and things have really gone up since then. We started to collaborate more, made useful tools to debug Fantomas and organize occasional Skype calls.

While the project was gaining some traction, new functionality was added to preserve the line ends after formatting. This change meant that the end of each formatted line was still more or less on the same line as the original source code.

At the time, it seemed like a good idea, however, it did bring along a lot of bugs with it. So, we decided to replace it with something similar. Trying to preserve each line end is simply not always possible. But preserving blank lines and comments is.

How Fantomas works

At a high-level, Fantomas (2.x), uses the FSharp Compiler Service to create an untyped abstract syntax tree (known as AST). It then traverses this tree and prints out all the nodes to strings. Check out the AST viewer to view some examples. The AST, however, does not contain all the information to do this.

A great example is code comments. These are nowhere to be found in the tree because the compiler doesn’t need them to create an executable format (.exe or .dll).

That is why after traversing the tree, the formatted code is being compared with the original. Token by token, the differences are being found and added to the new code if they are deemed necessary. To continue our code comments example, if it is found in the original and not in the formatted, it must have been added to the formatted code.

The road ahead

Some bugs were just not solvable with the current codebase. It is hard to pinpoint where comments should end up for example. Jindřich mentioned this to Don Syme and they started talking about the “trivia implementation.” Trivia is something that can be found in the source code but is not present in the AST. Comments and newlines being good examples, however, sometimes braces and keyword as well.

The main idea behind the next version of Fantomas is that we scan the source code first, before traversing the AST. In this scan, all the trivia are detected and linked to certain ranges. A range is a location inside the source base determined by four values (start-of-line, start-of-column, end-of-line and end-of-column). After the scan, we take this additional information with us when the tree is being traversed. If a node of the tree is being processed, we also take its trivia information into account. This way, we print the found-code comment at the time of creating the new code.

Once the tree has been fully traversed, we have already printed everything we need and do not require another comparison with the original source.

Rewriting all branches

Akin to C#, F# has the concept of compiler directives. With this, you can include or exclude a piece of code based a configuration-setting the compiler knows about.

#if DEBUG

printfn “Foo”

#else

printfn “Bar”

#endif

In the snippet above the word, “Foo” will be printed if the configuration is DEBUG, in RELEASE the word “Bar” would be printed. The current version of Fantomas will only format one of both code branches and add the other one as is.

The next version of Fantomas will format the code multiple times, based on the combination of found directives and merge all results back together afterwards. This is a new powerful feature that overcomes a previous limitation. In its current form, Fantomas will work for most scenarios and might only misbehave when conditional operators come into play. That last part is highly unlikely, so we will cross that bridge only when we have to.

Timing and Release

We have currently released the first beta of Fantomas 3.0 on NuGet. Or you can try it out online.
Please create issues if you encounter any problems whatsoever. Use the “create issue” link down below in the online tool.

With your help, we hope to be able to ship a stable version some time this summer.

Shout-outs

G Research

A huge supporter of big data research in real-world data sets, the firm focuses on analysis and scientific prediction of global financial markets. They like open-source research and support F# development and the research community around computer science.

Jindřich Ivánek

Jindřich has been my sounding board for various questions and suggestions. While I got the time to work on the project, he took the time to review and discuss my changes. Many thanks for all your time and effort.

The F# Community

Other people have really helped us well, shout outs to the ones that:

  • raised issues in GitHub
  • depend on Fantomas and provide us with feedback
  • helped us with technical questions about the compiler
  • supported us in any other way…

FableConf

Fantomas would not be what it is today without FableConf last year. Meeting Jindřich in person brought this endeavour to a whole new level. And frankly Fable has nothing to do with Fantomas, FableConf brings together the great F# community and acts as a catalyzer for innovation and collaboration.

Join us at FableConf Antwerp this year! Add your support and buy your ticket today. Trust me its an amazing experience and awe-inspiring event.

Feel free to reach out if you wish to support the further development of Fantomas – in whatever shape or form that may be!

Image by Thomas Konings

About the author

Florian Verdonck

Florian Verdonck

.NET Consultant

Share this article

GET TO KNOW US BETTER

Get to know Axxes and our corporate culture!

Want to learn more about Functional Programming?

Join us at FableConf on September the 6th & 7th!

Keep up with news and updates in the sector