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

Fix IHasArgumentsExpression implementation

上级 aa38ba15
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
<Compile Include="Diagnostics\DiagnosticAnalyzerTests.AllInOne.cs" /> <Compile Include="Diagnostics\DiagnosticAnalyzerTests.AllInOne.cs" />
<Compile Include="Diagnostics\DiagnosticAnalyzerTests.cs" /> <Compile Include="Diagnostics\DiagnosticAnalyzerTests.cs" />
<Compile Include="Diagnostics\GetDiagnosticsTests.cs" /> <Compile Include="Diagnostics\GetDiagnosticsTests.cs" />
<Compile Include="IOperation\IOperationTests_IArgument.cs" />
<Compile Include="IOperation\IOperationTests_IIfStatement.cs" /> <Compile Include="IOperation\IOperationTests_IIfStatement.cs" />
<Compile Include="IOperation\IOperationTests_ISymbolInitializer.cs" /> <Compile Include="IOperation\IOperationTests_ISymbolInitializer.cs" />
<Compile Include="IOperation\IOperationTests_InvalidExpression.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 ...@@ -11,7 +11,7 @@ internal partial class IndexedPropertyReferenceExpression : IHasArgumentsExpress
/// and params/ParamArray arguments have been collected into arrays. Default values are supplied for /// and params/ParamArray arguments have been collected into arrays. Default values are supplied for
/// optional arguments missing in source. /// optional arguments missing in source.
/// </summary> /// </summary>
public ImmutableArray<IArgument> ArgumentsInParameterOrder { get; } public ImmutableArray<IArgument> ArgumentsInEvaluationOrder { get; }
/// <summary> /// <summary>
/// Find the argument supplied for a given parameter of the target method. /// Find the argument supplied for a given parameter of the target method.
/// </summary> /// </summary>
......
...@@ -11,7 +11,7 @@ internal partial class InvocationExpression : IHasArgumentsExpression ...@@ -11,7 +11,7 @@ internal partial class InvocationExpression : IHasArgumentsExpression
/// and params/ParamArray arguments have been collected into arrays. Default values are supplied for /// and params/ParamArray arguments have been collected into arrays. Default values are supplied for
/// optional arguments missing in source. /// optional arguments missing in source.
/// </summary> /// </summary>
public ImmutableArray<IArgument> ArgumentsInParameterOrder { get; } public ImmutableArray<IArgument> ArgumentsInEvaluationOrder { get; }
/// <summary> /// <summary>
/// Find the argument supplied for a given parameter of the target method. /// Find the argument supplied for a given parameter of the target method.
/// </summary> /// </summary>
......
...@@ -11,7 +11,7 @@ internal partial class ObjectCreationExpression : IHasArgumentsExpression ...@@ -11,7 +11,7 @@ internal partial class ObjectCreationExpression : IHasArgumentsExpression
/// and params/ParamArray arguments have been collected into arrays. Default values are supplied for /// and params/ParamArray arguments have been collected into arrays. Default values are supplied for
/// optional arguments missing in source. /// optional arguments missing in source.
/// </summary> /// </summary>
public ImmutableArray<IArgument> ArgumentsInParameterOrder { get; } public ImmutableArray<IArgument> ArgumentsInEvaluationOrder { get; }
/// <summary> /// <summary>
/// Find the argument supplied for a given parameter of the target method. /// Find the argument supplied for a given parameter of the target method.
/// </summary> /// </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. // 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.Generic;
using System.Collections.Immutable;
using System.Threading; using System.Threading;
using Roslyn.Utilities; using Roslyn.Utilities;
...@@ -11,12 +12,17 @@ public static class OperationExtensions ...@@ -11,12 +12,17 @@ public static class OperationExtensions
/// <summary> /// <summary>
/// Find the argument supplied for a given parameter of the target method. /// Find the argument supplied for a given parameter of the target method.
/// </summary> /// </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> /// <param name="parameter">Parameter of the target method.</param>
/// <returns>Argument corresponding to the parameter.</returns> /// <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) if (argument.Parameter == parameter)
{ {
...@@ -26,6 +32,43 @@ public static IArgument GetArgumentMatchingParameter(this IHasArgumentsExpressio ...@@ -26,6 +32,43 @@ public static IArgument GetArgumentMatchingParameter(this IHasArgumentsExpressio
return null; 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) public static IEnumerable<IOperation> Descendants(this IOperation operation)
{ {
if (operation == null) if (operation == null)
......
...@@ -293,10 +293,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -293,10 +293,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Partial Friend Class BoundCall Partial Friend Class BoundCall
Implements IInvocationExpression 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 Private ReadOnly Property IHasArgumentsExpression_ArgumentsInEvaluationOrder As ImmutableArray(Of IArgument) Implements IHasArgumentsExpression.ArgumentsInEvaluationOrder
Get Get
Return DeriveArguments(Me.Arguments, Me.Method.Parameters) Return DeriveArguments(Me.Arguments, Me.Method.Parameters)
...@@ -340,23 +336,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -340,23 +336,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return visitor.VisitInvocationExpression(Me, argument) Return visitor.VisitInvocationExpression(Me, argument)
End Function 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) 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 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 For index As Integer = 0 To argumentsLength - 1 Step 1
arguments.Add(DeriveArgument(index, boundArguments(index), parameters)) arguments.Add(DeriveArgument(index, boundArguments(index), parameters))
Next Next
Return arguments.ToImmutable() Return arguments.ToImmutableAndFree()
End Function End Function
Private Shared ReadOnly s_argumentMappings As New System.Runtime.CompilerServices.ConditionalWeakTable(Of BoundExpression, IArgument) Private Shared ReadOnly s_argumentMappings As New System.Runtime.CompilerServices.ConditionalWeakTable(Of BoundExpression, IArgument)
...@@ -1168,10 +1155,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1168,10 +1155,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private Shared ReadOnly s_memberInitializersMappings As New System.Runtime.CompilerServices.ConditionalWeakTable(Of BoundObjectCreationExpression, Object) 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 Private ReadOnly Property IObjectCreationExpression_Constructor As IMethodSymbol Implements IObjectCreationExpression.Constructor
Get Get
Return Me.ConstructorOpt Return Me.ConstructorOpt
...@@ -1463,10 +1446,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1463,10 +1446,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get End Get
End Property 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 Protected Overrides Function ExpressionKind() As OperationKind
Return If(Me.Arguments.Length > 0, OperationKind.IndexedPropertyReferenceExpression, OperationKind.PropertyReferenceExpression) Return If(Me.Arguments.Length > 0, OperationKind.IndexedPropertyReferenceExpression, OperationKind.PropertyReferenceExpression)
End Function End Function
......
...@@ -98,6 +98,7 @@ ...@@ -98,6 +98,7 @@
<Compile Include="Diagnostics\GetDiagnosticsTests.vb" /> <Compile Include="Diagnostics\GetDiagnosticsTests.vb" />
<Compile Include="IOperation\IOperationTests_InvalidStatement.vb" /> <Compile Include="IOperation\IOperationTests_InvalidStatement.vb" />
<Compile Include="IOperation\IOperationTests_InvalidExpression.vb" /> <Compile Include="IOperation\IOperationTests_InvalidExpression.vb" />
<Compile Include="IOperation\IOperationTests_IArgument.vb" />
<Compile Include="IOperation\IOperationTests_IBlockStatement_MethodBlocks.vb" /> <Compile Include="IOperation\IOperationTests_IBlockStatement_MethodBlocks.vb" />
<Compile Include="IOperation\IOperationTests_IIfStatement.vb" /> <Compile Include="IOperation\IOperationTests_IIfStatement.vb" />
<Compile Include="IOperation\IOperationTests_ISymbolInitializer.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) ...@@ -536,12 +536,13 @@ public override void VisitInvocationExpression(IInvocationExpression operation)
private void VisitArguments(IHasArgumentsExpression operation) private void VisitArguments(IHasArgumentsExpression operation)
{ {
VisitArray(operation.ArgumentsInParameterOrder, "Arguments", logElementCount: true); VisitArray(operation.ArgumentsInEvaluationOrder, "Arguments", logElementCount: true);
} }
public override void VisitArgument(IArgument operation) public override void VisitArgument(IArgument operation)
{ {
LogString($"{nameof(IArgument)} ("); LogString($"{nameof(IArgument)} (");
LogString($"{nameof(ArgumentKind)}.{operation.ArgumentKind} ");
LogSymbol(operation.Parameter, header: "Matching Parameter", logDisplayString: false); LogSymbol(operation.Parameter, header: "Matching Parameter", logDisplayString: false);
LogString(")"); LogString(")");
LogCommonPropertiesAndNewLine(operation); LogCommonPropertiesAndNewLine(operation);
...@@ -706,6 +707,7 @@ public override void VisitIndexedPropertyReferenceExpression(IIndexedPropertyRef ...@@ -706,6 +707,7 @@ public override void VisitIndexedPropertyReferenceExpression(IIndexedPropertyRef
LogString($": {operation.Property.ToTestDisplayString()}"); LogString($": {operation.Property.ToTestDisplayString()}");
VisitMemberReferenceExpressionCommon(operation); VisitMemberReferenceExpressionCommon(operation);
VisitArguments(operation);
} }
public override void VisitUnaryOperatorExpression(IUnaryOperatorExpression operation) public override void VisitUnaryOperatorExpression(IUnaryOperatorExpression operation)
......
...@@ -67,7 +67,7 @@ public sealed override void Initialize(AnalysisContext context) ...@@ -67,7 +67,7 @@ public sealed override void Initialize(AnalysisContext context)
(operationContext) => (operationContext) =>
{ {
IInvocationExpression invocation = (IInvocationExpression)operationContext.Operation; 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) if (argument.Parameter.RefKind == RefKind.Out || argument.Parameter.RefKind == RefKind.Ref)
{ {
......
...@@ -59,7 +59,7 @@ public sealed override void Initialize(AnalysisContext context) ...@@ -59,7 +59,7 @@ public sealed override void Initialize(AnalysisContext context)
(operationContext) => (operationContext) =>
{ {
IInvocationExpression invocation = (IInvocationExpression)operationContext.Operation; 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) if (argument.Parameter.RefKind == RefKind.Out || argument.Parameter.RefKind == RefKind.Ref)
{ {
......
...@@ -53,7 +53,7 @@ public sealed override void Initialize(AnalysisContext context) ...@@ -53,7 +53,7 @@ public sealed override void Initialize(AnalysisContext context)
(operationContext) => (operationContext) =>
{ {
IInvocationExpression invocation = (IInvocationExpression)operationContext.Operation; 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) 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.
先完成此消息的编辑!
想要评论请 注册