diff --git a/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj b/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj index 4a4c65fbab736379eecd1ee2149757e1e2002326..919da6cb6560607f779c357d5794b483147fa4ac 100644 --- a/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj +++ b/src/Compilers/CSharp/Test/Semantic/CSharpCompilerSemanticTest.csproj @@ -59,6 +59,7 @@ + diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IIfStatement.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IIfStatement.cs new file mode 100644 index 0000000000000000000000000000000000000000..87d5e395e19ffeb9de211532e6b8a8ca4226ccf3 --- /dev/null +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IIfStatement.cs @@ -0,0 +1,739 @@ +// 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.CSharp.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public partial class IOperationTests : SemanticModelTestBase + { + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementSimpleIf() + { + string source = @" +class P +{ + private void M() + { + bool condition=false; + /**/if (true) + { + condition = true; + }/**/ + } +} +"; + + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: True) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IExpressionStatement (OperationKind.ExpressionStatement) + IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Boolean) + Left: ILocalReferenceExpression: condition (OperationKind.LocalReferenceExpression, Type: System.Boolean) + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: True) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementSimpleIfWithElse() + { + string source = @" +class P +{ + private void M() + { + bool condition=false; + /**/if (true) + { + condition = true; + } + else + { + condition = false; + }/**/ + } +} +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: True) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IExpressionStatement (OperationKind.ExpressionStatement) + IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Boolean) + Left: ILocalReferenceExpression: condition (OperationKind.LocalReferenceExpression, Type: System.Boolean) + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: True) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IExpressionStatement (OperationKind.ExpressionStatement) + IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Boolean) + Left: ILocalReferenceExpression: condition (OperationKind.LocalReferenceExpression, Type: System.Boolean) + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: False) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementSimpleIfWithConditionEvaluationTrue() + { + string source = @" +class P +{ + private void M() + { + bool condition=false; + /**/if (1==1) + { + condition = true; + }/**/ + + } +} +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: IBinaryOperatorExpression (BinaryOperationKind.IntegerEquals) (OperationKind.BinaryOperatorExpression, Type: System.Boolean, Constant: True) + Left: ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) + Right: ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IExpressionStatement (OperationKind.ExpressionStatement) + IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Boolean) + Left: ILocalReferenceExpression: condition (OperationKind.LocalReferenceExpression, Type: System.Boolean) + Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: True) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementSimpleIfNested1() + { + string source = @" +using System; +class P +{ + private void M() + { + int m = 12; + int n = 18; + /**/ + if (m > 10) + { + if (n > 20) + Console.WriteLine(""Result1""); + } + else + { + Console.WriteLine(""Result2""); + }/**/ + + } +} +"; + var compilation = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseDll, parseOptions: TestOptions.Regular); + + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: IBinaryOperatorExpression (BinaryOperationKind.IntegerGreaterThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) + Left: ILocalReferenceExpression: m (OperationKind.LocalReferenceExpression, Type: System.Int32) + Right: ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IIfStatement (OperationKind.IfStatement) + Condition: IBinaryOperatorExpression (BinaryOperationKind.IntegerGreaterThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) + Left: ILocalReferenceExpression: n (OperationKind.LocalReferenceExpression, Type: System.Int32) + Right: ILiteralExpression (Text: 20) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 20) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: value) (OperationKind.Argument) + ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: Result1) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: value) (OperationKind.Argument) + ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: Result2) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementSimpleIfNested2() + { + string source = @" +using System; +class P +{ +private void M() + { + int m = 9; + int n = 7; + /**/if (m > 10) + if (n > 20) + { + Console.WriteLine(""Result1""); + } + else + { + Console.WriteLine(""Result2""); + }/**/ + + } +} +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: IBinaryOperatorExpression (BinaryOperationKind.IntegerGreaterThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) + Left: ILocalReferenceExpression: m (OperationKind.LocalReferenceExpression, Type: System.Int32) + Right: ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) + IIfStatement (OperationKind.IfStatement) + Condition: IBinaryOperatorExpression (BinaryOperationKind.IntegerGreaterThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) + Left: ILocalReferenceExpression: n (OperationKind.LocalReferenceExpression, Type: System.Int32) + Right: ILiteralExpression (Text: 20) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 20) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: value) (OperationKind.Argument) + ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: Result1) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: value) (OperationKind.Argument) + ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: Result2) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementWithMultipleCondition() + { + string source = @" +using System; +class P +{ + private void M() + { + int m = 9; + int n = 7; + int p = 5; + /**/if (m >= n && m >= p) + { + Console.WriteLine(""Nothing is larger than m.""); + }/**/ + } +} +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: IBinaryOperatorExpression (BinaryOperationKind.BooleanConditionalAnd) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) + Left: IBinaryOperatorExpression (BinaryOperationKind.IntegerGreaterThanOrEqual) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) + Left: ILocalReferenceExpression: m (OperationKind.LocalReferenceExpression, Type: System.Int32) + Right: ILocalReferenceExpression: n (OperationKind.LocalReferenceExpression, Type: System.Int32) + Right: IBinaryOperatorExpression (BinaryOperationKind.IntegerGreaterThanOrEqual) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) + Left: ILocalReferenceExpression: m (OperationKind.LocalReferenceExpression, Type: System.Int32) + Right: ILocalReferenceExpression: p (OperationKind.LocalReferenceExpression, Type: System.Int32) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: value) (OperationKind.Argument) + ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: Nothing is larger than m.) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementWithElseIfCondition() + { + string source = @" +using System; +class P +{ + private void M() + { + int m = 9; + int n = 7; + /**/if (n > 20) + { + Console.WriteLine(""Result1""); + } + else if(m > 10) + { + Console.WriteLine(""Result2""); + } + else + { + Console.WriteLine(""Result3""); + }/**/ + + } +} +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: IBinaryOperatorExpression (BinaryOperationKind.IntegerGreaterThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) + Left: ILocalReferenceExpression: n (OperationKind.LocalReferenceExpression, Type: System.Int32) + Right: ILiteralExpression (Text: 20) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 20) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: value) (OperationKind.Argument) + ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: Result1) + IIfStatement (OperationKind.IfStatement) + Condition: IBinaryOperatorExpression (BinaryOperationKind.IntegerGreaterThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) + Left: ILocalReferenceExpression: m (OperationKind.LocalReferenceExpression, Type: System.Int32) + Right: ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: value) (OperationKind.Argument) + ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: Result2) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: value) (OperationKind.Argument) + ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: Result3) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementWithElseIfConditionOutVar() + { + string source = @" +class P +{ + private void M() + { + var s = """"; + /**/if (int.TryParse(s, out var i)) + System.Console.WriteLine($""i ={ i}, s ={ s}""); + else + System.Console.WriteLine($""i ={ i}, s ={ s}"");/**/ + + } +} +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: IInvocationExpression (static System.Boolean System.Int32.TryParse(System.String s, out System.Int32 result)) (OperationKind.InvocationExpression, Type: System.Boolean) + IArgument (Matching Parameter: s) (OperationKind.Argument) + ILocalReferenceExpression: s (OperationKind.LocalReferenceExpression, Type: System.String) + IArgument (Matching Parameter: result) (OperationKind.Argument) + ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: value) (OperationKind.Argument) + IOperation: (OperationKind.None) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: value) (OperationKind.Argument) + IOperation: (OperationKind.None) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementWithOutVar() + { + string source = @" +class P +{ + private void M() + { + + /**/if (true) + System.Console.WriteLine(A());/**/ + } + private int A() + { + var s = """"; + if (int.TryParse(s, out var i)) + { + return i; + } + else + { + return -1; + } + + } + +} + +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: True) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void System.Console.WriteLine(System.Int32 value)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: value) (OperationKind.Argument) + IInvocationExpression ( System.Int32 P.A()) (OperationKind.InvocationExpression, Type: System.Int32) + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementExplictEmbeddedOutVar() + { + string source = @" +class P +{ + private void M() + { + var s = ""data""; + /**/if (true) + { + A(int.TryParse(s, out var i)); + }/**/ + } + private void A(bool flag) + { + if (flag) + { + System.Console.WriteLine(""Result1""); + } + } + +} + +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: True) + IBlockStatement (1 statements, 1 locals) (OperationKind.BlockStatement) + Local_1: System.Int32 i + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression ( void P.A(System.Boolean flag)) (OperationKind.InvocationExpression, Type: System.Void) + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P) + IArgument (Matching Parameter: flag) (OperationKind.Argument) + IInvocationExpression (static System.Boolean System.Int32.TryParse(System.String s, out System.Int32 result)) (OperationKind.InvocationExpression, Type: System.Boolean) + IArgument (Matching Parameter: s) (OperationKind.Argument) + ILocalReferenceExpression: s (OperationKind.LocalReferenceExpression, Type: System.String) + IArgument (Matching Parameter: result) (OperationKind.Argument) + ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementImplicitEmbeddedOutVar() + { + string source = @" +class Program +{ + static void Main(string[] args) + { + object o = 25; + /**/if (true) + A(o is int i, 1);/**/ + } + + private static void A(bool flag, int number) + { + if (flag) + { + System.Console.WriteLine(new string('*', number)); + } + } +} +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: True) + IBlockStatement (1 statements, 1 locals) (OperationKind.BlockStatement) + Local_1: System.Int32 i + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void Program.A(System.Boolean flag, System.Int32 number)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: flag) (OperationKind.Argument) + IOperation: (OperationKind.None) + IArgument (Matching Parameter: number) (OperationKind.Argument) + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementWithConditionPattern() + { + string source = @" +using System; + +class P +{ + private void M() + { + object obj = ""pattern""; + + /**/if (obj is string str) + { + Console.WriteLine(str); + }/**/ + } +} +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: IOperation: (OperationKind.None) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: value) (OperationKind.Argument) + ILocalReferenceExpression: str (OperationKind.LocalReferenceExpression, Type: System.String) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementWithPattern() + { + string source = @" +class Program +{ + static void Main(string[] args) + { + /**/if (true) + A(25);/**/ + } + + private static void A(object o) + { + if (o is null) return; + if (!(o is int i)) return; + System.Console.WriteLine(new string('*', i)); + } +} +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: True) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void Program.A(System.Object o)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: o) (OperationKind.Argument) + IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Object) + ILiteralExpression (Text: 25) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 25) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementWithEmbeddedPattern() + { + string source = @" +class Program +{ + static void Main(string[] args) + { + object o = 25; + /**/if (true) + { + A(o is int i, 1); + }/**/ + } + + private static void A(bool flag, int number) + { + if (flag) + { + System.Console.WriteLine(new string('*', number)); + } + } +} +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: True) + IBlockStatement (1 statements, 1 locals) (OperationKind.BlockStatement) + Local_1: System.Int32 i + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void Program.A(System.Boolean flag, System.Int32 number)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: flag) (OperationKind.Argument) + IOperation: (OperationKind.None) + IArgument (Matching Parameter: number) (OperationKind.Argument) + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementWithElseMissing() + { + string source = @" +using System; + +class P +{ + private void M() + { + object obj = ""pattern""; + + /**/if (obj is string str) + { + Console.WriteLine(str); + } + else +/**/ } +} +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement, IsInvalid) + Condition: IOperation: (OperationKind.None) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression (static void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) + IArgument (Matching Parameter: value) (OperationKind.Argument) + ILocalReferenceExpression: str (OperationKind.LocalReferenceExpression, Type: System.String) + IExpressionStatement (OperationKind.ExpressionStatement, IsInvalid) + IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementWithConditionMissing() + { + string source = @" +using System; + +class P +{ + private void M() + { + int a = 1; + /**/if () + { + a = 2; + } + else + { + a = 3; + }/**/ + } +} +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement, IsInvalid) + Condition: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Boolean, IsInvalid) + IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IExpressionStatement (OperationKind.ExpressionStatement) + IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Int32) + Left: ILocalReferenceExpression: a (OperationKind.LocalReferenceExpression, Type: System.Int32) + Right: ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IExpressionStatement (OperationKind.ExpressionStatement) + IAssignmentExpression (OperationKind.AssignmentExpression, Type: System.Int32) + Left: ILocalReferenceExpression: a (OperationKind.LocalReferenceExpression, Type: System.Int32) + Right: ILiteralExpression (Text: 3) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 3) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementWithStatementMissing() + { + string source = @" +using System; + +class P +{ + private void M() + { + int a = 1; + /**/if (a==1) + else +/**/ + } +} +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement, IsInvalid) + Condition: IBinaryOperatorExpression (BinaryOperationKind.IntegerEquals) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) + Left: ILocalReferenceExpression: a (OperationKind.LocalReferenceExpression, Type: System.Int32) + Right: ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) + IExpressionStatement (OperationKind.ExpressionStatement, IsInvalid) + IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) + IExpressionStatement (OperationKind.ExpressionStatement, IsInvalid) + IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementWithFuncCall() + { + string source = @" +using System; + +class P +{ + private void M() + { + /**/if (true) + A(); + else + B();/**/ + } + private void A() + { + Console.WriteLine(""A""); + } + private void B() + { + Console.WriteLine(""B""); + } +} +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: True) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression ( void P.A()) (OperationKind.InvocationExpression, Type: System.Void) + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P) + IExpressionStatement (OperationKind.ExpressionStatement) + IInvocationExpression ( void P.B()) (OperationKind.InvocationExpression, Type: System.Void) + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + [Fact, WorkItem(17601, "https://github.com/dotnet/roslyn/issues/17601")] + public void IIfstatementWithDynamic() + { + string source = @" +using System; + +class C +{ + public static int F(dynamic d, Type t, T x) where T : struct + { + /**/if (d.GetType() == t && ((T)d).Equals(x)) + { + return 1; + }/**/ + + return 2; + } +} +"; + string expectedOperationTree = @" +IIfStatement (OperationKind.IfStatement) + Condition: IUnaryOperatorExpression (UnaryOperationKind.DynamicTrue) (OperationKind.UnaryOperatorExpression, Type: System.Boolean) + IBinaryOperatorExpression (BinaryOperationKind.DynamicAnd) (OperationKind.BinaryOperatorExpression, Type: dynamic) + Left: IBinaryOperatorExpression (BinaryOperationKind.Invalid) (OperationKind.BinaryOperatorExpression, Type: dynamic) + Left: IOperation: (OperationKind.None) + Right: IParameterReferenceExpression: t (OperationKind.ParameterReferenceExpression, Type: System.Type) + Right: IInvocationExpression (virtual System.Boolean System.ValueType.Equals(System.Object obj)) (OperationKind.InvocationExpression, Type: System.Boolean) + Instance Receiver: IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: T) + IParameterReferenceExpression: d (OperationKind.ParameterReferenceExpression, Type: dynamic) + IArgument (Matching Parameter: obj) (OperationKind.Argument) + IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Object) + IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: T) + IBlockStatement (1 statements) (OperationKind.BlockStatement) + IReturnStatement (OperationKind.ReturnStatement) + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) +"; + VerifyOperationTreeForTest(source, expectedOperationTree); + } + + } +} diff --git a/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj b/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj index 83e2c7f40c5a9b8b1e858130f5a70bcddc408a34..4c4c938c888b5b9fe5756474c156d1f8f2b2b607 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj +++ b/src/Compilers/VisualBasic/Test/Semantic/BasicCompilerSemanticTest.vbproj @@ -96,6 +96,7 @@ + diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IIfStatement.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IIfStatement.vb new file mode 100644 index 0000000000000000000000000000000000000000..d9505d737bc60827ef54ee7fe4c2408f5f7262db --- /dev/null +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IIfStatement.vb @@ -0,0 +1,612 @@ +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +Imports Microsoft.CodeAnalysis.VisualBasic.Syntax +Imports Roslyn.Test.Utilities + +Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics + + Partial Public Class IOperationTests + Inherits SemanticModelTestBase + + + Public Sub IIfstatementSingleLineIf() + Dim source = 0 Then returnValue = count'BIND:"If count > 0 Then returnValue = count" + End Sub +End Module + ]]>.Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of SingleLineIfStatementSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementMultiLineIf() + Dim source = 0 Then'BIND:"If count > 0 Then" + returnValue = count + End If + End Sub + End Module + + ]]>.Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of MultiLineIfBlockSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementSingleLineIfAndElse() + Dim source = 10 Then data = data + count Else data = data - count'BIND:"If count > 10 Then data = data + count Else data = data - count" + End Sub +End Module + ]]>.Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of SingleLineIfStatementSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementSingleLineIfAndElseNested() + Dim source = 10 Then If n > 20 Then returnValue = n'BIND:"If m > 10 Then If n > 20 Then returnValue = n" + End Sub +End Module + ]]>.Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of SingleLineIfStatementSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementSimpleIfWithConditionEvaluationTrue() + Dim source = .Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of MultiLineIfBlockSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementSimpleIfWithConditionConstantFalse() + Dim source = .Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of MultiLineIfBlockSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementSingleLineWithOperator() + Dim source = 10 And n > 20) Then returnValue = n'BIND:"If (m > 10 And n > 20) Then returnValue = n" + End Sub +End Module + ]]>.Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of SingleLineIfStatementSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementMultiLineIfWithElse() + Dim source = 0 Then'BIND:"If count > 0 Then" + returnValue = count + Else + returnValue = -1 + End If + End Sub +End Module + ]]>.Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of MultiLineIfBlockSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementSimpleIfNested1() + Dim source = 10) Then'BIND:"If (m > 10) Then" + If (n > 20) Then + Console.WriteLine("Result 1") + End If + Else + Console.WriteLine("Result 2") + End If + End Sub +End Module + ]]>.Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of MultiLineIfBlockSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementIfNested2() + Dim source = 10) Then'BIND:"If (m > 10) Then" + If (n > 20) Then + Console.WriteLine("Result 1") + Else + Console.WriteLine("Result 2") + End If + End If + End Sub +End Module + ]]>.Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of MultiLineIfBlockSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementWithMultipleCondition() + Dim source = = n AndAlso m >= p) Then'BIND:"If (m >= n AndAlso m >= p) Then" + Console.WriteLine("Nothing Is larger than m.") + End If + End Sub +End Module + ]]>.Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of MultiLineIfBlockSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementWithElseIfCondition() + Dim source = 20) Then'BIND:"If (m > 20) Then" + Console.WriteLine("Result1") + ElseIf (n > 10) Then + Console.WriteLine("Result2") + Else + Console.WriteLine("Result3") + End If + End Sub +End Module + ]]>.Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of MultiLineIfBlockSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementWithElseIfSingleLine() + Dim source = 20) Then System.Console.WriteLine("Result1") Else If (n > 10) Then System.Console.WriteLine("Result2") Else System.Console.WriteLine("Result3") End If'BIND:"If (m > 20) Then System.Console.WriteLine("Result1") Else If (n > 10) Then System.Console.WriteLine("Result2") Else System.Console.WriteLine("Result3")" + End Sub +End Module + ]]>.Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of SingleLineIfStatementSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementWithElseMissing() + Dim source = 20) Then'BIND:"If (m > 20) Then" + Console.WriteLine("Result1") + Else + End Sub +End Module + ]]>.Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of MultiLineIfBlockSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementWithConditionMissing() + Dim source = .Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of MultiLineIfBlockSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementWithStatementMissing() + Dim source = .Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of MultiLineIfBlockSyntax)(source, expectedOperationTree) + End Sub + + + Public Sub IIfstatementWithFuncCall() + Dim source = .Value + + Dim expectedOperationTree = .Value + + VerifyOperationTreeForTest(Of MultiLineIfBlockSyntax)(source, expectedOperationTree) + End Sub + + End Class +End Namespace