ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c# – 如何使用Roslyn以编程方式从代码中删除区域?

2019-06-27 13:55:41  阅读:190  来源: 互联网

标签:c roslyn


我正在使用Roslyn从文本中解析C#代码.一些代码具有围绕多个类的区域.例:

#region Classes
public class MyClass
{
}

public class MyClass2
{
    #region Methods
    #endregion
}
#endregion

我想删除类周围的区域(上例中的“类”),但保留内部区域,就像上面示例中名为“Methods”的区域一样.我该怎么做呢?

解决方法:

区域相当特殊,因为它们不遵循通常的树形结构.例如,您可以创建一个这样的构造:

public class TestClass{
    public void TestMethod(){
        #region TestRegion
    }
}
#endregion

这仍然有效.考虑到这一点,在分析区域时还有一个问题:它们是琐事中的节点.因此,要获取相关节点,您可以使用SyntaxRewriter(并传递构造函数“true”以启用琐事分析)或使用node.DescendantNodes(descendIntoTrivia:true)查找后代节点.

由于区域的开始和结束可能位于文件中的任何位置,因此您应始终在语法树的根目录开始分析,以确保您可以找到区域的结束/开始.

为了找到该区域,您可以覆盖VisitRegionDirectiveTrivia以及VisitEndRegionDirectiveTrivia.由于RegionTrivia的开始和结束彼此不了解,您需要自己匹配它们.在下面的例子中,我简单地计算了我已经传递了多少个区域,并注意了一个#endregion位置列表,这些位置在走出区域时应该被删除.

为了识别相关区域,我提供了两种方法:您可以使用区域名称或标识附加的节点是否为ClassDeclaration.

这两种方法都没有在类声明之前考虑诸如属性声明之类的情况.如果你想要处理这个问题,你需要看看兄弟节点,并检查它们是否在该区域的范围内开始.

private class RegionSyntaxRewriter : CSharpSyntaxRewriter
{
    int currentPosition = 0;
    private List<int> EndRegionsForDeletion = new List<int>();
    private string deletedRegion;
    private bool useRegionNameForAnalysis = false;

    public RegionSyntaxRewriter(string deletedRegion) : base(true)
    {
        this.deletedRegion = deletedRegion;
    }

    public override SyntaxNode VisitRegionDirectiveTrivia(
            RegionDirectiveTriviaSyntax node)
    {
        currentPosition++;
        var regionText = node.ToFullString().Substring(8).Trim();
        if (!useRegionNameForAnalysis &&
            node.ParentTrivia.Token.Parent is ClassDeclarationSyntax)
        {
            EndRegionsForDeletion.Add(currentPosition);
            return SyntaxFactory.SkippedTokensTrivia();
        }
        if (useRegionNameForAnalysis && 
            regionText == deletedRegion)
        {
            EndRegionsForDeletion.Add(currentPosition);
            return SyntaxFactory.SkippedTokensTrivia();
        }

        return base.VisitRegionDirectiveTrivia(node);
    }

    public override SyntaxNode VisitEndRegionDirectiveTrivia(
            EndRegionDirectiveTriviaSyntax node)
    {
        var oldPosition = currentPosition;
        currentPosition--;
        if (EndRegionsForDeletion.Contains(oldPosition))
        {
            EndRegionsForDeletion.Remove(currentPosition);
            return SyntaxFactory.SkippedTokensTrivia();
        }

        return base.VisitEndRegionDirectiveTrivia(node);
    }
}

标签:c,roslyn
来源: https://codeday.me/bug/20190627/1305409.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有