232 lines
8.1 KiB
C#
232 lines
8.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax;
|
|
using Microsoft.CodeAnalysis.Syntax.InternalSyntax;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
|
|
internal static class SyntaxEquivalence
|
|
{
|
|
internal static bool AreEquivalent(SyntaxTree? before, SyntaxTree? after, Func<SyntaxKind, bool>? ignoreChildNode, bool topLevel)
|
|
{
|
|
if (before == after)
|
|
{
|
|
return true;
|
|
}
|
|
if (before == null || after == null)
|
|
{
|
|
return false;
|
|
}
|
|
return AreEquivalent(before.GetRoot(default(CancellationToken)), after.GetRoot(default(CancellationToken)), ignoreChildNode, topLevel);
|
|
}
|
|
|
|
public static bool AreEquivalent(SyntaxNode? before, SyntaxNode? after, Func<SyntaxKind, bool>? ignoreChildNode, bool topLevel)
|
|
{
|
|
if (before == null || after == null)
|
|
{
|
|
return before == after;
|
|
}
|
|
return AreEquivalentRecursive(before.Green, after.Green, ignoreChildNode, topLevel);
|
|
}
|
|
|
|
public static bool AreEquivalent(SyntaxTokenList before, SyntaxTokenList after)
|
|
{
|
|
return AreEquivalentRecursive(((SyntaxTokenList)(ref before)).Node, ((SyntaxTokenList)(ref after)).Node, null, topLevel: false);
|
|
}
|
|
|
|
public static bool AreEquivalent(SyntaxToken before, SyntaxToken after)
|
|
{
|
|
if (((SyntaxToken)(ref before)).RawKind == ((SyntaxToken)(ref after)).RawKind)
|
|
{
|
|
if (((SyntaxToken)(ref before)).Node != null)
|
|
{
|
|
return AreTokensEquivalent(((SyntaxToken)(ref before)).Node, ((SyntaxToken)(ref after)).Node, null);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static bool AreTokensEquivalent(GreenNode? before, GreenNode? after, Func<SyntaxKind, bool>? ignoreChildNode)
|
|
{
|
|
if (before == null || after == null)
|
|
{
|
|
if (before == null)
|
|
{
|
|
return after == null;
|
|
}
|
|
return false;
|
|
}
|
|
if (before.IsMissing != after.IsMissing)
|
|
{
|
|
return false;
|
|
}
|
|
switch ((SyntaxKind)(ushort)before.RawKind)
|
|
{
|
|
case SyntaxKind.IdentifierToken:
|
|
if (((SyntaxToken)(object)before).ValueText != ((SyntaxToken)(object)after).ValueText)
|
|
{
|
|
return false;
|
|
}
|
|
break;
|
|
case SyntaxKind.NumericLiteralToken:
|
|
case SyntaxKind.CharacterLiteralToken:
|
|
case SyntaxKind.StringLiteralToken:
|
|
case SyntaxKind.InterpolatedStringTextToken:
|
|
case SyntaxKind.SingleLineRawStringLiteralToken:
|
|
case SyntaxKind.MultiLineRawStringLiteralToken:
|
|
case SyntaxKind.Utf8StringLiteralToken:
|
|
case SyntaxKind.Utf8SingleLineRawStringLiteralToken:
|
|
case SyntaxKind.Utf8MultiLineRawStringLiteralToken:
|
|
if (((SyntaxToken)(object)before).Text != ((SyntaxToken)(object)after).Text)
|
|
{
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
return AreNullableDirectivesEquivalent(before, after, ignoreChildNode);
|
|
}
|
|
|
|
private static bool AreEquivalentRecursive(GreenNode? before, GreenNode? after, Func<SyntaxKind, bool>? ignoreChildNode, bool topLevel)
|
|
{
|
|
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00de: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
|
|
if (before == after)
|
|
{
|
|
return true;
|
|
}
|
|
if (before == null || after == null)
|
|
{
|
|
return false;
|
|
}
|
|
if (before.RawKind != after.RawKind)
|
|
{
|
|
return false;
|
|
}
|
|
if (before.IsToken)
|
|
{
|
|
return AreTokensEquivalent(before, after, ignoreChildNode);
|
|
}
|
|
if (topLevel)
|
|
{
|
|
SyntaxKind syntaxKind = (SyntaxKind)before.RawKind;
|
|
if (syntaxKind == SyntaxKind.Block || syntaxKind == SyntaxKind.ArrowExpressionClause)
|
|
{
|
|
return AreNullableDirectivesEquivalent(before, after, ignoreChildNode);
|
|
}
|
|
if ((ushort)before.RawKind == 8873)
|
|
{
|
|
Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.FieldDeclarationSyntax obj = (Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.FieldDeclarationSyntax)(object)before;
|
|
Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.FieldDeclarationSyntax fieldDeclarationSyntax = (Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.FieldDeclarationSyntax)(object)after;
|
|
bool num = obj.Modifiers.Any(8350);
|
|
bool flag = fieldDeclarationSyntax.Modifiers.Any(8350);
|
|
if (!num && !flag)
|
|
{
|
|
ignoreChildNode = (SyntaxKind childKind) => childKind == SyntaxKind.EqualsValueClause;
|
|
}
|
|
}
|
|
}
|
|
if (ignoreChildNode != null)
|
|
{
|
|
ChildSyntaxList val = before.ChildNodesAndTokens();
|
|
Enumerator enumerator = ((ChildSyntaxList)(ref val)).GetEnumerator();
|
|
val = after.ChildNodesAndTokens();
|
|
Enumerator enumerator2 = ((ChildSyntaxList)(ref val)).GetEnumerator();
|
|
GreenNode val2;
|
|
GreenNode val3;
|
|
do
|
|
{
|
|
val2 = null;
|
|
val3 = null;
|
|
while (((Enumerator)(ref enumerator)).MoveNext())
|
|
{
|
|
GreenNode current = ((Enumerator)(ref enumerator)).Current;
|
|
if (current != null && (current.IsToken || !ignoreChildNode((SyntaxKind)current.RawKind)))
|
|
{
|
|
val2 = current;
|
|
break;
|
|
}
|
|
}
|
|
while (((Enumerator)(ref enumerator2)).MoveNext())
|
|
{
|
|
GreenNode current2 = ((Enumerator)(ref enumerator2)).Current;
|
|
if (current2 != null && (current2.IsToken || !ignoreChildNode((SyntaxKind)current2.RawKind)))
|
|
{
|
|
val3 = current2;
|
|
break;
|
|
}
|
|
}
|
|
if (val2 == null || val3 == null)
|
|
{
|
|
return val2 == val3;
|
|
}
|
|
}
|
|
while (AreEquivalentRecursive(val2, val3, ignoreChildNode, topLevel));
|
|
return false;
|
|
}
|
|
int slotCount = before.SlotCount;
|
|
if (slotCount != after.SlotCount)
|
|
{
|
|
return false;
|
|
}
|
|
for (int num2 = 0; num2 < slotCount; num2++)
|
|
{
|
|
GreenNode slot = before.GetSlot(num2);
|
|
GreenNode slot2 = after.GetSlot(num2);
|
|
if (!AreEquivalentRecursive(slot, slot2, ignoreChildNode, topLevel))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private static bool AreNullableDirectivesEquivalent(GreenNode before, GreenNode after, Func<SyntaxKind, bool>? ignoreChildNode)
|
|
{
|
|
if (ignoreChildNode != null && ignoreChildNode(SyntaxKind.NullableDirectiveTrivia))
|
|
{
|
|
return true;
|
|
}
|
|
using (IEnumerator<Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.DirectiveTriviaSyntax> enumerator = ((Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.CSharpSyntaxNode)(object)before).GetDirectives().GetEnumerator())
|
|
{
|
|
using IEnumerator<Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.DirectiveTriviaSyntax> enumerator2 = ((Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.CSharpSyntaxNode)(object)after).GetDirectives().GetEnumerator();
|
|
Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.DirectiveTriviaSyntax directiveTriviaSyntax;
|
|
Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.DirectiveTriviaSyntax directiveTriviaSyntax2;
|
|
do
|
|
{
|
|
directiveTriviaSyntax = getNextNullableDirective(enumerator);
|
|
directiveTriviaSyntax2 = getNextNullableDirective(enumerator2);
|
|
if (directiveTriviaSyntax == null || directiveTriviaSyntax2 == null)
|
|
{
|
|
return directiveTriviaSyntax == directiveTriviaSyntax2;
|
|
}
|
|
}
|
|
while (AreEquivalentRecursive((GreenNode?)(object)directiveTriviaSyntax, (GreenNode?)(object)directiveTriviaSyntax2, ignoreChildNode, topLevel: false));
|
|
return false;
|
|
}
|
|
static Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.DirectiveTriviaSyntax? getNextNullableDirective(IEnumerator<Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.DirectiveTriviaSyntax> enumerator3)
|
|
{
|
|
while (enumerator3.MoveNext())
|
|
{
|
|
Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.DirectiveTriviaSyntax current = enumerator3.Current;
|
|
if (current.Kind == SyntaxKind.NullableDirectiveTrivia)
|
|
{
|
|
return current;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
}
|