Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 与Roslyn比较2种方法,包括评论和琐事_C#_Roslyn - Fatal编程技术网

C# 与Roslyn比较2种方法,包括评论和琐事

C# 与Roslyn比较2种方法,包括评论和琐事,c#,roslyn,C#,Roslyn,我需要在c代码中对两种方法进行比较, 我发现SyntaxNode.IsEquivalentTo,但如果方法是: public void Method1() { //hello } 及 返回值为:True Rslyn API是否有其他方法来执行比较,包括注释和琐事?? (在上面的例子中得到:False??) (我不使用常规字符串比较的原因是我不希望空格和新行不算作差,例如: public void Method1() { int i=1; } 及 将相等。如果它们需要完全相同,

我需要在c代码中对两种方法进行比较, 我发现SyntaxNode.IsEquivalentTo,但如果方法是:

public void Method1()
{
    //hello
}

返回值为:
True

Rslyn API是否有其他方法来执行比较,包括注释和琐事?? (在上面的例子中得到:False??)

(我不使用常规字符串比较的原因是我不希望空格和新行不算作差,例如:

public void Method1()
{
    int i=1;
}


将相等。

如果它们需要完全相同,您只需在节点上调用
node.ToString()
,然后比较字符串。

在编写本文时,没有内置方法支持这种比较,但使用语法重写器编写一个方法很容易

基本思想非常简单。编写一个函数,从两个比较的节点中删除所有非注释性琐事,然后使用内置方法比较新创建的节点

下面的代码就是您要查找的。要比较两个节点(
MethodDeclarationSyntax
),只需调用:

firstNode.IsEquivalentToWithCommentsPreserved(secondNode);
以下是实施方案:

public static class SyntaxNodeExtensions
{
    public static bool IsEquivalentToWithCommentsPreserved(this SyntaxNode syntaxNode, SyntaxNode otherNode)
    {
        var triviaRemover = new NonCommentTriviaRemover();
        return triviaRemover.Visit(syntaxNode)
               .IsEquivalentTo(triviaRemover.Visit(otherNode));
    }

    private class NonCommentTriviaRemover : CSharpSyntaxRewriter
    {
        private static readonly SyntaxTrivia EmptyTrivia = default(SyntaxTrivia);

        public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia)
        {
            return trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) ||
                   trivia.IsKind(SyntaxKind.MultiLineCommentTrivia)
                ? trivia // Preserve comments by returning the original comment trivia.
                : EmptyTrivia; // Remove all other trivias.
        }
    }
}
请记住,此代码不会忽略注释中琐事的最终差异。这意味着,这两个版本的方法将被视为不等效:

void Method()
{
    // Some comment.
}

void Method()
{
    // Some      comment.
}
如果您可能需要忽略这些差异,请告诉我。然后我可以扩展解决方案以涵盖该情况

我很快就在以下一个非常重要的示例上尝试了该解决方案,效果很好:

var firstCode =
@"
    // First comment.
    // Second comment.
    int x(int a)
    {
        // This is a comment.
        // And this as well.
        if (a == 1) // This also
        {
            return 0 ;
        }

        /*
            Multi line comment.
        */if(a == -5) return -10   ;

        if (a == 2)
                return 0 ;

        return 5;

    }
";

var secondCode =
@"
    // First comment.

    // Second comment.

    int x(int a)
    {

        // This is a comment.
        // And this as well.
                if    (a 
                == 1) // This also
        {
            return     0 ;
              }

        /*
            Multi line comment.
        */

        if(a == -5) return -10   ;

        if (a == 2) return 0 ;

        return 5;


    }
";

var firstMethod = CSharpSyntaxTree.ParseText(firstCode).GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First();
var secondMethod = CSharpSyntaxTree.ParseText(secondCode).GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First();

Console.WriteLine($"{firstMethod.IsEquivalentTo(secondMethod)}"); // Prints false.
Console.WriteLine($"{firstMethod.IsEquivalentToWithCommentsPreserved(secondMethod)}"); // Prints true.
var firstCode=
@"
//第一条评论。
//第二条评论。
整数x(整数a)
{
//这是一个评论。
//还有这个。
如果(a==1)//这也是
{
返回0;
}
/*
多行注释。
*/如果(a==-5)返回-10;
如果(a==2)
返回0;
返回5;
}
";
var第二代码=
@"
//第一条评论。
//第二条评论。
整数x(整数a)
{
//这是一个评论。
//还有这个。
如果(a)
==1)//这也是
{
返回0;
}
/*
多行注释。
*/
如果(a==-5)返回-10;
如果(a==2)返回0;
返回5;
}
";
var firstMethod=CSharpSyntaxTree.ParseText(firstCode).GetRoot().genderantNodes().OfType().First();
var secondMethod=CSharpSyntaxTree.ParseText(secondCode.GetRoot().genderantnodes().OfType().First();
Console.WriteLine($“{firstMethod.IsEquivalentTo(secondMethod)}”);//打印为false。
Console.WriteLine($“{firstMethod.IsequivalentToWithCommentsReserved(secondMethod)}”);//打印true。

尽管如此,在产品中使用代码之前,最好为其编写适当的单元测试、空检查等;-)

但我不希望额外的空间或新行被视为差异,而使用ToString()则会……空格、新行和注释都是琐事。所以我认为你想比较平等,包括琐事,但没有空格琐事?是的,所有的代码和注释都将包括在内。不包括空格和额外的新行
void Method()
{
    // Some comment.
}

void Method()
{
    // Some      comment.
}
var firstCode =
@"
    // First comment.
    // Second comment.
    int x(int a)
    {
        // This is a comment.
        // And this as well.
        if (a == 1) // This also
        {
            return 0 ;
        }

        /*
            Multi line comment.
        */if(a == -5) return -10   ;

        if (a == 2)
                return 0 ;

        return 5;

    }
";

var secondCode =
@"
    // First comment.

    // Second comment.

    int x(int a)
    {

        // This is a comment.
        // And this as well.
                if    (a 
                == 1) // This also
        {
            return     0 ;
              }

        /*
            Multi line comment.
        */

        if(a == -5) return -10   ;

        if (a == 2) return 0 ;

        return 5;


    }
";

var firstMethod = CSharpSyntaxTree.ParseText(firstCode).GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First();
var secondMethod = CSharpSyntaxTree.ParseText(secondCode).GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First();

Console.WriteLine($"{firstMethod.IsEquivalentTo(secondMethod)}"); // Prints false.
Console.WriteLine($"{firstMethod.IsEquivalentToWithCommentsPreserved(secondMethod)}"); // Prints true.