【问题标题】:Can I write a resharper plugin to refactor a custom DSL that generates c# code我可以编写一个 resharper 插件来重构生成 c# 代码的自定义 DSL
【发布时间】:2014-05-11 18:25:16
【问题描述】:

比如说我有一个 yaml 文件

immutable_class: Foo
  A: int
  B: string

根据想象的 MSBUILD 规则将生成

partial class Foo {

    public int A { set ; private get; }
    public string B { set; private get; }

    private Foo(){}

    public static Foo Default = new Foo(); 

    public Foo SetA(int value){
        var r = (Foo) this.Clone();
        r.A = value;    
        return r;
    }  

    public Foo SetB(string value){
        var r = (Foo) this.Clone();
        r.B = value; 
        return r;   
    }                  
}

现在在我的源代码中的某个地方我将拥有

Foo foo = Foo.Default;
foo = foo
    .SetA(1)
    .SetB("Hello");

var tmp = foo.B;

我现在告诉 resharper 我希望重构重命名 B 并且插件将识别此属性的来源是生成类的 DSL,并相应地重构该 DSL。假设一旦我被正确的信息触发,我就有工具可以自己实际重构 DSL。

Resharper API 是否足够开放,可以做这种事情?

【问题讨论】:

  • 好问题!让我试着想一个不涉及首先在 R# 中实现 YAML 支持的答案:)

标签: c# plugins refactoring resharper dsl


【解决方案1】:

ReSharper API 或多或少允许您执行此操作,但实现起来并非易事。

您需要实现对 yaml 文件的文件支持。一旦有了抽象语法树,就可以在 C# 文件中的 B 节点和 yaml 文件中的 B 节点之间创建引用。重命名时,ReSharper 将能够跟随引用,并将引用文本从“B”重命名为任何内容。

(通过编辑生成的类和生成它的数据会增加额外的复杂性。例如,如果您重命名 Foo.B,这将更新 yaml 文件中的 B,但是如何更新Foo.SetB 方法?我想你可以通过实现从 yaml BFoo.SetB 方法的引用来做到这一点,当重命名 B 时,它会重命名 SetB。但是,如果你重命名 @987654334 @? 我不知道如何处理。您还需要找到一种方法来知道 yaml 文件旨在生成 C# 文件)

在 ReSharper 中提供文件支持并非易事,但它是对文件内容进行所有操作(导航、使用、重构、编辑等)的基础。 devguide 中没有正确记录它,但有一些例子:

  • ForTea - 通过手工制作的解析器为 .tt 文件提供语言支持
  • NTriples - 语言支持 RDF 三元文件,使用 SDK 的专有解析器格式
  • AngularJs plugin - 嵌入在 HTML 文件中的 AngularJS 表达式中的语言支持。修改现有的 JS 语言解析器以支持 Angular 所需的子集。

【讨论】:

  • 几点。 1 生成的代码永远不会被编辑。将像 XAML 一样生成部分类,因此用户可以自定义这种方式。 2 不需要完整的 YAML 解析器,只需代表正在实现的 DSL
  • 您仍然需要创建 dsl 控制文件的抽象语法树(yaml 与否)以允许树中节点之间的引用。
  • 当然可以,但是 AST 会比完整的 YAML AST 简单得多。 YAML 文件只是词法分析器阶段。我会解析它并构建一个 AST,然后生成所需的 C# 代码。 resharper 挂钩将能够修改 AST,然后写回相应的 YAML。反正就是这样。
猜你喜欢
  • 2022-06-10
  • 1970-01-01
  • 2014-03-07
  • 1970-01-01
  • 2012-03-03
  • 2017-05-12
  • 1970-01-01
  • 2019-09-16
  • 2010-10-14
相关资源
最近更新 更多