【问题标题】:Search and replace C# expression搜索和替换 C# 表达式
【发布时间】:2015-08-28 03:24:20
【问题描述】:

我一次又一次地发现自己需要将一种方法调用的使用更改为另一种方法调用。

例如我有 100 次类似的方法调用:

Helper.GetIntFromData(packetData.Skip(offset).Take(length).ToArray());

需要改成

Helper.GetIntFromData(packetData, offset, length);

这可以通过正则表达式相对容易地解决。但是如果空白(有时)发挥作用呢?

Helper.GetIntFromData(packetData
    .Skip(  offset  )
    .Take(  length  )
    .ToArray()  
);

仍然可以使用正则表达式,但它现在是一堆不可读的可选空白标记。

好的,但是如果参数并不总是简单的标识符,而是任意表达式呢?

Helper.GetIntFromData(obj.GetData(true).Skip( 7 + GetOffset( item.GetData() ) )
    .Take( length1 / length2 ).ToArray());

这是正则表达式真正崩溃的地方。

我的问题是:

今天可以完成吗? (以一种让你保持理智的方式,即没有正则表达式)

是否有可以在更高(语义)级别处理搜索和替换 C# 代码的 VS 扩展或独立工具?

可以让我搜索的东西(我想):

Helper.GetIntFromData($expr1.Skip($expr2).Take($expr3).ToArray())

替换为

Helper.GetIntFromData($1, $2, $3)

C# 是否存在这样的工具? (我想它可以围绕 Roslyn 构建。)

【问题讨论】:

    标签: c# regex visual-studio roslyn


    【解决方案1】:

    再想一想,你想要达到的目标是危险的,最好避免。 RegEx 匹配/替换是一项有限功能。它无法“理解”复杂的代码,并且注定会失败。考虑一个例子(如果该代码甚至有意义,让我们忽略一秒钟):

    Helper.GetIntFromData(packetData.Skip(skipArray.Take(1)).Take(length).ToArray());

    不是专门为避免“错误的Take”而定制的正则表达式是不可能的。你的自动替换方法破坏你的代码只是时间问题,你唯一的希望是它足够残酷以产生编译时错误。它也可能会造成很难找到运行时异常或更糟糕的无法解释的行为。代码重构应该使用能够理解代码的工具,而不是能够识别文本模式的工具。

    【讨论】:

    • 没错。这就是为什么我要询问语义搜索/替换——而不是语法,比如正则表达式。
    【解决方案2】:

    如果可能的话,我会“手动”完成,但使用简单的正则表达式(是的,我知道你说没有它们,虽然我没有检查过边缘情况,但 Amit 的回答“看起来正确”)。

    类似这样的:

    Helper.GetIntFromData(packetData.Skip(offset).Take(length).ToArray());
    Helper.GetIntFromData(obj.GetData(true).Skip( 7 + GetOffset( item.GetData() ) )
        .Take( length1 / length2 ).ToArray());
    

    (Helper.GetIntFromData.*?)\.Skip\(替换为\1,得到

    Helper.GetIntFromData(packetData, offset).Take(length).ToArray());
    Helper.GetIntFromData(obj.GetData(true),  7 + GetOffset( item.GetData() ) )
        .Take( length1 / length2 ).ToArray());
    

    然后将(Helper.GetIntFromData.*?)\)\.Take\(替换为\1,即可得到

    Helper.GetIntFromData(packetData, offset, length).ToArray());
    Helper.GetIntFromData(obj.GetData(true),  7 + GetOffset( item.GetData() ) 
        ,  length1 / length2 ).ToArray());
    

    最后将(Helper.GetIntFromData.*?)\)\.ToArray\(\)\);替换成\1\);得到

    Helper.GetIntFromData(packetData, offset, length);
    Helper.GetIntFromData(obj.GetData(true),  7 + GetOffset( item.GetData() ) 
        ,  length1 / length2 );
    

    【讨论】:

      【解决方案3】:

      Resharper 具有语义搜索和替换功能

      Helper.GetIntFromData(packetData.Skip($offset$).Take($length$).ToArray());
      

      Helper.GetIntFromData(packetData, $offset$, $length$);
      

      它对空格不敏感,您可以将标记匹配限制为某些类型。我一直用它来做你想做的事情。我还没有看到任何基于 roslyn 的项目让所有用户都如此轻松地做到这一点。

      这是 resharpers 网站上的功能介绍

      http://blog.jetbrains.com/dotnet/2010/04/07/introducing-resharper-50-structural-search-and-replace/

      【讨论】:

      • 伙计,我永远无法让它发挥作用。猜猜是时候再试一次了。
      猜你喜欢
      • 2013-06-14
      • 1970-01-01
      • 2018-05-25
      • 2010-11-25
      • 2010-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多