Files

232 lines
8.1 KiB
C#
Raw Permalink Normal View History

2026-08-27 10:56:38 -06:00
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;
}
}
}