title: Roslyn: Continuously shadow-copy & syntax-transform a document as it is being changed
body: <p>I'm writing a script editor that needs to transform the user's input (which is similar to script syntax) into valid C# according to some rules I define. For example, if the users puts in</p>
  
  <pre><code>using System;
  
  public string hello()
  {
    return "Hi!"  // whoops, semicolon here is missing!
   }
  </code></pre>
  
  <p>I'd need to transform this to</p>
  
  <pre><code>using System;
  
  public class ContainerClass
  {
    public string hello()
    {
      return "Hi!"  // whoops, semicolon here is missing!
    }
  }
  </code></pre>
  
  <p>my transformation will insert new nodes (such as the class declaration) and might move around existing ones, but it will never modify or remove existing ones. (I know SourceCodeKind = Script does something vaguely <em>similar</em>, but I can't use that for a variety of reasons).</p>
  
  <p>Now I need to come up with a way to do this transformation given the following considerations:</p>
  
  <ol>
  <li><p>Since I need to run the transformation each time the user changes the original document (i.e. just types a single letter), I can't afford to re-parse the entire thing every time from a performance perspective. For example, if the user inserts the missing semicolon after ";", ideally I would just insert the same (or cloned) node into my already transformed document, instead of re-parsing everything. I suppose that rules out standard ways of modification such as DocumentEditor.</p></li>
  <li><p>I need to have a way to re-map locations from my transformed document to locations in the original document. Since I will never delete nodes, I think theoretically this should be possible (but how?).
  This is necessary e.g. as I would end up with diagnostic messages (and intellisense information etc.) pointing to locations in the transformed document, and need to get the original document's location for these to actually show them to the user.</p></li>
  </ol>
  
  <p>Can anyone thing of a more or less direct way to do this? Is there maybe even some Roslyn helper classes for use cases like this?</p>
  
  <hr>
  
  <p>My ideas below. I'm not quite sure they'd work, and I think they'd be very hard to implement, so I'm hoping there is some easier way to be honest;</p>
  
  <p>For #1, my only idea was to get get the text changes (Document.GetTextChangesAsync) of the original document after its source code changes; and then somehow try to find out what nodes have been affected by this (maybe get nodes that intersect the edited area in the old and new document, then compute which ones have been deleted, added or modified) - and then to apply these changes in my transformed document. This seems awfully complex though.</p>
  
  <p>For #2, my only idea so far was to enable tracking for nodes of the original document. Then I would find whatever node a location points to in the transformed document, and find the node in the original document this originated from (and then find the location of that node).
  But the problem is that e.g. the code above would produce a diagnostic error pointing towards the location right after "Hi!", wich the location span's length of 0, as there's a semicolon missing. So the location doesn't really point to a node at all. Maybe I could try finding adjacent nodes in that case?!</p>