有没有办法创建SyntaxToken
或SyntaxNode
并更改FullSpan
属性?
由于所有类都是密封的,不可变的并且没有可访问的构造函数,因此创建一个类的唯一方法是使用SyntaxFactory
静态方法,这些方法没有重载来指定位置。
我正在编写一种脚本语言,该语言被解析为Roslyn SyntaxTree
。当使用访问者模式检查表达式的语义时,我希望能够通过将节点映射到某个位置来告诉用户错误发生的位置。
还有吗?提前致谢。
答案 0 :(得分:7)
不,没有办法做到这一点。我们确保我们的语法树遵循几个核心原则:
这些核心公理意味着分析树的任何代码(包括编译器)都可以合理地使用树。如果我们为您提供了为某些节点而不是其他节点指定FullSpans的方法,那么我们将无法维护这些不变量以及谁知道会破坏什么。我们可能会要求您指定所有跨度,但此时您只是疯狂地试图维持这些公理。
您有几个选择:
您可以在生成的源中使用#line指令告诉编译器脚本文件中的“真实”代码行。通常,这意味着在将用户代码放入文件之前,您需要在其前面添加#line。我们有像SyntaxTree.GetMappedLineSpan
这样的函数,它将采用常规范围,并根据我们对#line指令的解释将其转换为文件/行/列信息。
如果为不同的表达式生成一堆小树,只需保留树的地图 - >您的文件中的起始位置,以及当您需要转换为显示位置时,只需通过该位置进行映射。
如果生成带有一堆表达式的单个树,请将SyntaxAnnotation
附加到表达式中,其中包含表达式所在的脚本文件中的位置。然后,您可以通过向父母一起走,直到找到SyntaxAnnotation
,然后计算该位置来轻松计算节点的脚本文件位置。