【问题标题】:Collecting a source code change list and then apply it with Roslyn收集源代码更改列表,然后使用 Roslyn 应用它
【发布时间】:2023-04-04 10:43:01
【问题描述】:

我正在使用 Roslyn 实现不同的源代码转换。 (代码上下文将是一个独立的命令行实用程序,不是一个 VS CodeAction)

实现 CSharpSyntaxRewriter 并在访问特定节点时应用更改 on fly 的最简单方法。然而,这种方法可能有也可能没有副作用,导致结果不稳定。在更改树时,我们也在更改语义模型,因此之前获得的语义模型可能会失效。不详细介绍它有点类似于更改列表,同时枚举该而不通知枚举器

(是的,我知道树是不可变的,但这就是重点:当重载方法返回替换节点而不是原始节点时,访问者更改它。)

所以我有了这个想法:我们必须分两遍进行转换:首先收集更改,第二次实际应用更改。

  • 第一遍显然是一个CSharpSyntaxRewriter(访问者),实际上并没有重写任何东西,只是产生了一个更改列表。 (也许一些较低的基本访问者类会比重写器做得更好,因为实际上不会在此过程中重写任何东西)
  • 第二遍是更改列表应用程序,用于应用在第一遍中收集的更改。

下一个有趣的想法,第二遍不必操作树本身:它可以直接操作原始源文本(第一遍可以构建具有确切源代码位置的更改列表,因为 Span 信息可用于每个节点和令牌。)

抱歉这么长的解释,现在是问题:

我不想重新发明轮子:是否已经在 Roslyn 中实现了任何源代码操作基础架构(有一个更改列表,(例如基于 Spans)和 Apply(...) 它在源代码上?

提前谢谢

【问题讨论】:

  • 我认为(但我可能错了)如果 "tree is immutable" 那么访问者 不会 更改它。这是一个处理阶段,而不是就地修改。
  • @Adriano,当然访问者不会更改不可变的东西,而是继续处理创建和更改的新对象,特别是当访问方法返回替换并且子节点尚未访问时。这样整个处理就完成了,而且数据结构不一致,前半部分处理在原来的,后半部分改了其他的。

标签: c# roslyn


【解决方案1】:

找到所描述的内容:

SourceText 类有一个 WithChanges(...) 方法,该方法通过应用更改返回新的 SourceText 实例 transformad。更改采用 TextChange 列表的形式,它基本上是 TextSpan 的薄包装,包含 span 本身和替换文本。

感谢任何花时间处理此问题的人。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-31
    • 2019-05-03
    • 1970-01-01
    • 2012-02-14
    相关资源
    最近更新 更多