Roslyn - 更改SyntaxToken或SyntaxNode的TextSpan

时间:2014-08-01 08:32:48

标签: c# roslyn

有没有办法创建SyntaxTokenSyntaxNode并更改FullSpan属性?

由于所有类都是密封的,不可变的并且没有可访问的构造函数,因此创建一个类的唯一方法是使用SyntaxFactory静态方法,这些方法没有重载来指定位置。

我正在编写一种脚本语言,该语言被解析为Roslyn SyntaxTree。当使用访问者模式检查表达式的语义时,我希望能够通过将节点映射到某个位置来告诉用户错误发生的位置。

还有吗?提前致谢。

1 个答案:

答案 0 :(得分:7)

不,没有办法做到这一点。我们确保我们的语法树遵循几个核心原则:

  1. 树的开头是零位。
  2. 孩子们的整个范围都是有序的,彼此相邻(即一个人的结尾是另一个人的开始)
  3. 节点的完整范围等于其所有子节点的总和。
  4. 这些核心公理意味着分析树的任何代码(包括编译器)都可以合理地使用树。如果我们为您提供了为某些节点而不是其他节点指定FullSpans的方法,那么我们将无法维护这些不变量以及谁知道会破坏什么。我们可能会要求您指定所有跨度,但此时您只是疯狂地试图维持这些公理。

    您有几个选择:

    1. 您可以在生成的源中使用#line指令告诉编译器脚本文件中的“真实”代码行。通常,这意味着在将用户代码放入文件之前,您需要在其前面添加#line。我们有像SyntaxTree.GetMappedLineSpan这样的函数,它将采用常规范围,并根据我们对#line指令的解释将其转换为文件/行/列信息。

    2. 如果为不同的表达式生成一堆小树,只需保留树的地图 - >您的文件中的起始位置,以及当您需要转换为显示位置时,只需通过该位置进行映射。

    3. 如果生成带有一堆表达式的单个树,请将SyntaxAnnotation附加到表达式中,其中包含表达式所在的脚本文件中的位置。然后,您可以通过向父母一起走,直到找到SyntaxAnnotation,然后计算该位置来轻松计算节点的脚本文件位置。