I don’t know if I’ll do this every week, but this week I hit two spots of the .NET Compiler Platform API quicksand. I did not get out of either alone, so wanted to share what I learned.
I struggled fantastically with creating code for XML documentation. Run the Roslyn quoter against a simple comment and you’ll get the gist of it.
For my work with RoslynDom I need to go both ways after modifying the documentation:
- Code -> Compiler API (syntax tree) -> RoslynDom items
- RoslynDom items -> Compiler API (syntax tree) -> to code
The first works great. Grab the symbol and you can grab the documentation:
This gives you the XML as a string. Just load it as an XDocument and run as much LINQ to XML as you like. All is good.
But then… I needed to recreate the syntax tree. I really, really felt I should be able to build it up from primitives. After a few hours banging my head against that wall, I had to accept the core rule of …
The .NET Compiler Platform is a compiler, what it does really, really well is parse code.
So, even though it made me feel dirty, I wrote out the XML to a string, split the string into lines, iterated over the lines inserting the three slashes, and asked the SyntaxFactory to parse it. If you’re struggling to build something, see if you can parse into what you need.
In this particular case, it failed. I mean I had the output and it looked good, but the first three slashes were missing and the end of line at the end was missing. Specifically, I mean when I wrote it out in the immediate window these were missing. Crap.
Happily I have friends. Anthony D Green (ADG) on the team pointed out that I wasn’t using ToFullString(). At various points in working with the API, ToString() may do surprising things – working too hard or just getting nuts on your behalf. Perhaps someone somewhere needs the stripped version.
If you’re looking at a string output from the API, check it also with ToFullString().
The Formatter is picky, and EndOfLineTrivia requires \r\n
The .NET Compiler Platform is designed, and massively tested, with code that can happen in the real world from its own parsing. When you build trees, there is a large number of ways you can mess up that could never happen through parsing. I’d say infinite, but my son is an astrophysicist and doesn’t let me say things are infinite.
In my case, I naively thought that EndOfLineTrivia would understand that it was supposed to, well, you know, output an end of line. I did not anticipate that I would also need to pass a \r\n. I also did not anticipate that it would silently create an object that would later cause an exception – deep in the heart of the Formatter API. This time Balaji Soundrarajan did a little telepathic debugging and guessed that I’d failed to include \r\n. Thanks to him and all the folks that took a look at that one!