Skip to content

C#: Add StructuralEqualityComparator to SDK#7009

Merged
knutwannheden merged 4 commits intomainfrom
add-structural-equality-comparator-to-rewrite-csharp
Mar 17, 2026
Merged

C#: Add StructuralEqualityComparator to SDK#7009
knutwannheden merged 4 commits intomainfrom
add-structural-equality-comparator-to-rewrite-csharp

Conversation

@knutwannheden
Copy link
Contributor

Summary

  • Add StructuralEqualityComparator — a public static class for comparing two J (LST) nodes for structural equality, ignoring whitespace, formatting, node IDs, and type attribution
  • Consolidate shared reflection helpers (HasNullSafe, IsRightPadded, IsLeftPadded, IsContainer) from PatternMatchingComparator into TreeHelper, eliminating duplication
  • Cache PropertyInfo lookups in TreeHelper.UnwrapPadded and GetContainerElements for better hot-path performance

Motivation

Recipe authors in recipes-csharp need to compare AST subtrees for structural equality (e.g., checking if both sides of x ?? x are identical, or if if/else branches match). The existing PatternMatchingComparator handles this internally but is internal and carries capture/placeholder/variadic overhead not needed for simple equality checks.

Usage

// Instead of fragile string comparison:
// binary.Left.ToString().Trim() == binary.Right.ToString().Trim()

// Use structural equality:
StructuralEqualityComparator.AreStructurallyEqual(binary.Left, binary.Right)

Test plan

  • 20 xUnit tests covering: identical/different literals, binary expressions, operators, identifiers, whitespace insensitivity, nested expressions, method invocations, string literals, same reference, boolean/null literals, different argument counts, NullSafe vs regular access
  • All existing C# module tests pass (no regressions)

Provides a public static method for comparing two J (LST) nodes for
structural equality, ignoring whitespace, formatting, markers, node IDs,
and type attribution. Reuses TreeHelper from the pattern matching engine.
Move HasNullSafe, IsRightPadded, IsLeftPadded, IsContainer to TreeHelper
to eliminate duplication between StructuralEqualityComparator and
PatternMatchingComparator. Cache PropertyInfo lookups in UnwrapPadded and
GetContainerElements. Optimize generic type dispatch in CompareValues to
call GetType() once per value instead of up to three times.
Update class summary to note that most markers are ignored but
semantic markers like NullSafe (distinguishing ?. from .) are
explicitly compared.
@github-project-automation github-project-automation bot moved this to In Progress in OpenRewrite Mar 17, 2026
@knutwannheden knutwannheden changed the title C#: Add StructuralEqualityComparator to SDK C#: Add StructuralEqualityComparator to SDK Mar 17, 2026
@knutwannheden knutwannheden merged commit 6758868 into main Mar 17, 2026
1 check failed
@knutwannheden knutwannheden deleted the add-structural-equality-comparator-to-rewrite-csharp branch March 17, 2026 17:39
@github-project-automation github-project-automation bot moved this from In Progress to Done in OpenRewrite Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant