Skip to content

C#: Add semantic matching to pattern comparator#7069

Merged
knutwannheden merged 4 commits intomainfrom
rosy-robin
Mar 20, 2026
Merged

C#: Add semantic matching to pattern comparator#7069
knutwannheden merged 4 commits intomainfrom
rosy-robin

Conversation

@knutwannheden
Copy link
Contributor

Summary

  • Static method/field matching: Math.Abs(x) matches Abs(x) via using static, and vice versa — compares MethodType.DeclaringType FQN instead of receiver syntax when the method is static. Same for static fields (Math.PIPI)
  • Type reference matching: Console matches System.Console when both resolve to the same JavaType.FullyQualified
  • Using alias matching: Con.WriteLine() matches Console.WriteLine() when using Con = System.Console — works automatically via Roslyn's alias resolution into canonical FQNs
  • Implicit this matching: Foo() matches this.Foo() for instance methods
  • Bug fix: JavaType.Variable.FlagsBitMap was not populated in CSharpTypeMapping.MapVariable — now calls MapFlags(symbol) so static/public/etc. flags are set
  • Template engine: Scaffold now creates a SemanticModel when usings are provided, enabling type attribution on pattern trees

Test plan

  • 10 new tests covering all semantic matching scenarios (static methods both directions, static fields both directions, instance method negative case, type references, using aliases both directions, implicit this both directions)
  • All 1467 existing C# tests pass — no regressions

…d type references

Enable type-aware pattern matching that matches across syntactic forms when
both sides resolve to the same symbol:

- Static method invocations: Math.Abs(x) matches Abs(x) via using static
  when both have the same MethodType declaring type
- Static fields: Math.PI matches PI via using static when both reference
  the same Variable with the same owner
- Type references: Console matches System.Console when both resolve to
  the same FullyQualified type

Also fixes Variable.FlagsBitMap not being populated in CSharpTypeMapping,
and enables semantic model creation for template scaffolds when usings
are provided.
…ching

- Implicit this: Foo() matches this.Foo() and vice versa — when one
  MethodInvocation has no Select and the other's Select is "this",
  skip receiver comparison and match by name + arguments
- Using aliases: Con.WriteLine() matches Console.WriteLine() when
  using Con = System.Console — this works automatically through the
  existing static method MethodType.DeclaringType comparison since
  Roslyn resolves aliases to canonical FQNs
- Compare TypeParameters in both semantic method invocation paths
  (static match and implicit-this) to prevent false matches on
  generic methods like Max<int>() vs Max<double>()
- Check IsStatic on both sides in MatchFieldAccessToIdentifier
  for defensive correctness
…claring types

- Use typed capture in InstanceMethodWithReceiverDoesNotMatchWithoutReceiver
  test so both sides get MethodType attribution, proving the IsStatic guard
  is load-bearing (red-green verified)
- Unwrap JavaType.Parameterized when comparing declaring type FQNs — generic
  types like List<int> have Parameterized declaring types that need unwrapping
  to get the underlying Class FQN
@knutwannheden knutwannheden merged commit 1aa3ad1 into main Mar 20, 2026
1 check passed
@knutwannheden knutwannheden deleted the rosy-robin branch March 20, 2026 07:53
@github-project-automation github-project-automation bot moved this from In Progress to Done in OpenRewrite Mar 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant