Skip to main content
Replace verbose if-statements with composable matchers for symbols and invocations.

Match.* (Symbol Matching)

Fluent matching for ISymbol types:
// Method matching
Match.Method()
    .Named("Execute")
    .Async()
    .ReturningTask()
    .WithCancellationToken()
    .Public()
    .Matches(method);

// Match multiple attributes (any match)
Match.Method()
    .WithAttribute("Xunit.FactAttribute", "Xunit.TheoryAttribute", "NUnit.Framework.TestAttribute")
    .Public()
    .Matches(method);

// Finalizer matching
Match.Method().Finalizer().Matches(method);

// Type matching
Match.Type()
    .Class()
    .Public()
    .Implements("IDisposable")
    .HasParameterlessConstructor()
    .Matches(type);

// Property/Field/Parameter matching
Match.Property().ReadOnly().Required().Matches(prop);
Match.Field().Const().Public().Matches(field);
Match.Parameter().CancellationToken().Matches(param);
Matchers mutate this when chaining. Create new matchers for each distinct pattern.

Factory Pattern

For reusable base matchers:
static MethodMatcher PublicInstance() => Match.Method().Public().NotStatic();

var asyncApi = PublicInstance().Async().ReturningTask();
var syncApi = PublicInstance().NotAsync().ReturningVoid();

Method Matcher

Match.Method()
    .Named("name")              // Exact name
    .NameStartsWith("Get")      // Name prefix
    .NameEndsWith("Async")      // Name suffix
    .Async()                    // async keyword
    .NotAsync()                 // Not async
    .ReturningTask()            // Returns Task/ValueTask
    .ReturningVoid()            // Returns void
    .WithParameters(2)          // Exact parameter count
    .WithCancellationToken()    // Has CancellationToken param
    .Public() / .Private() / .Internal() / .Protected()
    .Static() / .NotStatic()
    .Virtual() / .Override() / .Abstract()
    .Constructor()              // Is constructor
    .Finalizer()                // Is finalizer (~ClassName)
    .WithAttribute("AttrName")  // Has attribute
    .WithAttribute("A", "B")    // Has any of these attributes
    .Matches(method);

Type Matcher

Match.Type()
    .Class() / .Struct() / .Interface() / .Record() / .Enum()
    .Public() / .Internal()
    .Sealed() / .Abstract() / .Static()
    .Partial()
    .Generic() / .NotGeneric()
    .Implements("IDisposable")
    .InheritsFrom("BaseClass")
    .InNamespace("MyNamespace")
    .HasParameterlessConstructor()
    .HasMethod("Dispose")
    .HasProperty("Id")
    .Nested() / .TopLevel()
    .WithAttribute("AttrName")
    .Matches(type);

Invoke.* (Invocation Matching)

Match IInvocationOperation:
// Match specific method
Invoke.Method("Dispose")
    .OnTypeImplementing("IDisposable")
    .WithNoArguments()
    .Matches(invocation);

// LINQ methods
Invoke.Method()
    .Linq()                     // System.Linq extensions
    .Named("Where")
    .Matches(invocation);

// Match multiple method names (any match)
Invoke.Method("WriteLine", "Write")
    .OnConsole()
    .Matches(invocation);

// Match multiple receiver types (any match)
Invoke.Method("Wait", "GetAwaiter")
    .OnType("Task", "ValueTask")
    .Matches(invocation);

Invocation Matcher

Invoke.Method()
    .Named("name")              // Exact name
    .Named("A", "B", "C")       // Any of these names
    .NameStartsWith("Get")
    .NameEndsWith("Async")
    .OnType("TypeName")         // Receiver type name
    .OnType("A", "B")           // Any of these types
    .OnTypeInheritingFrom("Base")
    .OnTypeImplementing("IFace")
    .Extension() / .NotExtension()
    .Static() / .Instance()
    .Async()
    .Generic()
    .ReturningVoid() / .ReturningTask() / .Returning("Type")
    .WithArguments(2)           // Exact argument count
    .WithNoArguments()
    .WithMinArguments(1)
    .WithConstantArg(0)
    .WithConstantStringArg(0)
    .WithNullArg(0)
    .WithAllConstantArgs()
    .InNamespace("System.Linq")
    .InNamespaceStartingWith("System")
    .Linq()                     // Shortcut for System.Linq extensions
    .OnString()                 // Shortcut for String receiver
    .OnTask()                   // Shortcut for Task receiver
    .OnConsole()                // Shortcut for Console receiver
    .Where(custom => ...)       // Custom predicate
    .Matches(invocation);

Examples

Test Method Detection

var isTestMethod = Match.Method()
    .WithAttribute(
        "Xunit.FactAttribute",
        "Xunit.TheoryAttribute",
        "NUnit.Framework.TestAttribute",
        "Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute")
    .Public()
    .Matches(method);

Async Handler Detection

var isAsyncHandler = Match.Method()
    .Async()
    .Public()
    .ReturningTask()
    .WithCancellationToken()
    .NotStatic()
    .Matches(method);

Dispose Call Detection

var isDisposeCall = Invoke.Method("Dispose", "DisposeAsync")
    .OnTypeImplementing("IDisposable")
    .WithNoArguments()
    .Matches(invocation);

LINQ Query Detection

var isLinqQuery = Invoke.Method()
    .Linq()
    .Named("Where", "Select", "FirstOrDefault", "Any", "All")
    .Matches(invocation);