From 543e66e0528f344e32bf49cd7322bc20829d07a4 Mon Sep 17 00:00:00 2001 From: Gen Lu Date: Thu, 6 Apr 2017 16:39:21 -0700 Subject: [PATCH] More CSharp tests for IArgument --- .../IOperation/IOperationTests_IArgument.cs | 485 +++++++++++++++--- .../Operations/IHasArgumentsExpression.cs | 10 +- 2 files changed, 410 insertions(+), 85 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IArgument.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IArgument.cs index 47689408923..f2e49a755a3 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IArgument.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IArgument.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests public partial class IOperationTests : SemanticModelTestBase { [Fact] - public void ExplicitSimpleArgument() + public void PositinalArgument() { string source = @" class P @@ -37,7 +37,7 @@ static void M1() } [Fact] - public void DefaultSimpleArgument() + public void PositionalArgumentWithDefaultValue() { string source = @" class P @@ -63,7 +63,7 @@ static void M1() } [Fact] - public void ExplicitNamedArgument() + public void NamedArgumentListedInParameterOrder() { string source = @" class P @@ -90,7 +90,7 @@ static void M1() [Fact] - public void OutOfOrderExplicitNamedArgument() + public void NamedArgumentListedOutOfParameterOrder() { string source = @" class P @@ -116,25 +116,27 @@ static void M1() } [Fact] - public void DefaultNamedArgument() + public void NamedArgumentInParameterOrderWithDefaultValue() { string source = @" class P { static void M1() { - /**/M2(y: 9.9)/**/; + /**/M2(y: 0, z: 2)/**/; } - static void M2(int x = 1, double y = 0.0) { } + static void M2(int x = 1, int y = 2, int z = 3) { } } "; string expectedOperationTree = @" -IInvocationExpression (static void P.M2([System.Int32 x = 1], [System.Double y = 0])) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(y: 9.9)') - Arguments(2): IArgument (ArgumentKind.Explicit Matching Parameter: y) (OperationKind.Argument) (Syntax: '9.9') - ILiteralExpression (Text: 9.9) (OperationKind.LiteralExpression, Type: System.Double, Constant: 9.9) (Syntax: '9.9') - IArgument (ArgumentKind.DefaultValue Matching Parameter: x) (OperationKind.Argument) (Syntax: 'M2(y: 9.9)') - ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: 'M2(y: 9.9)') +IInvocationExpression (static void P.M2([System.Int32 x = 1], [System.Int32 y = 2], [System.Int32 z = 3])) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(y: 0, z: 2)') + Arguments(3): IArgument (ArgumentKind.Explicit Matching Parameter: y) (OperationKind.Argument) (Syntax: '0') + ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + IArgument (ArgumentKind.Explicit Matching Parameter: z) (OperationKind.Argument) (Syntax: '2') + ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: '2') + IArgument (ArgumentKind.DefaultValue Matching Parameter: x) (OperationKind.Argument) (Syntax: 'M2(y: 0, z: 2)') + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: 'M2(y: 0, z: 2)') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -142,27 +144,27 @@ static void M1() } [Fact] - public void DefaultAndExplicitNamedArguments() + public void NamedArgumentOutOfParameterOrderWithDefaultValue() { string source = @" class P { static void M1() { - /**/M2(1, z: 10)/**/; + /**/M2(z: 2, x: 9)/**/; } static void M2(int x = 1, int y = 2, int z = 3) { } } "; string expectedOperationTree = @" -IInvocationExpression (static void P.M2([System.Int32 x = 1], [System.Int32 y = 2], [System.Int32 z = 3])) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(1, z: 10)') - Arguments(3): IArgument (ArgumentKind.Explicit Matching Parameter: x) (OperationKind.Argument) (Syntax: '1') - ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') - IArgument (ArgumentKind.Explicit Matching Parameter: z) (OperationKind.Argument) (Syntax: '10') - ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') - IArgument (ArgumentKind.DefaultValue Matching Parameter: y) (OperationKind.Argument) (Syntax: 'M2(1, z: 10)') - ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: 'M2(1, z: 10)') +IInvocationExpression (static void P.M2([System.Int32 x = 1], [System.Int32 y = 2], [System.Int32 z = 3])) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(z: 2, x: 9)') + Arguments(3): IArgument (ArgumentKind.Explicit Matching Parameter: z) (OperationKind.Argument) (Syntax: '2') + ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: '2') + IArgument (ArgumentKind.Explicit Matching Parameter: x) (OperationKind.Argument) (Syntax: '9') + ILiteralExpression (Text: 9) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 9) (Syntax: '9') + IArgument (ArgumentKind.DefaultValue Matching Parameter: y) (OperationKind.Argument) (Syntax: 'M2(z: 2, x: 9)') + ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: 'M2(z: 2, x: 9)') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -170,7 +172,36 @@ static void M1() } [Fact] - public void RefAndOutArguments() + public void NamedAndPositionalArgumentsWithDefaultValue() + { + string source = @" +class P +{ + static void M1() + { + /**/M2(9, z: 10);/**/ + } + + static void M2(int x = 1, int y = 2, int z = 3) { } +} +"; + string expectedOperationTree = @" +IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'M2(9, z: 10);') + IInvocationExpression (static void P.M2([System.Int32 x = 1], [System.Int32 y = 2], [System.Int32 z = 3])) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(9, z: 10)') + Arguments(3): IArgument (ArgumentKind.Explicit Matching Parameter: x) (OperationKind.Argument) (Syntax: '9') + ILiteralExpression (Text: 9) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 9) (Syntax: '9') + IArgument (ArgumentKind.Explicit Matching Parameter: z) (OperationKind.Argument) (Syntax: '10') + ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') + IArgument (ArgumentKind.DefaultValue Matching Parameter: y) (OperationKind.Argument) (Syntax: 'M2(9, z: 10)') + ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: 'M2(9, z: 10)') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void PositionalRefAndOutArguments() { string source = @" class P @@ -199,7 +230,38 @@ void M1() } [Fact] - public void NamedRefAndOutArguments() + public void NamedRefAndOutArgumentsInParameterOrder() + { + string source = @" +class P +{ + void M1() + { + int a = 1; + int b; + /**/M2(x: ref a, y: out b)/**/; + } + + void M2(ref int x, out int y) { y = 10; } +} +"; + string expectedOperationTree = @" +IInvocationExpression ( void P.M2(ref System.Int32 x, out System.Int32 y)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(x: ref a, y: out b)') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P) (Syntax: 'M2') + Arguments(2): IArgument (ArgumentKind.Explicit Matching Parameter: x) (OperationKind.Argument) (Syntax: 'a') + ILocalReferenceExpression: a (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'a') + IArgument (ArgumentKind.Explicit Matching Parameter: y) (OperationKind.Argument) (Syntax: 'b') + ILocalReferenceExpression: b (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'b') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + + + [Fact] + public void NamedRefAndOutArgumentsOutOfParameterOrder() { string source = @" class P @@ -228,29 +290,147 @@ void M1() } [Fact] - public void OmittedParamsArrayArgument() + public void DefaultValueOfNewStruct() + { + string source = @" +class P +{ + void M1() + { + M2(); + } + + void M2(S sobj = new S()) { } +} + +/**/struct S { }/**/ +"; + string expectedOperationTree = @" +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void PositionalArgumentForExtensionMethod() + { + string source = @" +class P +{ + void M1() + { + /**/this.E1(1, 2)/**/; + } +} + +static class Extensions +{ + public static void E1(this P p, int x = 0, int y = 0) + { } +} +"; + string expectedOperationTree = @" +IInvocationExpression (static void Extensions.E1(this P p, [System.Int32 x = 0], [System.Int32 y = 0])) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'this.E1(1, 2)') + Arguments(3): IArgument (ArgumentKind.Explicit Matching Parameter: p) (OperationKind.Argument) (Syntax: 'this') + IInstanceReferenceExpression (InstanceReferenceKind.Explicit) (OperationKind.InstanceReferenceExpression, Type: P) (Syntax: 'this') + IArgument (ArgumentKind.Explicit Matching Parameter: x) (OperationKind.Argument) (Syntax: '1') + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') + IArgument (ArgumentKind.Explicit Matching Parameter: y) (OperationKind.Argument) (Syntax: '2') + ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: '2') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void NamedArgumentOutOfParameterOrderForExtensionMethod() + { + string source = @" +class P +{ + void M1() + { + /**/this.E1(y: 1, x: 2);/**/ + } +} + +static class Extensions +{ + public static void E1(this P p, int x = 0, int y = 0) + { } +} +"; + string expectedOperationTree = @" +IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'this.E1(y: 1, x: 2);') + IInvocationExpression (static void Extensions.E1(this P p, [System.Int32 x = 0], [System.Int32 y = 0])) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'this.E1(y: 1, x: 2)') + Arguments(3): IArgument (ArgumentKind.Explicit Matching Parameter: p) (OperationKind.Argument) (Syntax: 'this') + IInstanceReferenceExpression (InstanceReferenceKind.Explicit) (OperationKind.InstanceReferenceExpression, Type: P) (Syntax: 'this') + IArgument (ArgumentKind.Explicit Matching Parameter: y) (OperationKind.Argument) (Syntax: '1') + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') + IArgument (ArgumentKind.Explicit Matching Parameter: x) (OperationKind.Argument) (Syntax: '2') + ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: '2') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void NamedArgumentWithDefaultValueForExtensionMethod() + { + string source = @" +class P +{ + void M1() + { + /**/this.E1(y: 1)/**/; + } +} + +static class Extensions +{ + public static void E1(this P p, int x = 0, int y = 0) + { } +} +"; + string expectedOperationTree = @" +IInvocationExpression (static void Extensions.E1(this P p, [System.Int32 x = 0], [System.Int32 y = 0])) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'this.E1(y: 1)') + Arguments(3): IArgument (ArgumentKind.Explicit Matching Parameter: p) (OperationKind.Argument) (Syntax: 'this') + IInstanceReferenceExpression (InstanceReferenceKind.Explicit) (OperationKind.InstanceReferenceExpression, Type: P) (Syntax: 'this') + IArgument (ArgumentKind.Explicit Matching Parameter: y) (OperationKind.Argument) (Syntax: '1') + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') + IArgument (ArgumentKind.DefaultValue Matching Parameter: x) (OperationKind.Argument) (Syntax: 'this.E1(y: 1)') + ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: 'this.E1(y: 1)') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void ParamsArrayArgumentInNormalForm() { string source = @" class P { void M1() { - /**/M2(null)/**/; + var a = new[] { 0.0 }; + /**/M2(1, a)/**/; } - void M2(string str, params int[] array) { } + void M2(int x, params double[] array) { } } "; string expectedOperationTree = @" -IInvocationExpression ( void P.M2(System.String str, params System.Int32[] array)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(null)') +IInvocationExpression ( void P.M2(System.Int32 x, params System.Double[] array)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(1, a)') Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P) (Syntax: 'M2') - Arguments(2): IArgument (ArgumentKind.Explicit Matching Parameter: str) (OperationKind.Argument) (Syntax: 'null') - IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.String, Constant: null) (Syntax: 'null') - ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') - IArgument (ArgumentKind.ParamArray Matching Parameter: array) (OperationKind.Argument) (Syntax: 'M2(null)') - IArrayCreationExpression (Element Type: System.Int32) (OperationKind.ArrayCreationExpression, Type: System.Int32[]) (Syntax: 'M2(null)') - Dimension Sizes(1): ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: null, Constant: 0) (Syntax: 'M2(null)') - Initializer: IArrayInitializer (OperationKind.ArrayInitializer) (Syntax: 'M2(null)') + Arguments(2): IArgument (ArgumentKind.Explicit Matching Parameter: x) (OperationKind.Argument) (Syntax: '1') + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') + IArgument (ArgumentKind.Explicit Matching Parameter: array) (OperationKind.Argument) (Syntax: 'a') + ILocalReferenceExpression: a (OperationKind.LocalReferenceExpression, Type: System.Double[]) (Syntax: 'a') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -258,31 +438,30 @@ Dimension Sizes(1): ILiteralExpression (Text: 0) (OperationKind.LiteralExpressio } [Fact] - public void ParamsArrayArguments() + public void ParamsArrayArgumentInExpandedForm() { string source = @" class P { void M1() { - /**/M2(null, 1, 2)/**/; + /**/M2(1, 0.1, 0.2)/**/; } - void M2(string str, params int[] array) { } + void M2(int x, params double[] array) { } } "; string expectedOperationTree = @" -IInvocationExpression ( void P.M2(System.String str, params System.Int32[] array)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(null, 1, 2)') +IInvocationExpression ( void P.M2(System.Int32 x, params System.Double[] array)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(1, 0.1, 0.2)') Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P) (Syntax: 'M2') - Arguments(2): IArgument (ArgumentKind.Explicit Matching Parameter: str) (OperationKind.Argument) (Syntax: 'null') - IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.String, Constant: null) (Syntax: 'null') - ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') - IArgument (ArgumentKind.ParamArray Matching Parameter: array) (OperationKind.Argument) (Syntax: '1') - IArrayCreationExpression (Element Type: System.Int32) (OperationKind.ArrayCreationExpression, Type: System.Int32[]) (Syntax: '1') - Dimension Sizes(1): ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: null, Constant: 2) (Syntax: '1') - Initializer: IArrayInitializer (OperationKind.ArrayInitializer) (Syntax: '1') - Element Values(2): ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') - ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: '2') + Arguments(2): IArgument (ArgumentKind.Explicit Matching Parameter: x) (OperationKind.Argument) (Syntax: '1') + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') + IArgument (ArgumentKind.ParamArray Matching Parameter: array) (OperationKind.Argument) (Syntax: '0.1') + IArrayCreationExpression (Element Type: System.Double) (OperationKind.ArrayCreationExpression, Type: System.Double[]) (Syntax: '0.1') + Dimension Sizes(1): ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: null, Constant: 2) (Syntax: '0.1') + Initializer: IArrayInitializer (OperationKind.ArrayInitializer) (Syntax: '0.1') + Element Values(2): ILiteralExpression (Text: 0.1) (OperationKind.LiteralExpression, Type: System.Double, Constant: 0.1) (Syntax: '0.1') + ILiteralExpression (Text: 0.2) (OperationKind.LiteralExpression, Type: System.Double, Constant: 0.2) (Syntax: '0.2') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -290,31 +469,28 @@ Element Values(2): ILiteralExpression (Text: 1) (OperationKind.LiteralExpression } [Fact] - public void ArrayAsParamsArrayArgument() + public void ParamsArrayArgumentInExpandedFormWithNoArgument() { string source = @" class P { void M1() { - /**/M2(null, new[] { 1, 2 })/**/; + /**/M2(1)/**/; } - void M2(string str, params int[] array) { } + void M2(int x, params double[] array) { } } "; string expectedOperationTree = @" -IInvocationExpression ( void P.M2(System.String str, params System.Int32[] array)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(null, new[] { 1, 2 })') +IInvocationExpression ( void P.M2(System.Int32 x, params System.Double[] array)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(1)') Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P) (Syntax: 'M2') - Arguments(2): IArgument (ArgumentKind.Explicit Matching Parameter: str) (OperationKind.Argument) (Syntax: 'null') - IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.String, Constant: null) (Syntax: 'null') - ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') - IArgument (ArgumentKind.Explicit Matching Parameter: array) (OperationKind.Argument) (Syntax: 'new[] { 1, 2 }') - IArrayCreationExpression (Element Type: System.Int32) (OperationKind.ArrayCreationExpression, Type: System.Int32[]) (Syntax: 'new[] { 1, 2 }') - Dimension Sizes(1): ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: 'new[] { 1, 2 }') - Initializer: IArrayInitializer (OperationKind.ArrayInitializer) (Syntax: '{ 1, 2 }') - Element Values(2): ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') - ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: '2') + Arguments(2): IArgument (ArgumentKind.Explicit Matching Parameter: x) (OperationKind.Argument) (Syntax: '1') + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') + IArgument (ArgumentKind.ParamArray Matching Parameter: array) (OperationKind.Argument) (Syntax: 'M2(1)') + IArrayCreationExpression (Element Type: System.Double) (OperationKind.ArrayCreationExpression, Type: System.Double[]) (Syntax: 'M2(1)') + Dimension Sizes(1): ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: null, Constant: 0) (Syntax: 'M2(1)') + Initializer: IArrayInitializer (OperationKind.ArrayInitializer) (Syntax: 'M2(1)') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -322,30 +498,147 @@ Element Values(2): ILiteralExpression (Text: 1) (OperationKind.LiteralExpression } [Fact] - public void NamedParamsArrayArgument() + public void DefaultValueAndParamsArrayArgumentInExpandedFormWithNoArgument() { string source = @" class P { void M1() { - /**/M2(array: 1, str: null)/**/; + var a = new[] { 0.0 }; + /**/M2()/**/; } - void M2(string str, params int[] array) { } + void M2(int x = 0, params double[] array) { } } "; string expectedOperationTree = @" -IInvocationExpression ( void P.M2(System.String str, params System.Int32[] array)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(array: 1, str: null)') +IInvocationExpression ( void P.M2([System.Int32 x = 0], params System.Double[] array)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2()') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P) (Syntax: 'M2') + Arguments(2): IArgument (ArgumentKind.DefaultValue Matching Parameter: x) (OperationKind.Argument) (Syntax: 'M2()') + ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: 'M2()') + IArgument (ArgumentKind.ParamArray Matching Parameter: array) (OperationKind.Argument) (Syntax: 'M2()') + IArrayCreationExpression (Element Type: System.Double) (OperationKind.ArrayCreationExpression, Type: System.Double[]) (Syntax: 'M2()') + Dimension Sizes(1): ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: null, Constant: 0) (Syntax: 'M2()') + Initializer: IArrayInitializer (OperationKind.ArrayInitializer) (Syntax: 'M2()') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void DefaultValueAndNamedParamsArrayArgumentInNormalForm() + { + string source = @" +class P +{ + void M1() + { + var a = new[] { 0.0 }; + /**/M2(array: a)/**/; + } + + void M2(int x = 0, params double[] array) { } +} +"; + string expectedOperationTree = @" +IInvocationExpression ( void P.M2([System.Int32 x = 0], params System.Double[] array)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(array: a)') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P) (Syntax: 'M2') + Arguments(2): IArgument (ArgumentKind.Explicit Matching Parameter: array) (OperationKind.Argument) (Syntax: 'a') + ILocalReferenceExpression: a (OperationKind.LocalReferenceExpression, Type: System.Double[]) (Syntax: 'a') + IArgument (ArgumentKind.DefaultValue Matching Parameter: x) (OperationKind.Argument) (Syntax: 'M2(array: a)') + ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: 'M2(array: a)') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void DefaultValueAndNamedParamsArrayArgumentInExpandedForm() + { + string source = @" +class P +{ + void M1() + { + /**/M2(array: 1)/**/; + } + + void M2(int x = 0, params double[] array) { } +} +"; + string expectedOperationTree = @" +IInvocationExpression ( void P.M2([System.Int32 x = 0], params System.Double[] array)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(array: 1)') Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P) (Syntax: 'M2') Arguments(2): IArgument (ArgumentKind.ParamArray Matching Parameter: array) (OperationKind.Argument) (Syntax: '1') - IArrayCreationExpression (Element Type: System.Int32) (OperationKind.ArrayCreationExpression, Type: System.Int32[]) (Syntax: '1') + IArrayCreationExpression (Element Type: System.Double) (OperationKind.ArrayCreationExpression, Type: System.Double[]) (Syntax: '1') + Dimension Sizes(1): ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: null, Constant: 1) (Syntax: '1') + Initializer: IArrayInitializer (OperationKind.ArrayInitializer) (Syntax: '1') + Element Values(1): IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Double, Constant: 1) (Syntax: '1') + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') + IArgument (ArgumentKind.DefaultValue Matching Parameter: x) (OperationKind.Argument) (Syntax: 'M2(array: 1)') + ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: 'M2(array: 1)') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void PositionalArgumentAndNamedParamsArrayArgumentInNormalForm() + { + string source = @" +class P +{ + void M1() + { + var a = new[] { 0.0 }; + /**/M2(1, array: a)/**/; + } + + void M2(int x = 0, params double[] array) { } +} +"; + string expectedOperationTree = @" +IInvocationExpression ( void P.M2([System.Int32 x = 0], params System.Double[] array)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(1, array: a)') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P) (Syntax: 'M2') + Arguments(2): IArgument (ArgumentKind.Explicit Matching Parameter: x) (OperationKind.Argument) (Syntax: '1') + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') + IArgument (ArgumentKind.Explicit Matching Parameter: array) (OperationKind.Argument) (Syntax: 'a') + ILocalReferenceExpression: a (OperationKind.LocalReferenceExpression, Type: System.Double[]) (Syntax: 'a') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void PositionalArgumentAndNamedParamsArrayArgumentInExpandedForm() + { + string source = @" +class P +{ + void M1() + { + /**/M2(1, array: 1)/**/; + } + + void M2(int x = 0, params double[] array) { } +} +"; + string expectedOperationTree = @" +IInvocationExpression ( void P.M2([System.Int32 x = 0], params System.Double[] array)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(1, array: 1)') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P) (Syntax: 'M2') + Arguments(2): IArgument (ArgumentKind.Explicit Matching Parameter: x) (OperationKind.Argument) (Syntax: '1') + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') + IArgument (ArgumentKind.ParamArray Matching Parameter: array) (OperationKind.Argument) (Syntax: '1') + IArrayCreationExpression (Element Type: System.Double) (OperationKind.ArrayCreationExpression, Type: System.Double[]) (Syntax: '1') Dimension Sizes(1): ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: null, Constant: 1) (Syntax: '1') Initializer: IArrayInitializer (OperationKind.ArrayInitializer) (Syntax: '1') - Element Values(1): ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') - IArgument (ArgumentKind.Explicit Matching Parameter: str) (OperationKind.Argument) (Syntax: 'null') - IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.String, Constant: null) (Syntax: 'null') - ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') + Element Values(1): IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Double, Constant: 1) (Syntax: '1') + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') "; var expectedDiagnostics = DiagnosticDescription.None; @@ -353,31 +646,59 @@ Element Values(1): ILiteralExpression (Text: 1) (OperationKind.LiteralExpression } [Fact] - public void ArrayAsNamedParamsArrayArgument() + public void NamedArgumentAndNamedParamsArrayArgumentInNormalFormOutOfParameterOrder() + { + string source = @" +class P +{ + void M1() + { + var a = new[] { 0.0 }; + /**/M2(array: a, x: 1);/**/ + } + + void M2(int x = 0, params double[] array) { } +} +"; + string expectedOperationTree = @" +IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'M2(array: a, x: 1);') + IInvocationExpression ( void P.M2([System.Int32 x = 0], params System.Double[] array)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(array: a, x: 1)') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P) (Syntax: 'M2') + Arguments(2): IArgument (ArgumentKind.Explicit Matching Parameter: array) (OperationKind.Argument) (Syntax: 'a') + ILocalReferenceExpression: a (OperationKind.LocalReferenceExpression, Type: System.Double[]) (Syntax: 'a') + IArgument (ArgumentKind.Explicit Matching Parameter: x) (OperationKind.Argument) (Syntax: '1') + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void NamedArgumentAndNamedParamsArrayArgumentInExpandedFormOutOfParameterOrder() { string source = @" class P { void M1() { - /**/M2(array: new[] { 1, 2 }, str: null)/**/; + /**/M2(array: 1, x: 10)/**/; } - void M2(string str, params int[] array) { } + void M2(int x = 0, params double[] array) { } } "; string expectedOperationTree = @" -IInvocationExpression ( void P.M2(System.String str, params System.Int32[] array)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(array: n ... str: null)') +IInvocationExpression ( void P.M2([System.Int32 x = 0], params System.Double[] array)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'M2(array: 1, x: 10)') Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P) (Syntax: 'M2') - Arguments(2): IArgument (ArgumentKind.Explicit Matching Parameter: array) (OperationKind.Argument) (Syntax: 'new[] { 1, 2 }') - IArrayCreationExpression (Element Type: System.Int32) (OperationKind.ArrayCreationExpression, Type: System.Int32[]) (Syntax: 'new[] { 1, 2 }') - Dimension Sizes(1): ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: 'new[] { 1, 2 }') - Initializer: IArrayInitializer (OperationKind.ArrayInitializer) (Syntax: '{ 1, 2 }') - Element Values(2): ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') - ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: '2') - IArgument (ArgumentKind.Explicit Matching Parameter: str) (OperationKind.Argument) (Syntax: 'null') - IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.String, Constant: null) (Syntax: 'null') - ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') + Arguments(2): IArgument (ArgumentKind.ParamArray Matching Parameter: array) (OperationKind.Argument) (Syntax: '1') + IArrayCreationExpression (Element Type: System.Double) (OperationKind.ArrayCreationExpression, Type: System.Double[]) (Syntax: '1') + Dimension Sizes(1): ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: null, Constant: 1) (Syntax: '1') + Initializer: IArrayInitializer (OperationKind.ArrayInitializer) (Syntax: '1') + Element Values(1): IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Double, Constant: 1) (Syntax: '1') + ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') + IArgument (ArgumentKind.Explicit Matching Parameter: x) (OperationKind.Argument) (Syntax: '10') + ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') "; var expectedDiagnostics = DiagnosticDescription.None; diff --git a/src/Compilers/Core/Portable/Operations/IHasArgumentsExpression.cs b/src/Compilers/Core/Portable/Operations/IHasArgumentsExpression.cs index 223381dfca5..0a0c8c4174f 100644 --- a/src/Compilers/Core/Portable/Operations/IHasArgumentsExpression.cs +++ b/src/Compilers/Core/Portable/Operations/IHasArgumentsExpression.cs @@ -11,10 +11,14 @@ namespace Microsoft.CodeAnalysis.Semantics public interface IHasArgumentsExpression : IOperation { /// - /// Arguments of the invocation, excluding the instance argument. Arguments are in evaluation order, - /// and params/ParamArray arguments have been collected into arrays. Default values are supplied for - /// optional arguments missing in source. + /// Arguments of the invocation, excluding the instance argument. Arguments are in evaluation order. /// + /// + /// If the invocation is in its expanded form, then params/ParamArray arguments would be collected into arrays. + /// Default values are supplied for optional arguments missing in source. Because they are always constant, their + /// evaluation will not impact the evaluation order of the remaining arguments, therefore are appended at the end + /// of the returned argument list. + /// ImmutableArray ArgumentsInEvaluationOrder { get; } } } -- GitLab