diff --git a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs index efbe43fe4cf707bab6db2397ea2c2706f1abe7a2..2edb9e10f67245a49e1f6dcedbd63db2fdc2cf43 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/Expression.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/Expression.cs @@ -69,26 +69,6 @@ internal partial class BoundQueryClause protected override ImmutableArray Children => ImmutableArray.Create(this.Value); } - internal partial class BoundPattern - { - protected override abstract ImmutableArray Children { get; } - } - - internal partial class BoundDeclarationPattern - { - protected override ImmutableArray Children => ImmutableArray.Create(this.VariableAccess); - } - - internal partial class BoundConstantPattern - { - protected override ImmutableArray Children => ImmutableArray.Create(this.Value); - } - - internal partial class BoundWildcardPattern - { - protected override ImmutableArray Children => ImmutableArray.Empty; - } - internal partial class BoundArgListOperator { protected override ImmutableArray Children => StaticCast.From(this.Arguments); @@ -173,9 +153,4 @@ partial class BoundThrowExpression { protected override ImmutableArray Children => ImmutableArray.Create(this.Expression); } - - partial class BoundIsPatternExpression - { - protected override ImmutableArray Children => ImmutableArray.Create(this.Expression, this.Pattern); - } } diff --git a/src/Compilers/CSharp/Portable/BoundTree/Statement.cs b/src/Compilers/CSharp/Portable/BoundTree/Statement.cs index 7c2cf875708267b6188f141fbe47083111724ff5..2252529e8fe412afcce6c9e20b488ae2b930000c 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/Statement.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/Statement.cs @@ -25,19 +25,4 @@ partial class BoundLocalFunctionStatement { protected override ImmutableArray Children => ImmutableArray.Create(this.Body); } - - partial class BoundPatternSwitchStatement - { - protected override ImmutableArray Children => StaticCast.From(this.SwitchSections).Insert(0, this.Expression); - } - - partial class BoundPatternSwitchSection - { - protected override ImmutableArray Children => StaticCast.From(this.SwitchLabels).AddRange(this.Statements); - } - - partial class BoundPatternSwitchLabel - { - protected override ImmutableArray Children => ImmutableArray.Create(this.Pattern, this.Guard); - } } diff --git a/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj b/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj index 438b3b4051ce3c10934b8a93fa9ee710f928b919..db1e154ecdcf1291406ad4c66089fa05bc6c4409 100644 --- a/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj +++ b/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj @@ -291,9 +291,7 @@ - - Code - + diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs index 30bbc28c326aefa4bb5160f5146d43b2f65376a9..9fa7c48747ee9e02af79adcba1a0aad290530580 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs @@ -179,6 +179,18 @@ private IOperation CreateInternal(BoundNode boundNode) return CreateBoundInterpolationOperation((BoundStringInsert)boundNode); case BoundKind.LocalFunctionStatement: return CreateBoundLocalFunctionStatementOperation((BoundLocalFunctionStatement)boundNode); + case BoundKind.ConstantPattern: + return CreateBoundConstantPatternOperation((BoundConstantPattern)boundNode); + case BoundKind.DeclarationPattern: + return CreateBoundDeclarationPatternOperation((BoundDeclarationPattern)boundNode); + case BoundKind.WildcardPattern: + return null; + case BoundKind.PatternSwitchStatement: + return CreateBoundPatternSwitchStatementOperation((BoundPatternSwitchStatement)boundNode); + case BoundKind.PatternSwitchLabel: + return CreateBoundPatternSwitchLabelOperation((BoundPatternSwitchLabel)boundNode); + case BoundKind.IsPatternExpression: + return CreateBoundIsPatternExpressionOperation((BoundIsPatternExpression)boundNode); default: var constantValue = ConvertToOptional((boundNode as BoundExpression)?.ConstantValue); return Operation.CreateOperationNone(boundNode.HasErrors, boundNode.Syntax, constantValue, getChildren: () => GetIOperationChildren(boundNode)); @@ -1099,5 +1111,59 @@ private IInterpolatedStringText CreateBoundInterpolatedStringTextOperation(Bound Optional constantValue = default(Optional); return new LazyInterpolatedStringText(text, isInvalid, syntax, type, constantValue); } + + private IConstantPattern CreateBoundConstantPatternOperation(BoundConstantPattern boundConstantPattern) + { + Lazy value = new Lazy(() => Create(boundConstantPattern.Value)); + bool isInvalid = boundConstantPattern.HasErrors; + SyntaxNode syntax = boundConstantPattern.Syntax; + ITypeSymbol type = null; + Optional constantValue = default(Optional); + return new LazyConstantPattern(value, isInvalid, syntax, type, constantValue); + } + + private IDeclarationPattern CreateBoundDeclarationPatternOperation(BoundDeclarationPattern boundDeclarationPattern) + { + ISymbol variable = boundDeclarationPattern.Variable; + bool isInvalid = boundDeclarationPattern.HasErrors; + SyntaxNode syntax = boundDeclarationPattern.Syntax; + ITypeSymbol type = null; + Optional constantValue = default(Optional); + return new DeclarationPattern(variable, isInvalid, syntax, type, constantValue); + } + + private ISwitchStatement CreateBoundPatternSwitchStatementOperation(BoundPatternSwitchStatement boundPatternSwitchStatement) + { + Lazy value = new Lazy(() => Create(boundPatternSwitchStatement.Expression)); + Lazy> cases = new Lazy>(() => GetPatternSwitchStatementCases(boundPatternSwitchStatement)); + bool isInvalid = boundPatternSwitchStatement.HasErrors; + SyntaxNode syntax = boundPatternSwitchStatement.Syntax; + ITypeSymbol type = null; + Optional constantValue = default(Optional); + return new LazySwitchStatement(value, cases, isInvalid, syntax, type, constantValue); + } + + private IPatternCaseClause CreateBoundPatternSwitchLabelOperation(BoundPatternSwitchLabel boundPatternSwitchLabel) + { + LabelSymbol label = boundPatternSwitchLabel.Label; + Lazy pattern = new Lazy(() => (IPattern)Create(boundPatternSwitchLabel.Pattern)); + Lazy guardExpression = new Lazy(() => Create(boundPatternSwitchLabel.Guard)); + bool isInvalid = boundPatternSwitchLabel.HasErrors; + SyntaxNode syntax = boundPatternSwitchLabel.Syntax; + ITypeSymbol type = null; + Optional constantValue = default(Optional); + return new LazyPatternCaseClause(label, pattern, guardExpression, isInvalid, syntax, type, constantValue); + } + + private IIsPatternExpression CreateBoundIsPatternExpressionOperation(BoundIsPatternExpression boundIsPatternExpression) + { + Lazy expression = new Lazy(() => Create(boundIsPatternExpression.Expression)); + Lazy pattern = new Lazy(() => (IPattern)Create(boundIsPatternExpression.Pattern)); + bool isInvalid = boundIsPatternExpression.HasErrors; + SyntaxNode syntax = boundIsPatternExpression.Syntax; + ITypeSymbol type = boundIsPatternExpression.Type; + Optional constantValue = ConvertToOptional(boundIsPatternExpression.ConstantValue); + return new LazyIsPatternExpression(expression, pattern, isInvalid, syntax, type, constantValue); + } } } diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs index 403e3490830988bf5e7c2b5bc618056a7a76ec6a..0df7c7a28ca1ec1427d199548da3393188b11deb 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory_Methods.cs @@ -166,6 +166,17 @@ private ImmutableArray GetSwitchStatementCases(BoundSwitchStatement }); } + private ImmutableArray GetPatternSwitchStatementCases(BoundPatternSwitchStatement statement) + { + return statement.SwitchSections.SelectAsArray(switchSection => + { + var clauses = switchSection.SwitchLabels.SelectAsArray(s => (ICaseClause)Create(s)); + var body = switchSection.Statements.SelectAsArray(s => Create(s)); + + return (ISwitchCase)new SwitchCase(clauses, body, switchSection.HasErrors, switchSection.Syntax, type: null, constantValue: default(Optional)); + }); + } + private static BinaryOperationKind GetLabelEqualityKind(BoundSwitchLabel label) { BoundExpression caseValue = label.ExpressionOpt; diff --git a/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj b/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj index dca2b740f036412d70adc99e7af9e0a03bef4d3d..83b99bf7132f534f2a3c0619ff75ee7f911fa083 100644 --- a/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj +++ b/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj @@ -66,7 +66,9 @@ + + diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IIfStatement.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IIfStatement.cs index af42e20fa9938eba1868b38073c9e30f59f0ff32..44d2562682b1e035c36f77c03841319f291e6fc8 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IIfStatement.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IIfStatement.cs @@ -487,10 +487,9 @@ private static void A(bool flag, int number) IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'A(o is int i, 1);') IInvocationExpression (static void Program.A(System.Boolean flag, System.Int32 number)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'A(o is int i, 1)') Arguments(2): IArgument (ArgumentKind.Explicit, Matching Parameter: flag) (OperationKind.Argument) (Syntax: 'o is int i') - IOperation: (OperationKind.None) (Syntax: 'o is int i') - Children(2): ILocalReferenceExpression: o (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'o') - IOperation: (OperationKind.None) (Syntax: 'int i') - Children(1): ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'int i') + IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'o is int i') + Expression: ILocalReferenceExpression: o (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'o') + Pattern: IDeclarationPattern (Declared Symbol: System.Int32 i) (OperationKind.DeclarationPattern) (Syntax: 'int i') IArgument (ArgumentKind.Explicit, Matching Parameter: number) (OperationKind.Argument) (Syntax: '1') ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') "; @@ -520,10 +519,9 @@ private void M() "; string expectedOperationTree = @" IIfStatement (OperationKind.IfStatement) (Syntax: 'if (obj is ... }') - Condition: IOperation: (OperationKind.None) (Syntax: 'obj is string str') - Children(2): ILocalReferenceExpression: obj (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'obj') - IOperation: (OperationKind.None) (Syntax: 'string str') - Children(1): ILocalReferenceExpression: str (OperationKind.LocalReferenceExpression, Type: System.String) (Syntax: 'string str') + Condition: IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'obj is string str') + Expression: ILocalReferenceExpression: obj (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'obj') + Pattern: IDeclarationPattern (Declared Symbol: System.String str) (OperationKind.DeclarationPattern) (Syntax: 'string str') IfTrue: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.WriteLine(str);') IInvocationExpression (static void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.WriteLine(str)') @@ -601,10 +599,9 @@ private static void A(bool flag, int number) IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'A(o is int i, 1);') IInvocationExpression (static void Program.A(System.Boolean flag, System.Int32 number)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'A(o is int i, 1)') Arguments(2): IArgument (ArgumentKind.Explicit, Matching Parameter: flag) (OperationKind.Argument) (Syntax: 'o is int i') - IOperation: (OperationKind.None) (Syntax: 'o is int i') - Children(2): ILocalReferenceExpression: o (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'o') - IOperation: (OperationKind.None) (Syntax: 'int i') - Children(1): ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'int i') + IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'o is int i') + Expression: ILocalReferenceExpression: o (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'o') + Pattern: IDeclarationPattern (Declared Symbol: System.Int32 i) (OperationKind.DeclarationPattern) (Syntax: 'int i') IArgument (ArgumentKind.Explicit, Matching Parameter: number) (OperationKind.Argument) (Syntax: '1') ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') "; @@ -635,10 +632,9 @@ private void M() "; string expectedOperationTree = @" IIfStatement (OperationKind.IfStatement, IsInvalid) (Syntax: 'if (obj is ... else') - Condition: IOperation: (OperationKind.None) (Syntax: 'obj is string str') - Children(2): ILocalReferenceExpression: obj (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'obj') - IOperation: (OperationKind.None) (Syntax: 'string str') - Children(1): ILocalReferenceExpression: str (OperationKind.LocalReferenceExpression, Type: System.String) (Syntax: 'string str') + Condition: IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'obj is string str') + Expression: ILocalReferenceExpression: obj (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'obj') + Pattern: IDeclarationPattern (Declared Symbol: System.String str) (OperationKind.DeclarationPattern) (Syntax: 'string str') IfTrue: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.WriteLine(str);') IInvocationExpression (static void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.WriteLine(str)') diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IIsPatternExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IIsPatternExpression.cs new file mode 100644 index 0000000000000000000000000000000000000000..64a5636b8e69eff13161fd5f5bb3b3a0b9262f1d --- /dev/null +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IIsPatternExpression.cs @@ -0,0 +1,480 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public partial class IOperationTests : SemanticModelTestBase + { + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_VarPatternDeclaration() + { + string source = @" +using System; +class X +{ + void M() + { + int? x = 12; + if (/**/x is var y/**/) Console.WriteLine(y); + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'x is var y') + Expression: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32?) (Syntax: 'x') + Pattern: IDeclarationPattern (Declared Symbol: System.Int32? y) (OperationKind.DeclarationPattern) (Syntax: 'var y') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_PrimitiveTypePatternDeclaration() + { + string source = @" +using System; +class X +{ + void M() + { + int? x = 12; + if (/**/x is int y/**/) Console.WriteLine(y); + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'x is int y') + Expression: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32?) (Syntax: 'x') + Pattern: IDeclarationPattern (Declared Symbol: System.Int32 y) (OperationKind.DeclarationPattern) (Syntax: 'int y') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_ReferenceTypePatternDeclaration() + { + string source = @" +using System; +class X +{ + void M(X x) + { + if (/**/x is X y/**/) Console.WriteLine(y); + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'x is X y') + Expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: X) (Syntax: 'x') + Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_TypeParameterTypePatternDeclaration() + { + string source = @" +using System; +class X +{ + void M(T x) where T: class + { + if (/**/x is T y/**/) Console.WriteLine(y); + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'x is T y') + Expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: T) (Syntax: 'x') + Pattern: IDeclarationPattern (Declared Symbol: T y) (OperationKind.DeclarationPattern) (Syntax: 'T y') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_DynamicTypePatternDeclaration() + { + string source = @" +using System; +class X +{ + void M(X x) + { + if (/**/x is dynamic y/**/) Console.WriteLine(y); + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean, IsInvalid) (Syntax: 'x is dynamic y') + Expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: X) (Syntax: 'x') + Pattern: IDeclarationPattern (Declared Symbol: dynamic y) (OperationKind.DeclarationPattern, IsInvalid) (Syntax: 'dynamic y') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS8208: It is not legal to use the type 'dynamic' in a pattern. + // if (/**/x is dynamic y/**/) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_PatternDynamicType, "dynamic").WithLocation(7, 28) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_ConstantPattern() + { + string source = @" +using System; +class X +{ + void M() + { + int? x = 12, y = 12; + if (/**/x is 12/**/) Console.WriteLine(y); + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'x is 12') + Expression: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32?) (Syntax: 'x') + Pattern: IConstantPattern (OperationKind.ConstantPattern) (Syntax: '12') + Value: ILiteralExpression (Text: 12) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 12) (Syntax: '12') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_ConstantPatternWithConversion() + { + string source = @" +using System; +class X +{ + void M() + { + int? x = 12, y = 12; + if (/**/x is (int)12.0/**/) Console.WriteLine(y); + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'x is (int)12.0') + Expression: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32?) (Syntax: 'x') + Pattern: IConstantPattern (OperationKind.ConstantPattern) (Syntax: '(int)12.0') + Value: IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: System.Int32, Constant: 12) (Syntax: '(int)12.0') + ILiteralExpression (OperationKind.LiteralExpression, Type: System.Double, Constant: 12) (Syntax: '12.0') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_ConstantPatternWithNoImplicitConversion() + { + string source = @" +using System; +class X +{ + void M() + { + int? x = 12, y = 12; + if (/**/x is 12.0/**/) Console.WriteLine(y); + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'x is 12.0') + Expression: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32?) (Syntax: 'x') + Pattern: IConstantPattern (OperationKind.ConstantPattern) (Syntax: '12.0') + Value: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int32, Constant: 12) (Syntax: '12.0') + ILiteralExpression (OperationKind.LiteralExpression, Type: System.Double, Constant: 12) (Syntax: '12.0') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS0266: Cannot implicitly convert type 'double' to 'int?'. An explicit conversion exists (are you missing a cast?) + // if (/**/x is 12.0/**/) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "12.0").WithArguments("double", "int?").WithLocation(8, 28) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_ConstantPatternWithNoConversion() + { + string source = @" +using System; +class X +{ + void M() + { + int x = 12, y = 12; + if (/**/x is null/**/) Console.WriteLine(y); + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean, IsInvalid) (Syntax: 'x is null') + Expression: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'x') + Pattern: IConstantPattern (OperationKind.ConstantPattern, IsInvalid) (Syntax: 'null') + Value: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Int32, IsInvalid) (Syntax: 'null') + ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS0037: Cannot convert null to 'int' because it is a non-nullable value type + // if (/**/x is null/**/) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_ValueCantBeNull, "null").WithArguments("int").WithLocation(8, 28) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_UndefinedTypeInPatternDeclaration() + { + string source = @" +using System; +class X +{ + void M() + { + int? x = 12; + if (/**/x is UndefinedType y/**/) Console.WriteLine(y); + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean, IsInvalid) (Syntax: 'x is UndefinedType y') + Expression: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32?) (Syntax: 'x') + Pattern: IDeclarationPattern (Declared Symbol: UndefinedType y) (OperationKind.DeclarationPattern, IsInvalid) (Syntax: 'UndefinedType y') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS0246: The type or namespace name 'UndefinedType' could not be found (are you missing a using directive or an assembly reference?) + // if (/**/x is UndefinedType y/**/) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "UndefinedType").WithArguments("UndefinedType").WithLocation(8, 28) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_NonConstantExpressionInsteadOfPatternDeclaration() + { + string source = @" +using System; +class X +{ + void M() + { + int? x = 12, y = 12; + if (/**/x is y/**/) Console.WriteLine(y); + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean, IsInvalid) (Syntax: 'x is y') + Expression: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32?) (Syntax: 'x') + Pattern: IConstantPattern (OperationKind.ConstantPattern, IsInvalid) (Syntax: 'y') + Value: ILocalReferenceExpression: y (OperationKind.LocalReferenceExpression, Type: System.Int32?) (Syntax: 'y') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS0150: A constant value is expected + // if (/**/x is y/**/) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_ConstantExpected, "y").WithLocation(8, 28) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_InvalidTypeInPatternDeclaration() + { + string source = @" +using System; +class X +{ + void M() + { + int? x = 12; + if (/**/x is X y/**/) Console.WriteLine(y); + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean, IsInvalid) (Syntax: 'x is X y') + Expression: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32?) (Syntax: 'x') + Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern, IsInvalid) (Syntax: 'X y') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS8121: An expression of type 'int?' cannot be handled by a pattern of type 'X'. + // if (/**/x is X y/**/) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_PatternWrongType, "X").WithArguments("int?", "X").WithLocation(8, 28) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_DuplicateLocalInPatternDeclaration() + { + string source = @" +using System; +class X +{ + void M() + { + int? x = 12, y = 12; + if (/**/x is int y/**/) Console.WriteLine(y); + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean, IsInvalid) (Syntax: 'x is int y') + Expression: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32?) (Syntax: 'x') + Pattern: IDeclarationPattern (Declared Symbol: System.Int32 y) (OperationKind.DeclarationPattern, IsInvalid) (Syntax: 'int y') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS0128: A local variable or function named 'y' is already defined in this scope + // if (/**/x is int y/**/) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_LocalDuplicate, "y").WithArguments("y").WithLocation(8, 32) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_InvalidMultipleLocalsInPatternDeclaration() + { + string source = @" +using System; +class X +{ + void M() + { + int? x = 12, y = 12; + if (/**/x is int y2/**/, y3) Console.WriteLine(y); + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'x is int y2') + Expression: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32?) (Syntax: 'x') + Pattern: IDeclarationPattern (Declared Symbol: System.Int32 y2) (OperationKind.DeclarationPattern) (Syntax: 'int y2') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS1026: ) expected + // if (/**/x is int y2/**/, y3) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_CloseParenExpected, ",").WithLocation(8, 45), + // CS1525: Invalid expression term ',' + // if (/**/x is int y2/**/, y3) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ",").WithArguments(",").WithLocation(8, 45), + // CS1002: ; expected + // if (/**/x is int y2/**/, y3) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_SemicolonExpected, ",").WithLocation(8, 45), + // CS1513: } expected + // if (/**/x is int y2/**/, y3) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_RbraceExpected, ",").WithLocation(8, 45), + // CS1002: ; expected + // if (/**/x is int y2/**/, y3) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_SemicolonExpected, ")").WithLocation(8, 49), + // CS1513: } expected + // if (/**/x is int y2/**/, y3) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_RbraceExpected, ")").WithLocation(8, 49), + // CS0103: The name 'y3' does not exist in the current context + // if (/**/x is int y2/**/, y3) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_NameNotInContext, "y3").WithArguments("y3").WithLocation(8, 47) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_InvalidConstDeclarationInPatternDeclaration() + { + string source = @" +using System; +class X +{ + void M() + { + int x = 12; + if (/**/x is /**/const int y) Console.WriteLine(y); + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean, IsInvalid) (Syntax: 'x is /**/') + Expression: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'x') + Pattern: IConstantPattern (OperationKind.ConstantPattern, IsInvalid) (Syntax: '') + Value: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Int32, IsInvalid) (Syntax: '') + IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS1525: Invalid expression term 'const' + // if (/**/x is /**/const int y) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "const").WithArguments("const").WithLocation(8, 39), + // CS1026: ) expected + // if (/**/x is /**/const int y) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_CloseParenExpected, "const").WithLocation(8, 39), + // CS1023: Embedded statement cannot be a declaration or labeled statement + // if (/**/x is /**/const int y) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "const int y").WithLocation(8, 39), + // CS0145: A const field requires a value to be provided + // if (/**/x is /**/const int y) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_ConstValueRequired, "y").WithLocation(8, 49), + // CS1002: ; expected + // if (/**/x is /**/const int y) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_SemicolonExpected, ")").WithLocation(8, 50), + // CS1513: } expected + // if (/**/x is /**/const int y) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_RbraceExpected, ")").WithLocation(8, 50), + // CS0103: The name 'y' does not exist in the current context + // if (/**/x is /**/const int y) Console.WriteLine(y); + Diagnostic(ErrorCode.ERR_NameNotInContext, "y").WithArguments("y").WithLocation(8, 70), + // CS0168: The variable 'y' is declared but never used + // if (/**/x is /**/const int y) Console.WriteLine(y); + Diagnostic(ErrorCode.WRN_UnreferencedVar, "y").WithArguments("y").WithLocation(8, 49) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestIsPatternExpression_InvalidInDefaultParameterInitializer() + { + string source = @" +using System; +class X +{ + void M(string x = /**/string.Empty is string y/**/) + { + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'string.Empty is string y') + Expression: IFieldReferenceExpression: System.String System.String.Empty (Static) (OperationKind.FieldReferenceExpression, Type: System.String) (Syntax: 'string.Empty') + Pattern: IDeclarationPattern (Declared Symbol: System.String y) (OperationKind.DeclarationPattern) (Syntax: 'string y') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS1736: Default parameter value for 'x' must be a compile-time constant + // void M(string x = /**/string.Empty is string y/**/) + Diagnostic(ErrorCode.ERR_DefaultValueMustBeConstant, "string.Empty is string y").WithArguments("x").WithLocation(5, 33) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + } +} \ No newline at end of file diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs index ca42fba283277ce8e8a37e4aa4e0672a6999ac49..c8eb9760ebb68ae2aa62aecf4e9bcc3b78439c12 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs @@ -657,16 +657,15 @@ public void M(int x) } "; string expectedOperationTree = @" -IOperation: (OperationKind.None) (Syntax: 'switch (x) ... }') - Children(2): IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') - IOperation: (OperationKind.None) (Syntax: 'case var y ... break;') - Children(2): IOperation: (OperationKind.None) (Syntax: 'case var y ... (x >= 10):') - Children(2): IOperation: (OperationKind.None) (Syntax: 'var y') - Children(1): ILocalReferenceExpression: y (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'var y') - IBinaryOperatorExpression (BinaryOperationKind.IntegerGreaterThanOrEqual) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'x >= 10') - Left: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') - Right: ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +ISwitchStatement (1 cases) (OperationKind.SwitchStatement) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case var y ... break;') + Clauses: IPatternCaseClause (Label Symbol: case var y when (x >= 10):) (OperationKind.PatternCaseClause) (Syntax: 'case var y ... (x >= 10):') + Pattern: IDeclarationPattern (Declared Symbol: System.Int32 y) (OperationKind.DeclarationPattern) (Syntax: 'var y') + Guard Expression: IBinaryOperatorExpression (BinaryOperationKind.IntegerGreaterThanOrEqual) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'x >= 10') + Left: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') + Right: ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -693,20 +692,18 @@ public void M(int x) } "; string expectedOperationTree = @" -IOperation: (OperationKind.None) (Syntax: 'switch (x) ... }') - Children(3): IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') - IOperation: (OperationKind.None) (Syntax: 'case var y ... break;') - Children(2): IOperation: (OperationKind.None) (Syntax: 'case var y ... (x >= 10):') - Children(2): IOperation: (OperationKind.None) (Syntax: 'var y') - Children(1): ILocalReferenceExpression: y (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'var y') - IBinaryOperatorExpression (BinaryOperationKind.IntegerGreaterThanOrEqual) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'x >= 10') - Left: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') - Right: ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') - IOperation: (OperationKind.None) (Syntax: 'default:/*< ... break;') - Children(2): IOperation: (OperationKind.None) (Syntax: 'default:') - Children(1): IOperation: (OperationKind.None) (Syntax: 'default:') - IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +ISwitchStatement (2 cases) (OperationKind.SwitchStatement) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case var y ... break;') + Clauses: IPatternCaseClause (Label Symbol: case var y when (x >= 10):) (OperationKind.PatternCaseClause) (Syntax: 'case var y ... (x >= 10):') + Pattern: IDeclarationPattern (Declared Symbol: System.Int32 y) (OperationKind.DeclarationPattern) (Syntax: 'var y') + Guard Expression: IBinaryOperatorExpression (BinaryOperationKind.IntegerGreaterThanOrEqual) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'x >= 10') + Left: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x') + Right: ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'default:/*< ... break;') + Clauses: IPatternCaseClause (Label Symbol: default:) (OperationKind.PatternCaseClause) (Syntax: 'default:') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -844,10 +841,9 @@ public void Method1(object x) } "; string expectedOperationTree = @" -IOperation: (OperationKind.None) (Syntax: 'x is int y') - Children(2): IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') - IOperation: (OperationKind.None) (Syntax: 'int y') - Children(1): ILocalReferenceExpression: y (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'int y') +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'x is int y') + Expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Pattern: IDeclarationPattern (Declared Symbol: System.Int32 y) (OperationKind.DeclarationPattern) (Syntax: 'int y') "; var expectedDiagnostics = DiagnosticDescription.None; diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IPatternSwitchCase.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IPatternSwitchCase.cs new file mode 100644 index 0000000000000000000000000000000000000000..4e6b266764ba0924582717d288d658809b33b3fc --- /dev/null +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IPatternSwitchCase.cs @@ -0,0 +1,679 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public partial class IOperationTests : SemanticModelTestBase + { + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_VarPatternDeclaration() + { + string source = @" +using System; +class X +{ + void M() + { + int? x = 12; + switch (x) + { + /**/case var y:/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement) (Syntax: 'switch (x) ... }') + Switch expression: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32?) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case var y: ... break;') + Clauses: IPatternCaseClause (Label Symbol: case var y:) (OperationKind.PatternCaseClause) (Syntax: 'case var y:') + Pattern: IDeclarationPattern (Declared Symbol: System.Int32? y) (OperationKind.DeclarationPattern) (Syntax: 'var y') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_PrimitiveTypePatternDeclaration() + { + string source = @" +using System; +class X +{ + void M() + { + int? x = 12; + switch (x) + { + /**/case int y:/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement) (Syntax: 'switch (x) ... }') + Switch expression: ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Int32?) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case int y: ... break;') + Clauses: IPatternCaseClause (Label Symbol: case int y:) (OperationKind.PatternCaseClause) (Syntax: 'case int y:') + Pattern: IDeclarationPattern (Declared Symbol: System.Int32 y) (OperationKind.DeclarationPattern) (Syntax: 'int y') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_ReferenceTypePatternDeclaration() + { + string source = @" +using System; +class X +{ + void M(object x) + { + switch (x) + { + /**/case X y:/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case X y:/* ... break;') + Clauses: IPatternCaseClause (Label Symbol: case X y:) (OperationKind.PatternCaseClause) (Syntax: 'case X y:') + Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_TypeParameterTypePatternDeclaration() + { + string source = @" +using System; +class X +{ + void M(object x) where T : class + { + switch (x) + { + /**/case T y:/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case T y:/* ... break;') + Clauses: IPatternCaseClause (Label Symbol: case T y:) (OperationKind.PatternCaseClause) (Syntax: 'case T y:') + Pattern: IDeclarationPattern (Declared Symbol: T y) (OperationKind.DeclarationPattern) (Syntax: 'T y') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_DynamicTypePatternDeclaration() + { + string source = @" +using System; +class X +{ + void M(object x) where T : class + { + switch (x) + { + /**/case dynamic y:/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement, IsInvalid) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case dynami ... break;') + Clauses: IPatternCaseClause (Label Symbol: case dynamic y:) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case dynamic y:') + Pattern: IDeclarationPattern (Declared Symbol: dynamic y) (OperationKind.DeclarationPattern, IsInvalid) (Syntax: 'dynamic y') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS8208: It is not legal to use the type 'dynamic' in a pattern. + // /**/case dynamic y:/**/ + Diagnostic(ErrorCode.ERR_PatternDynamicType, "dynamic").WithLocation(9, 28) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_MixedDeclarationPatternAndConstantPatternClauses() + { + string source = @" +using System; +class X +{ + void M(object x) + { + switch (x) + { + case null: + break; + /**/case X y:/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (2 cases) (OperationKind.SwitchStatement) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case null: ... break;') + Clauses: IPatternCaseClause (Label Symbol: case null:) (OperationKind.PatternCaseClause) (Syntax: 'case null:') + Pattern: IConstantPattern (OperationKind.ConstantPattern) (Syntax: 'case null:') + Value: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Object, Constant: null) (Syntax: 'null') + ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') + ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case X y:/* ... break;') + Clauses: IPatternCaseClause (Label Symbol: case X y:) (OperationKind.PatternCaseClause) (Syntax: 'case X y:') + Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_MixedDeclarationPatternAndConstantPatternClausesInSameSwitchSection() + { + string source = @" +using System; +class X +{ + void M(object x) + { + switch (x) + { + case null: + /**/case X y:/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Sections: ISwitchCase (2 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case null: ... break;') + Clauses: IPatternCaseClause (Label Symbol: case null:) (OperationKind.PatternCaseClause) (Syntax: 'case null:') + Pattern: IConstantPattern (OperationKind.ConstantPattern) (Syntax: 'case null:') + Value: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Object, Constant: null) (Syntax: 'null') + ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') + IPatternCaseClause (Label Symbol: case X y:) (OperationKind.PatternCaseClause) (Syntax: 'case X y:') + Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_MixedDeclarationPatternAndConstantPatternWithDefaultLabel() + { + string source = @" +using System; +class X +{ + void M(object x) + { + switch (x) + { + case null: + /**/case X y:/**/ + default: + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Sections: ISwitchCase (3 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case null: ... break;') + Clauses: IPatternCaseClause (Label Symbol: case null:) (OperationKind.PatternCaseClause) (Syntax: 'case null:') + Pattern: IConstantPattern (OperationKind.ConstantPattern) (Syntax: 'case null:') + Value: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Object, Constant: null) (Syntax: 'null') + ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') + IPatternCaseClause (Label Symbol: case X y:) (OperationKind.PatternCaseClause) (Syntax: 'case X y:') + Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') + IPatternCaseClause (Label Symbol: default:) (OperationKind.PatternCaseClause) (Syntax: 'default:') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_GuardExpressionInPattern() + { + string source = @" +using System; +class X +{ + void M(object x) + { + switch (x) + { + /**/case X y when x != null:/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case X y wh ... break;') + Clauses: IPatternCaseClause (Label Symbol: case X y when x != null:) (OperationKind.PatternCaseClause) (Syntax: 'case X y when x != null:') + Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') + Guard Expression: IBinaryOperatorExpression (BinaryOperationKind.ObjectNotEquals) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'x != null') + Left: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Right: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Object, Constant: null) (Syntax: 'null') + ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_PatternInGuardExpressionInPattern() + { + string source = @" +using System; +class X +{ + void M(object x) + { + switch (x) + { + /**/case X y when x is X z :/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case X y wh ... break;') + Clauses: IPatternCaseClause (Label Symbol: case X y when x is X z :) (OperationKind.PatternCaseClause) (Syntax: 'case X y when x is X z :') + Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') + Guard Expression: IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'x is X z') + Expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Pattern: IDeclarationPattern (Declared Symbol: X z) (OperationKind.DeclarationPattern) (Syntax: 'X z') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_SyntaxErrorInGuardExpressionInPattern() + { + string source = @" +using System; +class X +{ + void M(object x) + { + switch (x) + { + /**/case X y when :/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement, IsInvalid) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case X y wh ... break;') + Clauses: IPatternCaseClause (Label Symbol: case X y when :) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case X y when :') + Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern, IsInvalid) (Syntax: 'X y') + Guard Expression: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Boolean, IsInvalid) (Syntax: '') + IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS1525: Invalid expression term ':' + // /**/case X y when :/**/ + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ":").WithArguments(":").WithLocation(9, 37) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_SemanticErrorInGuardExpressionInPattern() + { + string source = @" +using System; +class X +{ + void M(object x) + { + switch (x) + { + /**/case X y when x:/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement, IsInvalid) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case X y wh ... break;') + Clauses: IPatternCaseClause (Label Symbol: case X y when x:) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case X y when x:') + Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') + Guard Expression: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Boolean, IsInvalid) (Syntax: 'x') + IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS0266: Cannot implicitly convert type 'object' to 'bool'. An explicit conversion exists (are you missing a cast?) + // /**/case X y when x:/**/ + Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "x").WithArguments("object", "bool").WithLocation(9, 37) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_ConstantPattern() + { + string source = @" +using System; +class X +{ + void M(bool x) + { + switch (x) + { + case /**/x is true/**/: + break; + } + } +} +"; + string expectedOperationTree = @" +IIsPatternExpression (OperationKind.IsPatternExpression, Type: System.Boolean) (Syntax: 'x is true') + Expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Boolean) (Syntax: 'x') + Pattern: IConstantPattern (OperationKind.ConstantPattern) (Syntax: 'true') + Value: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: True) (Syntax: 'true') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS0150: A constant value is expected + // case /**/x is true/**/: + Diagnostic(ErrorCode.ERR_ConstantExpected, "x is true").WithLocation(9, 28) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_DefaultLabel() + { + string source = @" +using System; +class X +{ + void M(object x) + { + switch (x) + { + case X y: + /**/default:/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Sections: ISwitchCase (2 case clauses, 1 statements) (OperationKind.SwitchCase) (Syntax: 'case X y: ... break;') + Clauses: IPatternCaseClause (Label Symbol: case X y:) (OperationKind.PatternCaseClause) (Syntax: 'case X y:') + Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern) (Syntax: 'X y') + IPatternCaseClause (Label Symbol: default:) (OperationKind.PatternCaseClause) (Syntax: 'default:') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_InvalidTypeSwitch() + { + string source = @" +using System; +class X +{ + void M(object x) + { + switch (x.GetType()) + { + /**/case typeof(X):/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement, IsInvalid) (Syntax: 'switch (x.G ... }') + Switch expression: IInvocationExpression ( System.Type System.Object.GetType()) (OperationKind.InvocationExpression, Type: System.Type) (Syntax: 'x.GetType()') + Instance Receiver: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case typeof ... break;') + Clauses: IPatternCaseClause (Label Symbol: case typeof(X):) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case typeof(X):') + Pattern: IConstantPattern (OperationKind.ConstantPattern, IsInvalid) (Syntax: 'case typeof(X):') + Value: ITypeOfExpression (Type: X) (OperationKind.TypeOfExpression, Type: System.Type) (Syntax: 'typeof(X)') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS0150: A constant value is expected + // /**/case typeof(X):/**/ + Diagnostic(ErrorCode.ERR_ConstantExpected, "typeof(X)").WithLocation(9, 28), + // CS0162: Unreachable code detected + // break; + Diagnostic(ErrorCode.WRN_UnreachableCode, "break").WithLocation(10, 17) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_UndefinedTypeInPatternDeclaration() + { + string source = @" +using System; +class X +{ + void M(object x) + { + switch (x) + { + /**/case UndefinedType y:/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement, IsInvalid) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case Undefi ... break;') + Clauses: IPatternCaseClause (Label Symbol: case UndefinedType y:) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case UndefinedType y:') + Pattern: IDeclarationPattern (Declared Symbol: UndefinedType y) (OperationKind.DeclarationPattern, IsInvalid) (Syntax: 'UndefinedType y') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS0246: The type or namespace name 'UndefinedType' could not be found (are you missing a using directive or an assembly reference?) + // /**/case UndefinedType y:/**/ + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "UndefinedType").WithArguments("UndefinedType").WithLocation(9, 28) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_InvalidTypeInPatternDeclaration() + { + string source = @" +using System; +class X +{ + void M(int? x) + { + switch (x) + { + /**/case X y:/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement, IsInvalid) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32?) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case X y:/* ... break;') + Clauses: IPatternCaseClause (Label Symbol: case X y:) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case X y:') + Pattern: IDeclarationPattern (Declared Symbol: X y) (OperationKind.DeclarationPattern, IsInvalid) (Syntax: 'X y') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS8121: An expression of type 'int?' cannot be handled by a pattern of type 'X'. + // /**/case X y:/**/ + Diagnostic(ErrorCode.ERR_PatternWrongType, "X").WithArguments("int?", "X").WithLocation(9, 28) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_DuplicateLocalInPatternDeclaration() + { + string source = @" +using System; +class X +{ + void M(int? x) + { + int? y = 0; + switch (x) + { + /**/case int y:/**/ + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement, IsInvalid) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32?) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 1 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case int y: ... break;') + Clauses: IPatternCaseClause (Label Symbol: case int y:) (OperationKind.PatternCaseClause, IsInvalid) (Syntax: 'case int y:') + Pattern: IDeclarationPattern (Declared Symbol: System.Int32 y) (OperationKind.DeclarationPattern, IsInvalid) (Syntax: 'int y') + Body: IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS0136: A local or parameter named 'y' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter + // /**/case int y:/**/ + Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "y").WithArguments("y").WithLocation(10, 32), + // CS0219: The variable 'y' is assigned but its value is never used + // int? y = 0; + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y").WithArguments("y").WithLocation(7, 14) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact, WorkItem(19927, "https://github.com/dotnet/roslyn/issues/19927")] + public void TestPatternCaseClause_InvalidConstDeclarationInPatternDeclaration() + { + string source = @" +using System; +class X +{ + void M(int? x) + { + switch (x) + { + /**/case /**/const int y: + break; + } + } +} +"; + string expectedOperationTree = @" +ISwitchStatement (1 cases) (OperationKind.SwitchStatement, IsInvalid) (Syntax: 'switch (x) ... }') + Switch expression: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32?) (Syntax: 'x') + Sections: ISwitchCase (1 case clauses, 2 statements) (OperationKind.SwitchCase, IsInvalid) (Syntax: 'case /**/') + IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Int32, IsInvalid) (Syntax: '') + IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '') + Body: IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'const int y') + IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'const int y') + Variables: Local_1: System.Int32 y + IBranchStatement (BranchKind.Break) (OperationKind.BranchStatement) (Syntax: 'break;') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS1525: Invalid expression term 'const' + // /**/case /**/const int y: + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "const").WithArguments("const").WithLocation(9, 39), + // CS1003: Syntax error, ':' expected + // /**/case /**/const int y: + Diagnostic(ErrorCode.ERR_SyntaxError, "const").WithArguments(":", "const").WithLocation(9, 39), + // CS0145: A const field requires a value to be provided + // /**/case /**/const int y: + Diagnostic(ErrorCode.ERR_ConstValueRequired, "y").WithLocation(9, 49), + // CS1002: ; expected + // /**/case /**/const int y: + Diagnostic(ErrorCode.ERR_SemicolonExpected, ":").WithLocation(9, 50), + // CS1513: } expected + // /**/case /**/const int y: + Diagnostic(ErrorCode.ERR_RbraceExpected, ":").WithLocation(9, 50), + // CS0168: The variable 'y' is declared but never used + // /**/case /**/const int y: + Diagnostic(ErrorCode.WRN_UnreferencedVar, "y").WithArguments("y").WithLocation(9, 49) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + } +} \ No newline at end of file diff --git a/src/Compilers/Core/Portable/CodeAnalysis.csproj b/src/Compilers/Core/Portable/CodeAnalysis.csproj index 4915c2ba8dce2b4d132052a0648bfd4e6d0ef8d1..4d1293eb92fe170ae15636a9a1206b955dbda148 100644 --- a/src/Compilers/Core/Portable/CodeAnalysis.csproj +++ b/src/Compilers/Core/Portable/CodeAnalysis.csproj @@ -50,6 +50,11 @@ + + + + + diff --git a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs index 763f5f01e9d62d6aa5ff977ef147b31dc34e5521..f847aac3b55db2cbb31c17aa062860c0dcd21d36 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs @@ -4607,4 +4607,234 @@ public LazyLocalFunctionStatement(IMethodSymbol localFunctionSymbol, Lazy public override IBlockStatement Body => _lazyBody.Value; } + + /// + /// Represents a C# constant pattern. + /// + internal abstract partial class BaseConstantPattern : Operation, IConstantPattern + { + protected BaseConstantPattern(bool isInvalid, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + base(OperationKind.ConstantPattern, isInvalid, syntax, type, constantValue) + { + } + /// + /// Constant value of the pattern. + /// + public abstract IOperation Value { get; } + public override void Accept(OperationVisitor visitor) + { + visitor.VisitConstantPattern(this); + } + public override TResult Accept(OperationVisitor visitor, TArgument argument) + { + return visitor.VisitConstantPattern(this, argument); + } + } + + /// + /// Represents a C# constant pattern. + /// + internal sealed partial class ConstantPattern : BaseConstantPattern, IConstantPattern + { + public ConstantPattern(IOperation value, bool isInvalid, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + base(isInvalid, syntax, type, constantValue) + { + Value = value; + } + /// + /// Constant value of the pattern. + /// + public override IOperation Value { get; } + } + + /// + /// Represents a C# constant pattern. + /// + internal sealed partial class LazyConstantPattern : BaseConstantPattern, IConstantPattern + { + private readonly Lazy _lazyValue; + + public LazyConstantPattern(Lazy value, bool isInvalid, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) + : base(isInvalid, syntax, type, constantValue) + { + _lazyValue = value ?? throw new System.ArgumentNullException("value"); + } + /// + /// Constant value of the pattern. + /// + public override IOperation Value => _lazyValue.Value; + } + + /// + /// Represents a C# declaration pattern. + /// + internal sealed partial class DeclarationPattern : Operation, IDeclarationPattern + { + public DeclarationPattern(ISymbol declaredSymbol, bool isInvalid, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + base(OperationKind.DeclarationPattern, isInvalid, syntax, type, constantValue) + { + DeclaredSymbol = declaredSymbol; + } + /// + /// Symbol declared by the pattern. + /// + public ISymbol DeclaredSymbol { get; } + public override void Accept(OperationVisitor visitor) + { + visitor.VisitDeclarationPattern(this); + } + public override TResult Accept(OperationVisitor visitor, TArgument argument) + { + return visitor.VisitDeclarationPattern(this, argument); + } + } + + /// + /// Represents a C# pattern case clause. + /// + internal abstract partial class BasePatternCaseClause : CaseClause, IPatternCaseClause + { + protected BasePatternCaseClause(ILabelSymbol label, bool isInvalid, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + base(CaseKind.Pattern, OperationKind.PatternCaseClause, isInvalid, syntax, type, constantValue) + { + Label = label; + } + /// + /// Label associated with the case clause. + /// + public ILabelSymbol Label { get; } + /// + /// Pattern associated with case clause. + /// + public abstract IPattern Pattern { get; } + /// + /// Guard expression associated with the pattern case clause. + /// + public abstract IOperation GuardExpression { get; } + public override void Accept(OperationVisitor visitor) + { + visitor.VisitPatternCaseClause(this); + } + public override TResult Accept(OperationVisitor visitor, TArgument argument) + { + return visitor.VisitPatternCaseClause(this, argument); + } + } + + /// + /// Represents a C# pattern case clause. + /// + internal sealed partial class PatternCaseClause : BasePatternCaseClause, IPatternCaseClause + { + public PatternCaseClause(ILabelSymbol label, IPattern pattern, IOperation guardExpression, bool isInvalid, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + base(label, isInvalid, syntax, type, constantValue) + { + Pattern = pattern; + GuardExpression = guardExpression; + } + /// + /// Pattern associated with case clause. + /// + public override IPattern Pattern { get; } + /// + /// Guard expression associated with the pattern case clause. + /// + public override IOperation GuardExpression { get; } + } + + /// + /// Represents a C# pattern case clause. + /// + internal sealed partial class LazyPatternCaseClause : BasePatternCaseClause, IPatternCaseClause + { + private readonly Lazy _lazyPattern; + private readonly Lazy _lazyGuardExpression; + + public LazyPatternCaseClause(ILabelSymbol label, Lazy lazyPattern, Lazy lazyGuardExpression, bool isInvalid, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) + : base(label, isInvalid, syntax, type, constantValue) + { + _lazyPattern = lazyPattern ?? throw new System.ArgumentNullException("lazyPattern"); + _lazyGuardExpression = lazyGuardExpression ?? throw new System.ArgumentNullException("lazyGuardExpression"); + } + /// + /// Pattern associated with case clause. + /// + public override IPattern Pattern => _lazyPattern.Value; + /// + /// Guard expression associated with the pattern case clause. + /// + public override IOperation GuardExpression => _lazyGuardExpression.Value; + } + + /// + /// Represents a C# is pattern expression. For example, "x is int i". + /// + internal abstract partial class BaseIsPatternExpression : Operation, IIsPatternExpression + { + protected BaseIsPatternExpression(bool isInvalid, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + base(OperationKind.IsPatternExpression, isInvalid, syntax, type, constantValue) + { + } + /// + /// Expression. + /// + public abstract IOperation Expression { get; } + /// + /// Pattern. + /// + public abstract IPattern Pattern { get; } + public override void Accept(OperationVisitor visitor) + { + visitor.VisitIsPatternExpression(this); + } + public override TResult Accept(OperationVisitor visitor, TArgument argument) + { + return visitor.VisitIsPatternExpression(this, argument); + } + } + + /// + /// Represents a C# is pattern expression. For example, "x is int i". + /// + internal sealed partial class IsPatternExpression : BaseIsPatternExpression, IIsPatternExpression + { + public IsPatternExpression(IOperation expression, IPattern pattern, bool isInvalid, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + base(isInvalid, syntax, type, constantValue) + { + Expression = expression; + Pattern = pattern; + } + /// + /// Expression. + /// + public override IOperation Expression { get; } + /// + /// Pattern. + /// + public override IPattern Pattern { get; } + } + + /// + /// Represents a C# is pattern expression. For example, "x is int i". + /// + internal sealed partial class LazyIsPatternExpression : BaseIsPatternExpression, IIsPatternExpression + { + private readonly Lazy _lazyExpression; + private readonly Lazy _lazyPattern; + + public LazyIsPatternExpression(Lazy lazyExpression, Lazy lazyPattern, bool isInvalid, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) + : base(isInvalid, syntax, type, constantValue) + { + _lazyExpression = lazyExpression ?? throw new System.ArgumentNullException("lazyExpression"); + _lazyPattern = lazyPattern ?? throw new System.ArgumentNullException("lazyPattern"); + } + /// + /// Expression. + /// + public override IOperation Expression => _lazyExpression.Value; + /// + /// Pattern. + /// + public override IPattern Pattern => _lazyPattern.Value; + } } diff --git a/src/Compilers/Core/Portable/Operations/CaseKind.cs b/src/Compilers/Core/Portable/Operations/CaseKind.cs index 04df82a889aa1b6e847d79a2340adead7f62e6c4..9bb63eb8f16a86ebeccb4225d73220feb8134410 100644 --- a/src/Compilers/Core/Portable/Operations/CaseKind.cs +++ b/src/Compilers/Core/Portable/Operations/CaseKind.cs @@ -26,7 +26,11 @@ public enum CaseKind /// /// Indicates default in C# or Case Else in VB. /// - Default = 0x4 + Default = 0x4, + /// + /// Indicates pattern case in C#. + /// + Pattern = 0x5 } } diff --git a/src/Compilers/Core/Portable/Operations/IConstantPattern.cs b/src/Compilers/Core/Portable/Operations/IConstantPattern.cs new file mode 100644 index 0000000000000000000000000000000000000000..1f5e9ce0f8a1c2369787ff9e2b413c5e28bbd078 --- /dev/null +++ b/src/Compilers/Core/Portable/Operations/IConstantPattern.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.Semantics +{ + /// + /// Represents a C# constant pattern. + /// + /// + /// This interface is reserved for implementation by its associated APIs. We reserve the right to + /// change it in the future. + /// + public interface IConstantPattern : IPattern + { + /// + /// Constant value of the pattern. + /// + IOperation Value { get; } + } +} + diff --git a/src/Compilers/Core/Portable/Operations/IDeclarationPattern.cs b/src/Compilers/Core/Portable/Operations/IDeclarationPattern.cs new file mode 100644 index 0000000000000000000000000000000000000000..11363939decae5e4d8269a0dc6e58bce7dd1238c --- /dev/null +++ b/src/Compilers/Core/Portable/Operations/IDeclarationPattern.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.Semantics +{ + /// + /// Represents a C# declaration pattern. + /// + /// + /// This interface is reserved for implementation by its associated APIs. We reserve the right to + /// change it in the future. + /// + public interface IDeclarationPattern : IPattern + { + /// + /// Symbol declared by the pattern. + /// + ISymbol DeclaredSymbol { get; } + } +} + diff --git a/src/Compilers/Core/Portable/Operations/IIsPatternExpression.cs b/src/Compilers/Core/Portable/Operations/IIsPatternExpression.cs new file mode 100644 index 0000000000000000000000000000000000000000..b344b23f4b05a7169048533045003def34f6ea40 --- /dev/null +++ b/src/Compilers/Core/Portable/Operations/IIsPatternExpression.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.CodeAnalysis.Semantics +{ + /// + /// Represents a C# is pattern expression. For example, "x is int i". + /// + /// + /// This interface is reserved for implementation by its associated APIs. We reserve the right to + /// change it in the future. + /// + public interface IIsPatternExpression : IOperation + { + /// + /// Expression. + /// + IOperation Expression { get; } + + /// + /// Pattern. + /// + IPattern Pattern { get; } + } +} + diff --git a/src/Compilers/Core/Portable/Operations/IPattern.cs b/src/Compilers/Core/Portable/Operations/IPattern.cs new file mode 100644 index 0000000000000000000000000000000000000000..a3a5c55fc3cd2f9f6daf95c69b695b669886b788 --- /dev/null +++ b/src/Compilers/Core/Portable/Operations/IPattern.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Immutable; + +namespace Microsoft.CodeAnalysis.Semantics +{ + /// + /// Represents a C# pattern. + /// + /// + /// This interface is reserved for implementation by its associated APIs. We reserve the right to + /// change it in the future. + /// + public interface IPattern : IOperation + { + } +} + diff --git a/src/Compilers/Core/Portable/Operations/IPatternCaseClause.cs b/src/Compilers/Core/Portable/Operations/IPatternCaseClause.cs new file mode 100644 index 0000000000000000000000000000000000000000..ff6db3ca87acde1bc3ecba4783c30b21e7b52f91 --- /dev/null +++ b/src/Compilers/Core/Portable/Operations/IPatternCaseClause.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.CodeAnalysis.Semantics +{ + /// + /// Represents a C# pattern case clause. + /// + /// + /// This interface is reserved for implementation by its associated APIs. We reserve the right to + /// change it in the future. + /// + public interface IPatternCaseClause : ICaseClause + { + /// + /// Label associated with the case clause. + /// + ILabelSymbol Label { get; } + + /// + /// Pattern associated with case clause. + /// + IPattern Pattern { get; } + + /// + /// Guard expression associated with the pattern case clause. + /// + IOperation GuardExpression { get; } + } +} + diff --git a/src/Compilers/Core/Portable/Operations/OperationKind.cs b/src/Compilers/Core/Portable/Operations/OperationKind.cs index af6e2463f695bf665d06b21b8438651146e164f8..76a88ee703b71233b27adfde794d55bbd74d0b00 100644 --- a/src/Compilers/Core/Portable/Operations/OperationKind.cs +++ b/src/Compilers/Core/Portable/Operations/OperationKind.cs @@ -144,6 +144,8 @@ public enum OperationKind // 0x205 is open for future use. /// Indicates an . IncrementExpression = 0x206, + /// Indicates an . + IsPatternExpression = 0x207, // Expressions that occur only in Visual Basic. @@ -191,5 +193,12 @@ public enum OperationKind InterpolatedStringText = 0x40d, /// Indicates an . Interpolation = 0x40e, + + /// Indicates an . + ConstantPattern = 0x40f, + /// Indicates an . + DeclarationPattern = 0x410, + /// Indicates an . + PatternCaseClause = 0x411, } } diff --git a/src/Compilers/Core/Portable/Operations/OperationVisitor.cs b/src/Compilers/Core/Portable/Operations/OperationVisitor.cs index 98806b783d7aba032b038fba0126d348bca921cd..ce1ba3a56f66c2d45805ba34fb9b56a68d7bcfb2 100644 --- a/src/Compilers/Core/Portable/Operations/OperationVisitor.cs +++ b/src/Compilers/Core/Portable/Operations/OperationVisitor.cs @@ -404,6 +404,26 @@ public virtual void VisitInterpolation(IInterpolation operation) { DefaultVisit(operation); } + + public virtual void VisitIsPatternExpression(IIsPatternExpression operation) + { + DefaultVisit(operation); + } + + public virtual void VisitConstantPattern(IConstantPattern operation) + { + DefaultVisit(operation); + } + + public virtual void VisitDeclarationPattern(IDeclarationPattern operation) + { + DefaultVisit(operation); + } + + public virtual void VisitPatternCaseClause(IPatternCaseClause operation) + { + DefaultVisit(operation); + } } /// @@ -814,5 +834,25 @@ public virtual TResult VisitInterpolation(IInterpolation operation, TArgument ar { return DefaultVisit(operation, argument); } + + public virtual TResult VisitIsPatternExpression(IIsPatternExpression operation, TArgument argument) + { + return DefaultVisit(operation, argument); + } + + public virtual TResult VisitConstantPattern(IConstantPattern operation, TArgument argument) + { + return DefaultVisit(operation, argument); + } + + public virtual TResult VisitDeclarationPattern(IDeclarationPattern operation, TArgument argument) + { + return DefaultVisit(operation, argument); + } + + public virtual TResult VisitPatternCaseClause(IPatternCaseClause operation, TArgument argument) + { + return DefaultVisit(operation, argument); + } } } diff --git a/src/Compilers/Core/Portable/Operations/OperationWalker.cs b/src/Compilers/Core/Portable/Operations/OperationWalker.cs index 68afb672ca593c47c8884d308536805a43af87fc..d9038531f9d9747d8023ff193867f2a6e40d79f0 100644 --- a/src/Compilers/Core/Portable/Operations/OperationWalker.cs +++ b/src/Compilers/Core/Portable/Operations/OperationWalker.cs @@ -439,5 +439,26 @@ public override void VisitInterpolation(IInterpolation operation) Visit(operation.Alignment); Visit(operation.FormatString); } + + public override void VisitConstantPattern(IConstantPattern operation) + { + Visit(operation.Value); + } + + public override void VisitDeclarationPattern(IDeclarationPattern operation) + { + } + + public override void VisitIsPatternExpression(IIsPatternExpression operation) + { + Visit(operation.Expression); + Visit(operation.Pattern); + } + + public override void VisitPatternCaseClause(IPatternCaseClause operation) + { + Visit(operation.Pattern); + Visit(operation.GuardExpression); + } } } diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index 79b81bc3e69342d04ddfbbc1e4f117eefc0d3849..8f658b7a70346309b4826a01d4f7c38090042b86 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -65,7 +65,9 @@ Microsoft.CodeAnalysis.OperationKind.CompoundAssignmentExpression = 281 -> Micro Microsoft.CodeAnalysis.OperationKind.ConditionalAccessExpression = 284 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ConditionalAccessInstanceExpression = 285 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ConditionalChoiceExpression = 271 -> Microsoft.CodeAnalysis.OperationKind +Microsoft.CodeAnalysis.OperationKind.ConstantPattern = 1039 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ConversionExpression = 258 -> Microsoft.CodeAnalysis.OperationKind +Microsoft.CodeAnalysis.OperationKind.DeclarationPattern = 1040 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.DefaultValueExpression = 512 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.EmptyStatement = 9 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.EndStatement = 81 -> Microsoft.CodeAnalysis.OperationKind @@ -86,6 +88,7 @@ Microsoft.CodeAnalysis.OperationKind.Interpolation = 1038 -> Microsoft.CodeAnaly Microsoft.CodeAnalysis.OperationKind.InvalidExpression = 256 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.InvalidStatement = 1 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.InvocationExpression = 259 -> Microsoft.CodeAnalysis.OperationKind +Microsoft.CodeAnalysis.OperationKind.IsPatternExpression = 519 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.IsTypeExpression = 278 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.LabelStatement = 7 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.LambdaExpression = 273 -> Microsoft.CodeAnalysis.OperationKind @@ -103,6 +106,7 @@ Microsoft.CodeAnalysis.OperationKind.OmittedArgumentExpression = 768 -> Microsof Microsoft.CodeAnalysis.OperationKind.ParameterInitializerAtDeclaration = 1028 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ParameterReferenceExpression = 262 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ParenthesizedExpression = 282 -> Microsoft.CodeAnalysis.OperationKind +Microsoft.CodeAnalysis.OperationKind.PatternCaseClause = 1041 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.PlaceholderExpression = 770 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.PointerIndirectionReferenceExpression = 516 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.PropertyInitializerAtDeclaration = 1027 -> Microsoft.CodeAnalysis.OperationKind @@ -313,6 +317,7 @@ Microsoft.CodeAnalysis.Semantics.BranchKind.None = 0 -> Microsoft.CodeAnalysis.S Microsoft.CodeAnalysis.Semantics.CaseKind Microsoft.CodeAnalysis.Semantics.CaseKind.Default = 4 -> Microsoft.CodeAnalysis.Semantics.CaseKind Microsoft.CodeAnalysis.Semantics.CaseKind.None = 0 -> Microsoft.CodeAnalysis.Semantics.CaseKind +Microsoft.CodeAnalysis.Semantics.CaseKind.Pattern = 5 -> Microsoft.CodeAnalysis.Semantics.CaseKind Microsoft.CodeAnalysis.Semantics.CaseKind.Range = 3 -> Microsoft.CodeAnalysis.Semantics.CaseKind Microsoft.CodeAnalysis.Semantics.CaseKind.Relational = 2 -> Microsoft.CodeAnalysis.Semantics.CaseKind Microsoft.CodeAnalysis.Semantics.CaseKind.SingleValue = 1 -> Microsoft.CodeAnalysis.Semantics.CaseKind @@ -373,10 +378,14 @@ Microsoft.CodeAnalysis.Semantics.IConditionalChoiceExpression Microsoft.CodeAnalysis.Semantics.IConditionalChoiceExpression.Condition.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.IConditionalChoiceExpression.IfFalseValue.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.IConditionalChoiceExpression.IfTrueValue.get -> Microsoft.CodeAnalysis.IOperation +Microsoft.CodeAnalysis.Semantics.IConstantPattern +Microsoft.CodeAnalysis.Semantics.IConstantPattern.Value.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.IConversionExpression Microsoft.CodeAnalysis.Semantics.IConversionExpression.ConversionKind.get -> Microsoft.CodeAnalysis.Semantics.ConversionKind Microsoft.CodeAnalysis.Semantics.IConversionExpression.IsExplicit.get -> bool Microsoft.CodeAnalysis.Semantics.IConversionExpression.Operand.get -> Microsoft.CodeAnalysis.IOperation +Microsoft.CodeAnalysis.Semantics.IDeclarationPattern +Microsoft.CodeAnalysis.Semantics.IDeclarationPattern.DeclaredSymbol.get -> Microsoft.CodeAnalysis.ISymbol Microsoft.CodeAnalysis.Semantics.IDefaultValueExpression Microsoft.CodeAnalysis.Semantics.IEmptyStatement Microsoft.CodeAnalysis.Semantics.IEndStatement @@ -436,6 +445,9 @@ Microsoft.CodeAnalysis.Semantics.IInvocationExpression Microsoft.CodeAnalysis.Semantics.IInvocationExpression.Instance.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.IInvocationExpression.IsVirtual.get -> bool Microsoft.CodeAnalysis.Semantics.IInvocationExpression.TargetMethod.get -> Microsoft.CodeAnalysis.IMethodSymbol +Microsoft.CodeAnalysis.Semantics.IIsPatternExpression +Microsoft.CodeAnalysis.Semantics.IIsPatternExpression.Expression.get -> Microsoft.CodeAnalysis.IOperation +Microsoft.CodeAnalysis.Semantics.IIsPatternExpression.Pattern.get -> Microsoft.CodeAnalysis.Semantics.IPattern Microsoft.CodeAnalysis.Semantics.IIsTypeExpression Microsoft.CodeAnalysis.Semantics.IIsTypeExpression.IsType.get -> Microsoft.CodeAnalysis.ITypeSymbol Microsoft.CodeAnalysis.Semantics.IIsTypeExpression.Operand.get -> Microsoft.CodeAnalysis.IOperation @@ -480,6 +492,11 @@ Microsoft.CodeAnalysis.Semantics.IParameterReferenceExpression Microsoft.CodeAnalysis.Semantics.IParameterReferenceExpression.Parameter.get -> Microsoft.CodeAnalysis.IParameterSymbol Microsoft.CodeAnalysis.Semantics.IParenthesizedExpression Microsoft.CodeAnalysis.Semantics.IParenthesizedExpression.Operand.get -> Microsoft.CodeAnalysis.IOperation +Microsoft.CodeAnalysis.Semantics.IPattern +Microsoft.CodeAnalysis.Semantics.IPatternCaseClause +Microsoft.CodeAnalysis.Semantics.IPatternCaseClause.GuardExpression.get -> Microsoft.CodeAnalysis.IOperation +Microsoft.CodeAnalysis.Semantics.IPatternCaseClause.Label.get -> Microsoft.CodeAnalysis.ILabelSymbol +Microsoft.CodeAnalysis.Semantics.IPatternCaseClause.Pattern.get -> Microsoft.CodeAnalysis.Semantics.IPattern Microsoft.CodeAnalysis.Semantics.IPlaceholderExpression Microsoft.CodeAnalysis.Semantics.IPointerIndirectionReferenceExpression Microsoft.CodeAnalysis.Semantics.IPointerIndirectionReferenceExpression.Pointer.get -> Microsoft.CodeAnalysis.IOperation @@ -695,7 +712,9 @@ override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitCompoundAssignmen override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitConditionalAccessExpression(Microsoft.CodeAnalysis.Semantics.IConditionalAccessExpression operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitConditionalAccessInstanceExpression(Microsoft.CodeAnalysis.Semantics.IConditionalAccessInstanceExpression operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitConditionalChoiceExpression(Microsoft.CodeAnalysis.Semantics.IConditionalChoiceExpression operation) -> void +override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitConstantPattern(Microsoft.CodeAnalysis.Semantics.IConstantPattern operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitConversionExpression(Microsoft.CodeAnalysis.Semantics.IConversionExpression operation) -> void +override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitDeclarationPattern(Microsoft.CodeAnalysis.Semantics.IDeclarationPattern operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitDefaultValueExpression(Microsoft.CodeAnalysis.Semantics.IDefaultValueExpression operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitEmptyStatement(Microsoft.CodeAnalysis.Semantics.IEmptyStatement operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitEndStatement(Microsoft.CodeAnalysis.Semantics.IEndStatement operation) -> void @@ -717,6 +736,7 @@ override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitInterpolation(Mic override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitInvalidExpression(Microsoft.CodeAnalysis.Semantics.IInvalidExpression operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitInvalidStatement(Microsoft.CodeAnalysis.Semantics.IInvalidStatement operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitInvocationExpression(Microsoft.CodeAnalysis.Semantics.IInvocationExpression operation) -> void +override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitIsPatternExpression(Microsoft.CodeAnalysis.Semantics.IIsPatternExpression operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitIsTypeExpression(Microsoft.CodeAnalysis.Semantics.IIsTypeExpression operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitLabelStatement(Microsoft.CodeAnalysis.Semantics.ILabelStatement operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitLambdaExpression(Microsoft.CodeAnalysis.Semantics.ILambdaExpression operation) -> void @@ -732,6 +752,7 @@ override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitOmittedArgumentEx override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitParameterInitializer(Microsoft.CodeAnalysis.Semantics.IParameterInitializer operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitParameterReferenceExpression(Microsoft.CodeAnalysis.Semantics.IParameterReferenceExpression operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitParenthesizedExpression(Microsoft.CodeAnalysis.Semantics.IParenthesizedExpression operation) -> void +override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitPatternCaseClause(Microsoft.CodeAnalysis.Semantics.IPatternCaseClause operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitPlaceholderExpression(Microsoft.CodeAnalysis.Semantics.IPlaceholderExpression operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitPointerIndirectionReferenceExpression(Microsoft.CodeAnalysis.Semantics.IPointerIndirectionReferenceExpression operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitPropertyInitializer(Microsoft.CodeAnalysis.Semantics.IPropertyInitializer operation) -> void @@ -796,7 +817,9 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitCompoundAssignmen virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConditionalAccessExpression(Microsoft.CodeAnalysis.Semantics.IConditionalAccessExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConditionalAccessInstanceExpression(Microsoft.CodeAnalysis.Semantics.IConditionalAccessInstanceExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConditionalChoiceExpression(Microsoft.CodeAnalysis.Semantics.IConditionalChoiceExpression operation) -> void +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConstantPattern(Microsoft.CodeAnalysis.Semantics.IConstantPattern operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConversionExpression(Microsoft.CodeAnalysis.Semantics.IConversionExpression operation) -> void +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitDeclarationPattern(Microsoft.CodeAnalysis.Semantics.IDeclarationPattern operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitDefaultValueExpression(Microsoft.CodeAnalysis.Semantics.IDefaultValueExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitEmptyStatement(Microsoft.CodeAnalysis.Semantics.IEmptyStatement operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitEndStatement(Microsoft.CodeAnalysis.Semantics.IEndStatement operation) -> void @@ -818,6 +841,7 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitInterpolation(Mic virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitInvalidExpression(Microsoft.CodeAnalysis.Semantics.IInvalidExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitInvalidStatement(Microsoft.CodeAnalysis.Semantics.IInvalidStatement operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitInvocationExpression(Microsoft.CodeAnalysis.Semantics.IInvocationExpression operation) -> void +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitIsPatternExpression(Microsoft.CodeAnalysis.Semantics.IIsPatternExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitIsTypeExpression(Microsoft.CodeAnalysis.Semantics.IIsTypeExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLabelStatement(Microsoft.CodeAnalysis.Semantics.ILabelStatement operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLambdaExpression(Microsoft.CodeAnalysis.Semantics.ILambdaExpression operation) -> void @@ -833,6 +857,7 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitOmittedArgumentEx virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitParameterInitializer(Microsoft.CodeAnalysis.Semantics.IParameterInitializer operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitParameterReferenceExpression(Microsoft.CodeAnalysis.Semantics.IParameterReferenceExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitParenthesizedExpression(Microsoft.CodeAnalysis.Semantics.IParenthesizedExpression operation) -> void +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitPatternCaseClause(Microsoft.CodeAnalysis.Semantics.IPatternCaseClause operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitPlaceholderExpression(Microsoft.CodeAnalysis.Semantics.IPlaceholderExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitPointerIndirectionReferenceExpression(Microsoft.CodeAnalysis.Semantics.IPointerIndirectionReferenceExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitPropertyInitializer(Microsoft.CodeAnalysis.Semantics.IPropertyInitializer operation) -> void @@ -874,7 +899,9 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.Vi virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConditionalAccessExpression(Microsoft.CodeAnalysis.Semantics.IConditionalAccessExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConditionalAccessInstanceExpression(Microsoft.CodeAnalysis.Semantics.IConditionalAccessInstanceExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConditionalChoiceExpression(Microsoft.CodeAnalysis.Semantics.IConditionalChoiceExpression operation, TArgument argument) -> TResult +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConstantPattern(Microsoft.CodeAnalysis.Semantics.IConstantPattern operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConversionExpression(Microsoft.CodeAnalysis.Semantics.IConversionExpression operation, TArgument argument) -> TResult +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitDeclarationPattern(Microsoft.CodeAnalysis.Semantics.IDeclarationPattern operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitDefaultValueExpression(Microsoft.CodeAnalysis.Semantics.IDefaultValueExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitEmptyStatement(Microsoft.CodeAnalysis.Semantics.IEmptyStatement operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitEndStatement(Microsoft.CodeAnalysis.Semantics.IEndStatement operation, TArgument argument) -> TResult @@ -896,6 +923,7 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.Vi virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitInvalidExpression(Microsoft.CodeAnalysis.Semantics.IInvalidExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitInvalidStatement(Microsoft.CodeAnalysis.Semantics.IInvalidStatement operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitInvocationExpression(Microsoft.CodeAnalysis.Semantics.IInvocationExpression operation, TArgument argument) -> TResult +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitIsPatternExpression(Microsoft.CodeAnalysis.Semantics.IIsPatternExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitIsTypeExpression(Microsoft.CodeAnalysis.Semantics.IIsTypeExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLabelStatement(Microsoft.CodeAnalysis.Semantics.ILabelStatement operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLambdaExpression(Microsoft.CodeAnalysis.Semantics.ILambdaExpression operation, TArgument argument) -> TResult @@ -911,6 +939,7 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.Vi virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitParameterInitializer(Microsoft.CodeAnalysis.Semantics.IParameterInitializer operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitParameterReferenceExpression(Microsoft.CodeAnalysis.Semantics.IParameterReferenceExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitParenthesizedExpression(Microsoft.CodeAnalysis.Semantics.IParenthesizedExpression operation, TArgument argument) -> TResult +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitPatternCaseClause(Microsoft.CodeAnalysis.Semantics.IPatternCaseClause operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitPlaceholderExpression(Microsoft.CodeAnalysis.Semantics.IPlaceholderExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitPointerIndirectionReferenceExpression(Microsoft.CodeAnalysis.Semantics.IPointerIndirectionReferenceExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitPropertyInitializer(Microsoft.CodeAnalysis.Semantics.IPropertyInitializer operation, TArgument argument) -> TResult diff --git a/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs b/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs index 182bd6db2bffad8a3968982709a1d70759bd6cb1..d00ed38065ba018a8f2b5b75c87b3c0f1461c8a0 100644 --- a/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs +++ b/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs @@ -1123,6 +1123,42 @@ public override void VisitInterpolation(IInterpolation operation) Visit(operation.FormatString, "FormatString"); } + public override void VisitConstantPattern(IConstantPattern operation) + { + LogString(nameof(IConstantPattern)); + LogCommonPropertiesAndNewLine(operation); + + Visit(operation.Value, "Value"); + } + + public override void VisitDeclarationPattern(IDeclarationPattern operation) + { + LogString(nameof(IDeclarationPattern)); + LogSymbol(operation.DeclaredSymbol, " (Declared Symbol"); + LogString(")"); + LogCommonPropertiesAndNewLine(operation); + } + + public override void VisitIsPatternExpression(IIsPatternExpression operation) + { + LogString(nameof(IIsPatternExpression)); + LogCommonPropertiesAndNewLine(operation); + + Visit(operation.Expression, "Expression"); + Visit(operation.Pattern, "Pattern"); + } + + public override void VisitPatternCaseClause(IPatternCaseClause operation) + { + LogString(nameof(IPatternCaseClause)); + LogSymbol(operation.Label, " (Label Symbol"); + LogString(")"); + LogCommonPropertiesAndNewLine(operation); + + Visit(operation.Pattern, "Pattern"); + Visit(operation.GuardExpression, "Guard Expression"); + } + #endregion } } \ No newline at end of file diff --git a/src/Test/Utilities/Portable/Compilation/TestOperationWalker.cs b/src/Test/Utilities/Portable/Compilation/TestOperationWalker.cs index c524c43f919e2ec10b608d936f2ec26277fc6bc8..5d050384d1a7c2424513644257f78d6d163857ab 100644 --- a/src/Test/Utilities/Portable/Compilation/TestOperationWalker.cs +++ b/src/Test/Utilities/Portable/Compilation/TestOperationWalker.cs @@ -529,5 +529,29 @@ public override void VisitInterpolation(IInterpolation operation) { base.VisitInterpolation(operation); } + + public override void VisitConstantPattern(IConstantPattern operation) + { + base.VisitConstantPattern(operation); + } + + public override void VisitDeclarationPattern(IDeclarationPattern operation) + { + var declaredSymbol = operation.DeclaredSymbol; + + base.VisitDeclarationPattern(operation); + } + + public override void VisitIsPatternExpression(IIsPatternExpression operation) + { + base.VisitIsPatternExpression(operation); + } + + public override void VisitPatternCaseClause(IPatternCaseClause operation) + { + var label = operation.Label; + + base.VisitPatternCaseClause(operation); + } } } \ No newline at end of file