提交 b7f4f2c8 编写于 作者: G Gen Lu

Fix IHasArgumentsExpression implementation

上级 aa38ba15
......@@ -59,6 +59,7 @@
<Compile Include="Diagnostics\DiagnosticAnalyzerTests.AllInOne.cs" />
<Compile Include="Diagnostics\DiagnosticAnalyzerTests.cs" />
<Compile Include="Diagnostics\GetDiagnosticsTests.cs" />
<Compile Include="IOperation\IOperationTests_IArgument.cs" />
<Compile Include="IOperation\IOperationTests_IIfStatement.cs" />
<Compile Include="IOperation\IOperationTests_ISymbolInitializer.cs" />
<Compile Include="IOperation\IOperationTests_InvalidExpression.cs" />
......
// 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 Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public partial class IOperationTests : SemanticModelTestBase
{
[Fact]
public void ExplicitSimpleArgument()
{
string source = @"
class P
{
static void M1()
{
/*<bind>*/M2(1, """")/*</bind>*/;
}
static void M2(int x, string y) { }
}
";
string expectedOperationTree = @"
IInvocationExpression (static void P.M2(System.Int32 x, System.String y)) (OperationKind.InvocationExpression, Type: System.Void)
IArgument (ArgumentKind.Positional Matching Parameter: x) (OperationKind.Argument)
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1)
IArgument (ArgumentKind.Positional Matching Parameter: y) (OperationKind.Argument)
ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: )
";
VerifyOperationTreeForTest<InvocationExpressionSyntax>(source, expectedOperationTree);
}
[Fact]
public void DefaultSimpleArgument()
{
string source = @"
class P
{
static void M1()
{
/*<bind>*/M2(1)/*</bind>*/;
}
static void M2(int x, string y = null) { }
}
";
string expectedOperationTree = @"
IInvocationExpression (static void P.M2(System.Int32 x, [System.String y = null])) (OperationKind.InvocationExpression, Type: System.Void)
IArgument (ArgumentKind.Positional Matching Parameter: x) (OperationKind.Argument)
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1)
IArgument (ArgumentKind.DefaultValue Matching Parameter: y) (OperationKind.Argument)
ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: System.String, Constant: null)
";
VerifyOperationTreeForTest<InvocationExpressionSyntax>(source, expectedOperationTree);
}
[Fact]
public void DefaultAndExplicitNamedArguments()
{
string source = @"
class P
{
static void M1()
{
/*<bind>*/M2(1, z: 10)/*</bind>*/;
}
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)
IArgument (ArgumentKind.Positional Matching Parameter: x) (OperationKind.Argument)
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1)
IArgument (ArgumentKind.Named Matching Parameter: z) (OperationKind.Argument)
ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10)
IArgument (ArgumentKind.DefaultValue Matching Parameter: y) (OperationKind.Argument)
ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2)
";
VerifyOperationTreeForTest<InvocationExpressionSyntax>(source, expectedOperationTree);
}
[Fact]
public void ExplicitNamedArgument()
{
string source = @"
class P
{
static void M1()
{
/*<bind>*/M2(x: 1, y: """")/*</bind>*/;
}
static void M2(int x, string y = null) { }
}
";
string expectedOperationTree = @"
IInvocationExpression (static void P.M2(System.Int32 x, [System.String y = null])) (OperationKind.InvocationExpression, Type: System.Void)
IArgument (ArgumentKind.Named Matching Parameter: x) (OperationKind.Argument)
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1)
IArgument (ArgumentKind.Named Matching Parameter: y) (OperationKind.Argument)
ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: )
";
VerifyOperationTreeForTest<InvocationExpressionSyntax>(source, expectedOperationTree);
}
[Fact]
public void OutOfOrderExplicitNamedArgument()
{
string source = @"
class P
{
static void M1()
{
/*<bind>*/M2(y: """", x: 1)/*</bind>*/;
}
static void M2(int x = 1, string y = null) { }
}
";
string expectedOperationTree = @"
IInvocationExpression (static void P.M2([System.Int32 x = 1], [System.String y = null])) (OperationKind.InvocationExpression, Type: System.Void)
IArgument (ArgumentKind.Named Matching Parameter: y) (OperationKind.Argument)
ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: )
IArgument (ArgumentKind.Named Matching Parameter: x) (OperationKind.Argument)
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1)
";
VerifyOperationTreeForTest<InvocationExpressionSyntax>(source, expectedOperationTree);
}
[Fact]
public void DefaultNamedArgument()
{
string source = @"
class P
{
static void M1()
{
/*<bind>*/M2(y: """")/*</bind>*/;
}
static void M2(int x = 1, string y = null) { }
}
";
string expectedOperationTree = @"
IInvocationExpression (static void P.M2([System.Int32 x = 1], [System.String y = null])) (OperationKind.InvocationExpression, Type: System.Void)
IArgument (ArgumentKind.Named Matching Parameter: y) (OperationKind.Argument)
ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: )
IArgument (ArgumentKind.DefaultValue Matching Parameter: x) (OperationKind.Argument)
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1)
";
VerifyOperationTreeForTest<InvocationExpressionSyntax>(source, expectedOperationTree);
}
[Fact]
public void RefAndOutArguments()
{
string source = @"
class P
{
void M1()
{
int a = 1;
int b;
/*<bind>*/M2(ref a, out b)/*</bind>*/;
}
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)
Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P)
IArgument (ArgumentKind.Positional Matching Parameter: x) (OperationKind.Argument)
ILocalReferenceExpression: a (OperationKind.LocalReferenceExpression, Type: System.Int32)
IArgument (ArgumentKind.Positional Matching Parameter: y) (OperationKind.Argument)
ILocalReferenceExpression: b (OperationKind.LocalReferenceExpression, Type: System.Int32)
";
VerifyOperationTreeForTest<InvocationExpressionSyntax>(source, expectedOperationTree);
}
[Fact]
public void NamedRefAndOutArguments()
{
string source = @"
class P
{
void M1()
{
int a = 1;
int b;
/*<bind>*/M2(y: out b, x: ref a)/*</bind>*/;
}
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)
Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P)
IArgument (ArgumentKind.Named Matching Parameter: y) (OperationKind.Argument)
ILocalReferenceExpression: b (OperationKind.LocalReferenceExpression, Type: System.Int32)
IArgument (ArgumentKind.Named Matching Parameter: x) (OperationKind.Argument)
ILocalReferenceExpression: a (OperationKind.LocalReferenceExpression, Type: System.Int32)
";
VerifyOperationTreeForTest<InvocationExpressionSyntax>(source, expectedOperationTree);
}
[Fact]
public void OmittedParamsArrayArgument()
{
string source = @"
class P
{
static void M1(string[] args)
{
/*<bind>*/M2("""")/*</bind>*/;
}
static void M2(string str, params int[] array) { }
}
";
string expectedOperationTree = @"
IInvocationExpression (static void P.M2(System.String str, params System.Int32[] array)) (OperationKind.InvocationExpression, Type: System.Void)
IArgument (ArgumentKind.Positional Matching Parameter: str) (OperationKind.Argument)
ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: )
IArgument (ArgumentKind.ParamArray Matching Parameter: array) (OperationKind.Argument)
IArrayCreationExpression (Dimension sizes: 1, Element Type: System.Int32) (OperationKind.ArrayCreationExpression, Type: System.Int32[])
ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: null, Constant: 0)
IArrayInitializer (OperationKind.ArrayInitializer)
";
VerifyOperationTreeForTest<InvocationExpressionSyntax>(source, expectedOperationTree);
}
[Fact]
public void ParamsArrayArguments()
{
string source = @"
class P
{
static void M1(string[] args)
{
/*<bind>*/M2("""", 1, 2)/*</bind>*/;
}
static void M2(string str, params int[] array) { }
}
";
string expectedOperationTree = @"
IInvocationExpression (static void P.M2(System.String str, params System.Int32[] array)) (OperationKind.InvocationExpression, Type: System.Void)
IArgument (ArgumentKind.Positional Matching Parameter: str) (OperationKind.Argument)
ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: )
IArgument (ArgumentKind.ParamArray Matching Parameter: array) (OperationKind.Argument)
IArrayCreationExpression (Dimension sizes: 1, Element Type: System.Int32) (OperationKind.ArrayCreationExpression, Type: System.Int32[])
ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: null, Constant: 2)
IArrayInitializer (OperationKind.ArrayInitializer)
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1)
ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2)
";
VerifyOperationTreeForTest<InvocationExpressionSyntax>(source, expectedOperationTree);
}
[Fact]
public void ArrayAsParamsArrayArgument()
{
string source = @"
class P
{
static void M1(string[] args)
{
/*<bind>*/M2("""", new int[] { 1, 2 })/*</bind>*/;
}
static void M2(string str, params int[] array) { }
}
";
string expectedOperationTree = @"
IInvocationExpression (static void P.M2(System.String str, params System.Int32[] array)) (OperationKind.InvocationExpression, Type: System.Void)
IArgument (ArgumentKind.Positional Matching Parameter: str) (OperationKind.Argument)
ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: )
IArgument (ArgumentKind.Positional Matching Parameter: array) (OperationKind.Argument)
IArrayCreationExpression (Dimension sizes: 1, Element Type: System.Int32) (OperationKind.ArrayCreationExpression, Type: System.Int32[])
ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2)
IArrayInitializer (OperationKind.ArrayInitializer)
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1)
ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2)
";
VerifyOperationTreeForTest<InvocationExpressionSyntax>(source, expectedOperationTree);
}
[Fact]
public void NamedParamsArrayArgument()
{
string source = @"
class P
{
static void M1(string[] args)
{
/*<bind>*/M2(array: 1, str: """")/*</bind>*/;
}
static void M2(string str, params int[] array) { }
}
";
string expectedOperationTree = @"
IInvocationExpression (static void P.M2(System.String str, params System.Int32[] array)) (OperationKind.InvocationExpression, Type: System.Void)
IArgument (ArgumentKind.ParamArray Matching Parameter: array) (OperationKind.Argument)
IArrayCreationExpression (Dimension sizes: 1, Element Type: System.Int32) (OperationKind.ArrayCreationExpression, Type: System.Int32[])
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: null, Constant: 1)
IArrayInitializer (OperationKind.ArrayInitializer)
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1)
IArgument (ArgumentKind.Named Matching Parameter: str) (OperationKind.Argument)
ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: )
";
VerifyOperationTreeForTest<InvocationExpressionSyntax>(source, expectedOperationTree);
}
[Fact]
public void ArrayAsNamedParamsArrayArgument()
{
string source = @"
class P
{
static void M1(string[] args)
{
/*<bind>*/M2(array: new[] { 1 }, str: """")/*</bind>*/;
}
static void M2(string str, params int[] array) { }
}
";
string expectedOperationTree = @"
IInvocationExpression (static void P.M2(System.String str, params System.Int32[] array)) (OperationKind.InvocationExpression, Type: System.Void)
IArgument (ArgumentKind.Named Matching Parameter: array) (OperationKind.Argument)
IArrayCreationExpression (Dimension sizes: 1, Element Type: System.Int32) (OperationKind.ArrayCreationExpression, Type: System.Int32[])
ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1)
IArrayInitializer (OperationKind.ArrayInitializer)
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1)
IArgument (ArgumentKind.Named Matching Parameter: str) (OperationKind.Argument)
ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: )
";
VerifyOperationTreeForTest<InvocationExpressionSyntax>(source, expectedOperationTree);
}
}
}
......@@ -11,7 +11,7 @@ internal partial class IndexedPropertyReferenceExpression : IHasArgumentsExpress
/// and params/ParamArray arguments have been collected into arrays. Default values are supplied for
/// optional arguments missing in source.
/// </summary>
public ImmutableArray<IArgument> ArgumentsInParameterOrder { get; }
public ImmutableArray<IArgument> ArgumentsInEvaluationOrder { get; }
/// <summary>
/// Find the argument supplied for a given parameter of the target method.
/// </summary>
......
......@@ -11,7 +11,7 @@ internal partial class InvocationExpression : IHasArgumentsExpression
/// and params/ParamArray arguments have been collected into arrays. Default values are supplied for
/// optional arguments missing in source.
/// </summary>
public ImmutableArray<IArgument> ArgumentsInParameterOrder { get; }
public ImmutableArray<IArgument> ArgumentsInEvaluationOrder { get; }
/// <summary>
/// Find the argument supplied for a given parameter of the target method.
/// </summary>
......
......@@ -11,7 +11,7 @@ internal partial class ObjectCreationExpression : IHasArgumentsExpression
/// and params/ParamArray arguments have been collected into arrays. Default values are supplied for
/// optional arguments missing in source.
/// </summary>
public ImmutableArray<IArgument> ArgumentsInParameterOrder { get; }
public ImmutableArray<IArgument> ArgumentsInEvaluationOrder { get; }
/// <summary>
/// Find the argument supplied for a given parameter of the target method.
/// </summary>
......
// 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.Generic;
using System.Collections.Immutable;
using System.Threading;
using Roslyn.Utilities;
......@@ -11,12 +12,17 @@ public static class OperationExtensions
/// <summary>
/// Find the argument supplied for a given parameter of the target method.
/// </summary>
/// <param name="hasArgumentExpression">The IHasArgumentsExpression object to get matching argument object from.</param>
/// <param name="hasArgumentsExpression">The IHasArgumentsExpression object to get matching argument object from.</param>
/// <param name="parameter">Parameter of the target method.</param>
/// <returns>Argument corresponding to the parameter.</returns>
public static IArgument GetArgumentMatchingParameter(this IHasArgumentsExpression hasArgumentExpression, IParameterSymbol parameter)
public static IArgument GetArgumentMatchingParameter(this IHasArgumentsExpression hasArgumentsExpression, IParameterSymbol parameter)
{
foreach (var argument in hasArgumentExpression.ArgumentsInEvaluationOrder)
if (hasArgumentsExpression == null || parameter == null)
{
return null;
}
foreach (var argument in hasArgumentsExpression.ArgumentsInEvaluationOrder)
{
if (argument.Parameter == parameter)
{
......@@ -26,6 +32,43 @@ public static IArgument GetArgumentMatchingParameter(this IHasArgumentsExpressio
return null;
}
/// <summary>
/// Arguments of the invocation, excluding the instance argument. Arguments are in parameter order,
/// and params/ParamArray arguments have been collected into arrays. Default values are supplied for
/// optional arguments missing in source.
/// </summary>
public static ImmutableArray<IArgument> ArgumentsInParameterOrder(this IHasArgumentsExpression hasArgumentsExpression)
{
ImmutableArray<IArgument> argumentsInEvaluationOrder = hasArgumentsExpression.ArgumentsInEvaluationOrder;
// If all of the arguments were specified positionally the evaluation order is the same as the parameter order.
if (ArgumentsAreInParameterOrder(argumentsInEvaluationOrder))
{
return argumentsInEvaluationOrder;
}
return argumentsInEvaluationOrder.Sort(
(x, y) =>
{
int x1 = x.Parameter.Ordinal;
int y1 = y.Parameter.Ordinal;
return x1 == y1 ? 0 : (x1 < y1 ? -1 : 1);
});
bool ArgumentsAreInParameterOrder(ImmutableArray<IArgument> arguments)
{
for (int argumentIndex = 0; argumentIndex < arguments.Length; argumentIndex++)
{
if (arguments[argumentIndex].Parameter.Ordinal != argumentIndex)
{
return false;
}
}
return true;
}
}
public static IEnumerable<IOperation> Descendants(this IOperation operation)
{
if (operation == null)
......
......@@ -293,10 +293,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Partial Friend Class BoundCall
Implements IInvocationExpression
Private Function IHasArgumentsExpression_GetArgumentMatchingParameter(parameter As IParameterSymbol) As IArgument Implements IHasArgumentsExpression.GetArgumentMatchingParameter
Return ArgumentMatchingParameter(Me.Arguments, parameter, Me.Method.Parameters)
End Function
Private ReadOnly Property IHasArgumentsExpression_ArgumentsInEvaluationOrder As ImmutableArray(Of IArgument) Implements IHasArgumentsExpression.ArgumentsInEvaluationOrder
Get
Return DeriveArguments(Me.Arguments, Me.Method.Parameters)
......@@ -340,23 +336,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return visitor.VisitInvocationExpression(Me, argument)
End Function
Friend Shared Function ArgumentMatchingParameter(arguments As ImmutableArray(Of BoundExpression), parameter As IParameterSymbol, parameters As ImmutableArray(Of Symbols.ParameterSymbol)) As IArgument
Dim index As Integer = parameter.Ordinal
If index <= arguments.Length Then
Return DeriveArgument(index, arguments(index), parameters)
End If
Return Nothing
End Function
Friend Shared Function DeriveArguments(boundArguments As ImmutableArray(Of BoundExpression), parameters As ImmutableArray(Of Symbols.ParameterSymbol)) As ImmutableArray(Of IArgument)
Dim argumentsLength As Integer = boundArguments.Length
Dim arguments As ImmutableArray(Of IArgument).Builder = ImmutableArray.CreateBuilder(Of IArgument)(argumentsLength)
Dim arguments As ArrayBuilder(Of IArgument) = ArrayBuilder(Of IArgument).GetInstance(argumentsLength)
For index As Integer = 0 To argumentsLength - 1 Step 1
arguments.Add(DeriveArgument(index, boundArguments(index), parameters))
Next
Return arguments.ToImmutable()
Return arguments.ToImmutableAndFree()
End Function
Private Shared ReadOnly s_argumentMappings As New System.Runtime.CompilerServices.ConditionalWeakTable(Of BoundExpression, IArgument)
......@@ -1168,10 +1155,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private Shared ReadOnly s_memberInitializersMappings As New System.Runtime.CompilerServices.ConditionalWeakTable(Of BoundObjectCreationExpression, Object)
Private Function IHasArgumentExpression_GetArgumentMatchingParameter(parameter As IParameterSymbol) As IArgument Implements IHasArgumentsExpression.GetArgumentMatchingParameter
Return BoundCall.ArgumentMatchingParameter(Me.Arguments, parameter, Me.ConstructorOpt.Parameters)
End Function
Private ReadOnly Property IObjectCreationExpression_Constructor As IMethodSymbol Implements IObjectCreationExpression.Constructor
Get
Return Me.ConstructorOpt
......@@ -1463,10 +1446,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
Private Function IHasArgumentsExpression_GetArgumentMatchingParameter(parameter As IParameterSymbol) As IArgument Implements IHasArgumentsExpression.GetArgumentMatchingParameter
Return BoundCall.ArgumentMatchingParameter(Me.Arguments, parameter, Me.PropertySymbol.Parameters)
End Function
Protected Overrides Function ExpressionKind() As OperationKind
Return If(Me.Arguments.Length > 0, OperationKind.IndexedPropertyReferenceExpression, OperationKind.PropertyReferenceExpression)
End Function
......
......@@ -98,6 +98,7 @@
<Compile Include="Diagnostics\GetDiagnosticsTests.vb" />
<Compile Include="IOperation\IOperationTests_InvalidStatement.vb" />
<Compile Include="IOperation\IOperationTests_InvalidExpression.vb" />
<Compile Include="IOperation\IOperationTests_IArgument.vb" />
<Compile Include="IOperation\IOperationTests_IBlockStatement_MethodBlocks.vb" />
<Compile Include="IOperation\IOperationTests_IIfStatement.vb" />
<Compile Include="IOperation\IOperationTests_ISymbolInitializer.vb" />
......
' 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
<Fact()>
Public Sub ExplicitSimpleArgument()
Dim source = <![CDATA[
Module P
Sub M1()
M2(1, "")'BIND:"M2(1, "")"
End Sub
Sub M2(x As Integer, y As String)
End Sub
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IInvocationExpression (static Sub P.M2(x As System.Int32, y As System.String)) (OperationKind.InvocationExpression, Type: System.Void)
IArgument (ArgumentKind.Positional Matching Parameter: x) (OperationKind.Argument)
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1)
IArgument (ArgumentKind.Positional Matching Parameter: y) (OperationKind.Argument)
ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: )
]]>.Value
VerifyOperationTreeForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree)
End Sub
<Fact()>
Public Sub ExplicitSimpleArgumentByName()
Dim source = <![CDATA[
Class P
Sub M1()
M2(y:=1, x:=2)'BIND:"M2(y:=1, x:=2)"
End Sub
Sub M2(x As Integer, y As Integer)
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
IInvocationExpression ( Sub P.M2(x As System.Int32, y As System.Int32)) (OperationKind.InvocationExpression, Type: System.Void)
Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P)
IArgument (ArgumentKind.Positional Matching Parameter: x) (OperationKind.Argument)
ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2)
IArgument (ArgumentKind.Positional Matching Parameter: y) (OperationKind.Argument)
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1)
]]>.Value
VerifyOperationTreeForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree)
End Sub
<Fact()>
Public Sub DefaultArgument()
Dim source = <![CDATA[
Class P
Sub M1()
M2(1)'BIND:"M2(1)"
End Sub
Sub M2(x As Integer, Optional y As Integer = 10)
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
IInvocationExpression ( Sub P.M2(x As System.Int32, [y As System.Int32 = 10])) (OperationKind.InvocationExpression, Type: System.Void)
Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P)
IArgument (ArgumentKind.Positional Matching Parameter: x) (OperationKind.Argument)
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1)
IArgument (ArgumentKind.Positional Matching Parameter: y) (OperationKind.Argument)
ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10)
]]>.Value
VerifyOperationTreeForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree)
End Sub
<Fact()>
Public Sub ParamArrayArgument()
Dim source = <![CDATA[
Class P
Sub M1()
M2(1, 2, 3)'BIND:"M2(1, 2, 3)"
End Sub
Sub M2(a As Integer, ParamArray c As Integer())
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
IInvocationExpression ( Sub P.M2(a As System.Int32, ParamArray c As System.Int32())) (OperationKind.InvocationExpression, Type: System.Void)
Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: P)
IArgument (ArgumentKind.Positional Matching Parameter: a) (OperationKind.Argument)
ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1)
IArgument (ArgumentKind.ParamArray Matching Parameter: c) (OperationKind.Argument)
IArrayCreationExpression (Dimension sizes: 1, Element Type: System.Int32) (OperationKind.ArrayCreationExpression, Type: System.Int32())
ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2)
IArrayInitializer (OperationKind.ArrayInitializer)
ILiteralExpression (Text: 2) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2)
ILiteralExpression (Text: 3) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 3)
]]>.Value
VerifyOperationTreeForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree)
End Sub
End Class
End Namespace
......@@ -536,12 +536,13 @@ public override void VisitInvocationExpression(IInvocationExpression operation)
private void VisitArguments(IHasArgumentsExpression operation)
{
VisitArray(operation.ArgumentsInParameterOrder, "Arguments", logElementCount: true);
VisitArray(operation.ArgumentsInEvaluationOrder, "Arguments", logElementCount: true);
}
public override void VisitArgument(IArgument operation)
{
LogString($"{nameof(IArgument)} (");
LogString($"{nameof(ArgumentKind)}.{operation.ArgumentKind} ");
LogSymbol(operation.Parameter, header: "Matching Parameter", logDisplayString: false);
LogString(")");
LogCommonPropertiesAndNewLine(operation);
......@@ -706,6 +707,7 @@ public override void VisitIndexedPropertyReferenceExpression(IIndexedPropertyRef
LogString($": {operation.Property.ToTestDisplayString()}");
VisitMemberReferenceExpressionCommon(operation);
VisitArguments(operation);
}
public override void VisitUnaryOperatorExpression(IUnaryOperatorExpression operation)
......
......@@ -67,7 +67,7 @@ public sealed override void Initialize(AnalysisContext context)
(operationContext) =>
{
IInvocationExpression invocation = (IInvocationExpression)operationContext.Operation;
foreach (IArgument argument in invocation.ArgumentsInParameterOrder)
foreach (IArgument argument in invocation.ArgumentsInEvaluationOrder)
{
if (argument.Parameter.RefKind == RefKind.Out || argument.Parameter.RefKind == RefKind.Ref)
{
......
......@@ -59,7 +59,7 @@ public sealed override void Initialize(AnalysisContext context)
(operationContext) =>
{
IInvocationExpression invocation = (IInvocationExpression)operationContext.Operation;
foreach (IArgument argument in invocation.ArgumentsInParameterOrder)
foreach (IArgument argument in invocation.ArgumentsInEvaluationOrder)
{
if (argument.Parameter.RefKind == RefKind.Out || argument.Parameter.RefKind == RefKind.Ref)
{
......
......@@ -53,7 +53,7 @@ public sealed override void Initialize(AnalysisContext context)
(operationContext) =>
{
IInvocationExpression invocation = (IInvocationExpression)operationContext.Operation;
foreach (IArgument argument in invocation.ArgumentsInParameterOrder)
foreach (IArgument argument in invocation.ArgumentsInEvaluationOrder)
{
if (argument.Parameter.RefKind == RefKind.Out || argument.Parameter.RefKind == RefKind.Ref)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册