Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Roslyn - Change TextSpan of SyntaxToken or SyntaxNode

Tags:

c#

roslyn

Is there any way to create a SyntaxToken or SyntaxNode and change the the FullSpan property?

As all the classes are sealed, immutable and have no accessible constructors the only way to create one is by using the the SyntaxFactory static methods and these have no overload to specify a location.

I am writing a scripting language which is parsed into a Roslyn SyntaxTree. When using the visitor pattern to check the semantics of expressions I want to be able to tell the user where the error occurred by mapping the nodes to a location.

Is there anyway? Thanks in advance.

like image 932
user2697817 Avatar asked Aug 01 '14 08:08

user2697817


1 Answers

Nope, there's not a way to do this. We ensure that our syntax trees adhere to several core principles:

  1. The start of a tree is position zero.
  2. The full spans of children are in order, and abut each other (i.e. the end of one is the start of another)
  3. The full span of a node equals the span of all it's children combined.

These core axioms mean that any code (including the compiler) that are analyzing a tree can reasonably work with the tree. If we gave you a way to specify FullSpans for some nodes and not others, we wouldn't be able to maintain these invariants and who knows what would break. We could potentially require you to specify all spans, but at that point you'll just drive yourself insane trying to maintain these axioms.

You have a few options:

  1. You could use the #line directive in your generated source to tell the compiler the "real" lines of code in your script file. Typically, this means right before you put the user's code in the file you stick a #line before it. We have functions like SyntaxTree.GetMappedLineSpan which will take a regular span and convert it to file/line/column information based upon our interpretation of #line directives.

  2. If you generate a bunch of small trees for different expressions, just keep a map of tree -> starting position in your file, and when you need to convert to a display location just map through that.

  3. If you generate a single tree with a bunch of expressions, attach SyntaxAnnotations to your expressions that includes the position in your script file where the expression came from. Then, you can easily compute a script file location for a node by walking up through parents until you find a SyntaxAnnotation, and then compute the location that way.

like image 155
Jason Malinowski Avatar answered Oct 30 '22 09:10

Jason Malinowski