Search code examples
c#roslynvisual-studio-extensionsmicrosoft.codeanalysis

What is a PatternSyntax in Roslyn


This seems a fairly stupid question and I'm not sure it is suitable for StackOverflow.

A user of my tool has reported an error with the message

Unable to cast object of type
'Microsoft.CodeAnalysis.CSharp.Syntax.LiteralExpressionSyntax' to type
'Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax'.

I don't know exactly what his code looks like (at least not yet). I might be able to reproduce the error if I could write some code containing a PatternSyntax.

My problem is, that I haven't a clue what language construct in C# generates a syntax node of type PatternSyntax.

Can anybody help me with an example?


Solution

  • I believe it's part of the syntax generated from Pattern Matching. The spec for this feature describes the grammar along with some more examples.

    PatternSyntax is defined here: http://sourceroslyn.io/Microsoft.CodeAnalysis.CSharp/Generated/Syntax.xml.Internal.Generated.cs.html#b554fa43e6090c28

    The following inherit from PatternSyntax

    DiscardPatternSyntax
    DeclarationPatternSyntax
    VarPatternSyntax
    RecursivePatternSyntax
    ConstantPatternSyntax
    

    I believe one example of VarPatternSyntax is var o in the following:

    static object CreateShape(string shapeDescription)
    {
        switch (shapeDescription)
        {
            case var o when (o?.Trim().Length ?? 0) == 0:
                // white space
                return null;
            default:
                return "invalid shape description";
        }            
    }
    

    We can take the above code and feed it into RoslynQuoter to see how to generate it and it would look something like:

    CasePatternSwitchLabel(
                VarPattern(
                    SingleVariableDesignation(
                        Identifier("o"))),
                Token(SyntaxKind.ColonToken))
            .WithWhenClause(
                WhenClause(
                    BinaryExpression(
                        SyntaxKind.EqualsExpression,
                        ParenthesizedExpression(
                            BinaryExpression(
                                SyntaxKind.CoalesceExpression,
                                ConditionalAccessExpression(
                                    IdentifierName("o"),
                                    MemberAccessExpression(
                                        SyntaxKind.SimpleMemberAccessExpression,
                                        InvocationExpression(
                                            MemberBindingExpression(
                                                IdentifierName("Trim"))),
                                        IdentifierName("Length"))),
                                LiteralExpression(
                                    SyntaxKind.NumericLiteralExpression,
                                    Literal(0)))),
                        LiteralExpression(
                            SyntaxKind.NumericLiteralExpression,
                            Literal(0)))))))