提交 68e37cf1 编写于 作者: F Fred Silberberg 提交者: GitHub

Merge pull request #20966 from 333fred/dynamic-member-reference

Added IDynamicMemberReferenceExpression
......@@ -69,6 +69,8 @@ private IOperation CreateInternal(BoundNode boundNode)
return CreateBoundObjectInitializerMemberOperation((BoundObjectInitializerMember)boundNode);
case BoundKind.CollectionElementInitializer:
return CreateBoundCollectionElementInitializerOperation((BoundCollectionElementInitializer)boundNode);
case BoundKind.DynamicMemberAccess:
return CreateBoundDynamicMemberAccessOperation((BoundDynamicMemberAccess)boundNode);
case BoundKind.DynamicCollectionElementInitializer:
return CreateBoundDynamicCollectionElementInitializerOperation((BoundDynamicCollectionElementInitializer)boundNode);
case BoundKind.UnboundLambda:
......@@ -519,6 +521,22 @@ private ICollectionElementInitializerExpression CreateBoundCollectionElementInit
return new LazyCollectionElementInitializerExpression(addMethod, arguments, isDynamic, syntax, type, constantValue);
}
private IDynamicMemberReferenceExpression CreateBoundDynamicMemberAccessOperation(BoundDynamicMemberAccess boundDynamicMemberAccess)
{
Lazy<IOperation> instance = new Lazy<IOperation>(() => Create(boundDynamicMemberAccess.Receiver));
string memberName = boundDynamicMemberAccess.Name;
ImmutableArray<ITypeSymbol> typeArguments = ImmutableArray<ITypeSymbol>.Empty;
if (!boundDynamicMemberAccess.TypeArgumentsOpt.IsDefault)
{
typeArguments = ImmutableArray<ITypeSymbol>.CastUp(boundDynamicMemberAccess.TypeArgumentsOpt);
}
ITypeSymbol containingType = null;
SyntaxNode syntaxNode = boundDynamicMemberAccess.Syntax;
ITypeSymbol type = boundDynamicMemberAccess.Type;
Optional<object> constantValue = ConvertToOptional(boundDynamicMemberAccess.ConstantValue);
return new LazyDynamicMemberReferenceExpression(instance, memberName, typeArguments, containingType, syntaxNode, type, constantValue);
}
private ICollectionElementInitializerExpression CreateBoundDynamicCollectionElementInitializerOperation(BoundDynamicCollectionElementInitializer boundCollectionElementInitializer)
{
IMethodSymbol addMethod = null;
......
......@@ -38,4 +38,4 @@
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="..\..\..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
</Project>
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public partial class IOperationTests : SemanticModelTestBase
{
[Fact]
public void IDynamicMemberReferenceExpression_SimplePropertyAccess()
{
string source = @"
using System;
namespace ConsoleApp1
{
class C1
{
static void M1()
{
dynamic d = null;
int i = /*<bind>*/d.Prop1/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IDynamicMemberReferenceExpression (Member Name: ""Prop1"", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic) (Syntax: 'd.Prop1')
Type Arguments(0)
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'd')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void IDynamicMemberReferenceExpression_InvalidPropertyAccess()
{
string source = @"
using System;
namespace ConsoleApp1
{
class C1
{
static void M1()
{
dynamic d = null;
int i = /*<bind>*/d./*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IDynamicMemberReferenceExpression (Member Name: """", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic, IsInvalid) (Syntax: 'd./*</bind>*/')
Type Arguments(0)
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'd')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS1001: Identifier expected
// int i = /*<bind>*/d./*</bind>*/;
Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(11, 44)
};
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void IDynamicMemberReferenceExpression_SimpleMethodCall()
{
string source = @"
using System;
namespace ConsoleApp1
{
class C1
{
static void M1()
{
dynamic d = null;
/*<bind>*/d.GetValue()/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IOperation: (OperationKind.None) (Syntax: 'd.GetValue()')
Children(1):
IDynamicMemberReferenceExpression (Member Name: ""GetValue"", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic) (Syntax: 'd.GetValue')
Type Arguments(0)
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'd')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<InvocationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void IDynamicMemberReferenceExpression_InvalidMethodCall_MissingName()
{
string source = @"
namespace ConsoleApp1
{
class C1
{
static void M1()
{
dynamic d = null;
/*<bind>*/d.()/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IOperation: (OperationKind.None, IsInvalid) (Syntax: 'd.()')
Children(1):
IDynamicMemberReferenceExpression (Member Name: """", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic, IsInvalid) (Syntax: 'd.')
Type Arguments(0)
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'd')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS1001: Identifier expected
// /*<bind>*/d.()/*</bind>*/;
Diagnostic(ErrorCode.ERR_IdentifierExpected, "(").WithLocation(9, 25)
};
VerifyOperationTreeAndDiagnosticsForTest<InvocationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void IDynamicMemberReferenceExpression_InvalidMethodCall_MissingCloseParen()
{
string source = @"
namespace ConsoleApp1
{
class C1
{
static void M1()
{
dynamic d = null;
/*<bind>*/d.GetValue(/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IOperation: (OperationKind.None, IsInvalid) (Syntax: 'd.GetValue(/*</bind>*/')
Children(1):
IDynamicMemberReferenceExpression (Member Name: ""GetValue"", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic) (Syntax: 'd.GetValue')
Type Arguments(0)
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'd')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS1026: ) expected
// /*<bind>*/d.GetValue(/*</bind>*/;
Diagnostic(ErrorCode.ERR_CloseParenExpected, ";").WithLocation(9, 45)
};
VerifyOperationTreeAndDiagnosticsForTest<InvocationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void IDynamicMemberReference_GenericMethodCall_SingleGeneric()
{
string source = @"
namespace ConsoleApp1
{
class C1
{
static void M1()
{
dynamic d = null;
/*<bind>*/d.GetValue<int>()/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IOperation: (OperationKind.None) (Syntax: 'd.GetValue<int>()')
Children(1):
IDynamicMemberReferenceExpression (Member Name: ""GetValue"", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic) (Syntax: 'd.GetValue<int>')
Type Arguments(1):
Symbol: System.Int32
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'd')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<InvocationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void IDynamicMemberReference_GenericMethodCall_MultipleGeneric()
{
string source = @"
namespace ConsoleApp1
{
class C1
{
static void M1()
{
dynamic d = null;
/*<bind>*/d.GetValue<int, C1>()/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IOperation: (OperationKind.None) (Syntax: 'd.GetValue<int, C1>()')
Children(1):
IDynamicMemberReferenceExpression (Member Name: ""GetValue"", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic) (Syntax: 'd.GetValue<int, C1>')
Type Arguments(2):
Symbol: System.Int32
Symbol: ConsoleApp1.C1
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'd')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<InvocationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void IDynamicMemberReferenceExpression_GenericPropertyAccess()
{
string source = @"
namespace ConsoleApp1
{
class C1
{
static void M1()
{
dynamic d = null;
/*<bind>*/d.GetValue<int, C1>/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IDynamicMemberReferenceExpression (Member Name: ""GetValue"", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic, IsInvalid) (Syntax: 'd.GetValue<int, C1>')
Type Arguments(2):
Symbol: System.Int32
Symbol: ConsoleApp1.C1
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: dynamic, IsInvalid) (Syntax: 'd')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0307: The property 'GetValue' cannot be used with type arguments
// /*<bind>*/d.GetValue<int, C1>/*</bind>*/;
Diagnostic(ErrorCode.ERR_TypeArgsNotAllowed, "GetValue<int, C1>").WithArguments("GetValue", "property").WithLocation(9, 25),
// CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement
// /*<bind>*/d.GetValue<int, C1>/*</bind>*/;
Diagnostic(ErrorCode.ERR_IllegalStatement, "d.GetValue<int, C1>").WithLocation(9, 23)
};
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void IDynamicMemberReferenceExpression_GenericMethodCall_InvalidGenericParam()
{
string source = @"
namespace ConsoleApp1
{
class C1
{
static void M1()
{
dynamic d = null;
/*<bind>*/d.GetValue<int,>()/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IOperation: (OperationKind.None, IsInvalid) (Syntax: 'd.GetValue<int,>()')
Children(1):
IDynamicMemberReferenceExpression (Member Name: ""GetValue"", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic, IsInvalid) (Syntax: 'd.GetValue<int,>')
Type Arguments(2):
Symbol: System.Int32
Symbol: ?
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'd')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS1031: Type expected
// /*<bind>*/d.GetValue<int,>()/*</bind>*/;
Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(9, 38)
};
VerifyOperationTreeAndDiagnosticsForTest<InvocationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void IDynamicMemberReferenceExpression_NestedDynamicPropertyAccess()
{
string source = @"
namespace ConsoleApp1
{
class C1
{
static void M1()
{
dynamic d = null;
object o = /*<bind>*/d.Prop1.Prop2/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IDynamicMemberReferenceExpression (Member Name: ""Prop2"", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic) (Syntax: 'd.Prop1.Prop2')
Type Arguments(0)
Instance Receiver: IDynamicMemberReferenceExpression (Member Name: ""Prop1"", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic) (Syntax: 'd.Prop1')
Type Arguments(0)
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'd')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void IDynamicMemberReferenceExpression_NestedDynamicMethodAccess()
{
string source = @"
namespace ConsoleApp1
{
class C1
{
static void M1()
{
dynamic d = null;
/*<bind>*/d.Method1().Method2()/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IOperation: (OperationKind.None) (Syntax: 'd.Method1().Method2()')
Children(1):
IDynamicMemberReferenceExpression (Member Name: ""Method2"", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic) (Syntax: 'd.Method1().Method2')
Type Arguments(0)
Instance Receiver: IOperation: (OperationKind.None) (Syntax: 'd.Method1()')
Children(1):
IDynamicMemberReferenceExpression (Member Name: ""Method1"", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic) (Syntax: 'd.Method1')
Type Arguments(0)
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'd')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<InvocationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void IDynamicMemberReferenceExpression_NestedDynamicPropertyAndMethodAccess()
{
string source = @"
using System;
namespace ConsoleApp1
{
class C1
{
static void M1()
{
dynamic d = null;
int i = /*<bind>*/d.Method1<int>().Prop2/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IDynamicMemberReferenceExpression (Member Name: ""Prop2"", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic) (Syntax: 'd.Method1<int>().Prop2')
Type Arguments(0)
Instance Receiver: IOperation: (OperationKind.None) (Syntax: 'd.Method1<int>()')
Children(1):
IDynamicMemberReferenceExpression (Member Name: ""Method1"", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic) (Syntax: 'd.Method1<int>')
Type Arguments(1):
Symbol: System.Int32
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'd')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
}
}
......@@ -931,9 +931,9 @@ class C
Left: IBinaryOperatorExpression (BinaryOperationKind.Invalid) (OperationKind.BinaryOperatorExpression, Type: dynamic) (Syntax: 'd.GetType() == t')
Left: IOperation: (OperationKind.None) (Syntax: 'd.GetType()')
Children(1):
IOperation: (OperationKind.None) (Syntax: 'd.GetType')
Children(1):
IParameterReferenceExpression: d (OperationKind.ParameterReferenceExpression, Type: dynamic) (Syntax: 'd')
IDynamicMemberReferenceExpression (Member Name: ""GetType"", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic) (Syntax: 'd.GetType')
Type Arguments(0)
Instance Receiver: IParameterReferenceExpression: d (OperationKind.ParameterReferenceExpression, Type: dynamic) (Syntax: 'd')
Right: IParameterReferenceExpression: t (OperationKind.ParameterReferenceExpression, Type: System.Type) (Syntax: 't')
Right: IInvocationExpression (virtual System.Boolean System.ValueType.Equals(System.Object obj)) (OperationKind.InvocationExpression, Type: System.Boolean) (Syntax: '((T)d).Equals(x)')
Instance Receiver: IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: T) (Syntax: '(T)d')
......
......@@ -549,9 +549,9 @@ public void M(dynamic x, int y)
string expectedOperationTree = @"
IOperation: (OperationKind.None) (Syntax: 'x.M(y)')
Children(2):
IOperation: (OperationKind.None) (Syntax: 'x.M')
Children(1):
IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: dynamic) (Syntax: 'x')
IDynamicMemberReferenceExpression (Member Name: ""M"", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: dynamic) (Syntax: 'x.M')
Type Arguments(0)
Instance Receiver: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: dynamic) (Syntax: 'x')
IParameterReferenceExpression: y (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'y')
";
var expectedDiagnostics = DiagnosticDescription.None;
......
......@@ -142,4 +142,4 @@
<Import Project="..\..\..\Dependencies\CodeAnalysis.Debugging\Microsoft.CodeAnalysis.Debugging.projitems" Label="Shared" />
<Import Project="..\..\..\Dependencies\PooledObjects\Microsoft.CodeAnalysis.PooledObjects.projitems" Label="Shared" />
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
</Project>
......@@ -2668,7 +2668,7 @@ internal abstract partial class BaseInvocationExpression : Operation, IHasArgume
/// Arguments of the invocation, excluding the instance argument. Arguments are in evaluation order.
/// </summary>
/// <remarks>
/// If the invocation is in its expanded form, then params/ParamArray arguments would be collected into arrays.
/// 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.
/// </remarks>
public abstract ImmutableArray<IArgument> ArgumentsInEvaluationOrder { get; }
......@@ -2712,7 +2712,7 @@ internal sealed partial class InvocationExpression : BaseInvocationExpression, I
/// Arguments of the invocation, excluding the instance argument. Arguments are in evaluation order.
/// </summary>
/// <remarks>
/// If the invocation is in its expanded form, then params/ParamArray arguments would be collected into arrays.
/// 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.
/// </remarks>
public override ImmutableArray<IArgument> ArgumentsInEvaluationOrder { get; }
......@@ -2740,7 +2740,7 @@ public LazyInvocationExpression(IMethodSymbol targetMethod, Lazy<IOperation> ins
/// Arguments of the invocation, excluding the instance argument. Arguments are in evaluation order.
/// </summary>
/// <remarks>
/// If the invocation is in its expanded form, then params/ParamArray arguments would be collected into arrays.
/// 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.
/// </remarks>
public override ImmutableArray<IArgument> ArgumentsInEvaluationOrder => _lazyArgumentsInEvaluationOrder.Value;
......@@ -2951,23 +2951,34 @@ public LazyLambdaExpression(IMethodSymbol signature, Lazy<IBlockStatement> body,
}
/// <summary>
/// Represents a late-bound reference to a member of a class or struct.
/// Represents a dynamic access to a member of a class, struct, or module.
/// </summary>
internal abstract partial class BaseLateBoundMemberReferenceExpression : Operation, ILateBoundMemberReferenceExpression
internal abstract partial class BaseDynamicMemberReferenceExpression : Operation, IDynamicMemberReferenceExpression
{
protected BaseLateBoundMemberReferenceExpression(string memberName, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue) :
base(OperationKind.LateBoundMemberReferenceExpression, syntax, type, constantValue)
protected BaseDynamicMemberReferenceExpression(string memberName, ImmutableArray<ITypeSymbol> typeArguments, ITypeSymbol containingType, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue) :
base(OperationKind.DynamicMemberReferenceExpression, syntax, type, constantValue)
{
MemberName = memberName;
TypeArguments = typeArguments;
ContainingType = containingType;
}
/// <summary>
/// Instance used to bind the member reference.
/// Instance receiver. In VB, this can be null.
/// </summary>
public abstract IOperation Instance { get; }
/// <summary>
/// Name of the member.
/// Referenced member.
/// </summary>
public string MemberName { get; }
/// <summary>
/// Type arguments.
/// </summary>
public ImmutableArray<ITypeSymbol> TypeArguments { get; }
/// <summary>
/// The containing type of this expression. In C#, this will always be null.
/// </summary>
public ITypeSymbol ContainingType { get; }
public override IEnumerable<IOperation> Children
{
get
......@@ -2977,43 +2988,45 @@ public override IEnumerable<IOperation> Children
}
public override void Accept(OperationVisitor visitor)
{
visitor.VisitLateBoundMemberReferenceExpression(this);
visitor.VisitDynamicMemberReferenceExpression(this);
}
public override TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, TResult> visitor, TArgument argument)
{
return visitor.VisitLateBoundMemberReferenceExpression(this, argument);
return visitor.VisitDynamicMemberReferenceExpression(this, argument);
}
}
/// <summary>
/// Represents a late-bound reference to a member of a class or struct.
/// Represents a dynamic access to a member of a class, struct, or module.
/// </summary>
internal sealed partial class LateBoundMemberReferenceExpression : BaseLateBoundMemberReferenceExpression, ILateBoundMemberReferenceExpression
internal sealed partial class DynamicMemberReferenceExpression : BaseDynamicMemberReferenceExpression, IDynamicMemberReferenceExpression
{
public LateBoundMemberReferenceExpression(IOperation instance, string memberName, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue) :
base(memberName, syntax, type, constantValue)
public DynamicMemberReferenceExpression(IOperation instance, string memberName, ImmutableArray<ITypeSymbol> typeArguments, ITypeSymbol containingType, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue) :
base(memberName, typeArguments, containingType, syntax, type, constantValue)
{
Instance = instance;
}
/// <summary>
/// Instance used to bind the member reference.
/// Instance receiver. In VB, this can be null.
/// </summary>
public override IOperation Instance { get; }
}
/// <summary>
/// Represents a late-bound reference to a member of a class or struct.
/// <summary>
/// Represents a dynamic access to a member of a class, struct, or module.
/// </summary>
internal sealed partial class LazyLateBoundMemberReferenceExpression : BaseLateBoundMemberReferenceExpression, ILateBoundMemberReferenceExpression
internal sealed partial class LazyDynamicMemberReferenceExpression : BaseDynamicMemberReferenceExpression, IDynamicMemberReferenceExpression
{
private readonly Lazy<IOperation> _lazyInstance;
public LazyLateBoundMemberReferenceExpression(Lazy<IOperation> instance, string memberName, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue) : base(memberName, syntax, type, constantValue)
public LazyDynamicMemberReferenceExpression(Lazy<IOperation> lazyInstance, string memberName, ImmutableArray<ITypeSymbol> typeArguments, ITypeSymbol containingType, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue) :
base(memberName, typeArguments, containingType, syntax, type, constantValue)
{
_lazyInstance = instance ?? throw new System.ArgumentNullException(nameof(instance));
_lazyInstance = lazyInstance;
}
/// <summary>
/// Instance used to bind the member reference.
/// Instance receiver. In VB, this can be null.
/// </summary>
public override IOperation Instance => _lazyInstance.Value;
}
......@@ -3375,7 +3388,7 @@ internal abstract partial class BaseObjectCreationExpression : Operation, IHasAr
/// Arguments of the invocation, excluding the instance argument. Arguments are in evaluation order.
/// </summary>
/// <remarks>
/// If the invocation is in its expanded form, then params/ParamArray arguments would be collected into arrays.
/// 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.
/// </remarks>
public abstract ImmutableArray<IArgument> ArgumentsInEvaluationOrder { get; }
......@@ -3419,7 +3432,7 @@ internal sealed partial class ObjectCreationExpression : BaseObjectCreationExpre
/// Arguments of the invocation, excluding the instance argument. Arguments are in evaluation order.
/// </summary>
/// <remarks>
/// If the invocation is in its expanded form, then params/ParamArray arguments would be collected into arrays.
/// 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.
/// </remarks>
public override ImmutableArray<IArgument> ArgumentsInEvaluationOrder { get; }
......@@ -3447,7 +3460,7 @@ public LazyObjectCreationExpression(IMethodSymbol constructor, Lazy<IObjectOrCol
/// Arguments of the invocation, excluding the instance argument. Arguments are in evaluation order.
/// </summary>
/// <remarks>
/// If the invocation is in its expanded form, then params/ParamArray arguments would be collected into arrays.
/// 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.
/// </remarks>
public override ImmutableArray<IArgument> ArgumentsInEvaluationOrder => _lazyArgumentsInEvaluationOrder.Value;
......@@ -3869,7 +3882,7 @@ internal abstract partial class BasePropertyReferenceExpression : MemberReferenc
/// Arguments of the invocation, excluding the instance argument. Arguments are in evaluation order.
/// </summary>
/// <remarks>
/// If the invocation is in its expanded form, then params/ParamArray arguments would be collected into arrays.
/// 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.
/// </remarks>
public abstract ImmutableArray<IArgument> ArgumentsInEvaluationOrder { get; }
......@@ -3914,7 +3927,7 @@ internal sealed partial class PropertyReferenceExpression : BasePropertyReferenc
/// Arguments of the invocation, excluding the instance argument. Arguments are in evaluation order.
/// </summary>
/// <remarks>
/// If the invocation is in its expanded form, then params/ParamArray arguments would be collected into arrays.
/// 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.
/// </remarks>
public override ImmutableArray<IArgument> ArgumentsInEvaluationOrder { get; }
......@@ -3951,7 +3964,7 @@ internal sealed partial class LazyPropertyReferenceExpression : BasePropertyRefe
/// Arguments of the invocation, excluding the instance argument. Arguments are in evaluation order.
/// </summary>
/// <remarks>
/// If the invocation is in its expanded form, then params/ParamArray arguments would be collected into arrays.
/// 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.
/// </remarks>
public override ImmutableArray<IArgument> ArgumentsInEvaluationOrder => _lazyArgumentsInEvaluationOrder.Value;
......
......@@ -5,22 +5,32 @@
namespace Microsoft.CodeAnalysis.Semantics
{
/// <summary>
/// Represents a late-bound reference to a member of a class or struct.
/// Represents a dynamic reference to a member of a class, struct, or module.
/// </summary>
/// <remarks>
/// This interface is reserved for implementation by its associated APIs. We reserve the right to
/// change it in the future.
/// </remarks>
public interface ILateBoundMemberReferenceExpression : IOperation
public interface IDynamicMemberReferenceExpression : IOperation
{
/// <summary>
/// Instance used to bind the member reference.
/// Instance receiver. In VB, this can be null.
/// </summary>
IOperation Instance { get; }
/// <summary>
/// Name of the member.
/// Referenced member.
/// </summary>
string MemberName { get; }
/// <summary>
/// Type arguments.
/// </summary>
ImmutableArray<ITypeSymbol> TypeArguments { get; }
/// <summary>
/// The containing type of this expression. In C#, this will always be null.
/// </summary>
ITypeSymbol ContainingType { get; }
}
}
......@@ -140,6 +140,8 @@ public enum OperationKind
TupleExpression = 0x124,
/// <summary>Indicates an <see cref="IDynamicObjectCreationExpression"/>.</summary>
DynamicObjectCreationExpression = 0x125,
/// <summary>Indicates an <see cref="IDynamicMemberReferenceExpression"/>.</summary>
DynamicMemberReferenceExpression = 0x126,
// Expressions that occur only in C#.
......@@ -164,8 +166,7 @@ public enum OperationKind
/// <summary>Indicates an <see cref="IOmittedArgumentExpression"/>.</summary>
OmittedArgumentExpression = 0x300,
/// <summary>Indicates an <see cref="ILateBoundMemberReferenceExpression"/>.</summary>
LateBoundMemberReferenceExpression = 0x301,
// 0x301 was removed, and is available for use.
/// <summary>Indicates an <see cref="IPlaceholderExpression"/>.</summary>
PlaceholderExpression = 0x302,
......
......@@ -395,7 +395,7 @@ public virtual void VisitParenthesizedExpression(IParenthesizedExpression operat
DefaultVisit(operation);
}
public virtual void VisitLateBoundMemberReferenceExpression(ILateBoundMemberReferenceExpression operation)
public virtual void VisitDynamicMemberReferenceExpression(IDynamicMemberReferenceExpression operation)
{
DefaultVisit(operation);
}
......@@ -865,7 +865,7 @@ public virtual TResult VisitParenthesizedExpression(IParenthesizedExpression ope
return DefaultVisit(operation, argument);
}
public virtual TResult VisitLateBoundMemberReferenceExpression(ILateBoundMemberReferenceExpression operation, TArgument argument)
public virtual TResult VisitDynamicMemberReferenceExpression(IDynamicMemberReferenceExpression operation, TArgument argument)
{
return DefaultVisit(operation, argument);
}
......@@ -888,7 +888,7 @@ public virtual TResult VisitInvalidStatement(IInvalidStatement operation, TArgum
public virtual TResult VisitInvalidExpression(IInvalidExpression operation, TArgument argument)
{
return DefaultVisit(operation, argument);
}
}
public virtual TResult VisitLocalFunctionStatement(ILocalFunctionStatement operation, TArgument argument)
{
......
......@@ -67,6 +67,7 @@ Microsoft.CodeAnalysis.OperationKind.DeclarationPattern = 1040 -> Microsoft.Code
Microsoft.CodeAnalysis.OperationKind.DefaultCaseClause = 1042 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.DefaultValueExpression = 512 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.DynamicObjectCreationExpression = 293 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.DynamicMemberReferenceExpression = 294 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.EmptyStatement = 9 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.EndStatement = 81 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.EventAssignmentExpression = 283 -> Microsoft.CodeAnalysis.OperationKind
......@@ -88,7 +89,6 @@ Microsoft.CodeAnalysis.OperationKind.IsPatternExpression = 517 -> Microsoft.Code
Microsoft.CodeAnalysis.OperationKind.IsTypeExpression = 278 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.LabelStatement = 7 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.LambdaExpression = 273 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.LateBoundMemberReferenceExpression = 769 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.LiteralExpression = 257 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.LocalFunctionStatement = 49 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.LocalReferenceExpression = 261 -> Microsoft.CodeAnalysis.OperationKind
......@@ -394,6 +394,11 @@ Microsoft.CodeAnalysis.Semantics.IDeclarationPattern
Microsoft.CodeAnalysis.Semantics.IDeclarationPattern.DeclaredSymbol.get -> Microsoft.CodeAnalysis.ISymbol
Microsoft.CodeAnalysis.Semantics.IDefaultCaseClause
Microsoft.CodeAnalysis.Semantics.IDefaultValueExpression
Microsoft.CodeAnalysis.Semantics.IDynamicMemberReferenceExpression
Microsoft.CodeAnalysis.Semantics.IDynamicMemberReferenceExpression.ContainingType.get -> Microsoft.CodeAnalysis.ITypeSymbol
Microsoft.CodeAnalysis.Semantics.IDynamicMemberReferenceExpression.Instance.get -> Microsoft.CodeAnalysis.IOperation
Microsoft.CodeAnalysis.Semantics.IDynamicMemberReferenceExpression.MemberName.get -> string
Microsoft.CodeAnalysis.Semantics.IDynamicMemberReferenceExpression.TypeArguments.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ITypeSymbol>
Microsoft.CodeAnalysis.Semantics.IDynamicObjectCreationExpression
Microsoft.CodeAnalysis.Semantics.IDynamicObjectCreationExpression.Initializer.get -> Microsoft.CodeAnalysis.Semantics.IObjectOrCollectionInitializerExpression
Microsoft.CodeAnalysis.Semantics.IEmptyStatement
......@@ -470,9 +475,6 @@ Microsoft.CodeAnalysis.Semantics.ILabelStatement.LabeledStatement.get -> Microso
Microsoft.CodeAnalysis.Semantics.ILambdaExpression
Microsoft.CodeAnalysis.Semantics.ILambdaExpression.Body.get -> Microsoft.CodeAnalysis.Semantics.IBlockStatement
Microsoft.CodeAnalysis.Semantics.ILambdaExpression.Signature.get -> Microsoft.CodeAnalysis.IMethodSymbol
Microsoft.CodeAnalysis.Semantics.ILateBoundMemberReferenceExpression
Microsoft.CodeAnalysis.Semantics.ILateBoundMemberReferenceExpression.Instance.get -> Microsoft.CodeAnalysis.IOperation
Microsoft.CodeAnalysis.Semantics.ILateBoundMemberReferenceExpression.MemberName.get -> string
Microsoft.CodeAnalysis.Semantics.ILiteralExpression
Microsoft.CodeAnalysis.Semantics.ILiteralExpression.Text.get -> string
Microsoft.CodeAnalysis.Semantics.ILocalFunctionStatement
......@@ -780,6 +782,7 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitConversionExpress
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitDeclarationPattern(Microsoft.CodeAnalysis.Semantics.IDeclarationPattern operation) -> void
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitDefaultCaseClause(Microsoft.CodeAnalysis.Semantics.IDefaultCaseClause operation) -> void
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitDefaultValueExpression(Microsoft.CodeAnalysis.Semantics.IDefaultValueExpression operation) -> void
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitDynamicMemberReferenceExpression(Microsoft.CodeAnalysis.Semantics.IDynamicMemberReferenceExpression operation) -> void
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitDynamicObjectCreationExpression(Microsoft.CodeAnalysis.Semantics.IDynamicObjectCreationExpression operation) -> void
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitEmptyStatement(Microsoft.CodeAnalysis.Semantics.IEmptyStatement operation) -> void
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitEndStatement(Microsoft.CodeAnalysis.Semantics.IEndStatement operation) -> void
......@@ -804,7 +807,6 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitIsPatternExpressi
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitIsTypeExpression(Microsoft.CodeAnalysis.Semantics.IIsTypeExpression operation) -> void
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLabelStatement(Microsoft.CodeAnalysis.Semantics.ILabelStatement operation) -> void
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLambdaExpression(Microsoft.CodeAnalysis.Semantics.ILambdaExpression operation) -> void
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLateBoundMemberReferenceExpression(Microsoft.CodeAnalysis.Semantics.ILateBoundMemberReferenceExpression operation) -> void
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLiteralExpression(Microsoft.CodeAnalysis.Semantics.ILiteralExpression operation) -> void
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLocalFunctionStatement(Microsoft.CodeAnalysis.Semantics.ILocalFunctionStatement operation) -> void
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLocalReferenceExpression(Microsoft.CodeAnalysis.Semantics.ILocalReferenceExpression operation) -> void
......@@ -870,6 +872,7 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.Vi
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitDeclarationPattern(Microsoft.CodeAnalysis.Semantics.IDeclarationPattern operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitDefaultCaseClause(Microsoft.CodeAnalysis.Semantics.IDefaultCaseClause operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitDefaultValueExpression(Microsoft.CodeAnalysis.Semantics.IDefaultValueExpression operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitDynamicMemberReferenceExpression(Microsoft.CodeAnalysis.Semantics.IDynamicMemberReferenceExpression operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitDynamicObjectCreationExpression(Microsoft.CodeAnalysis.Semantics.IDynamicObjectCreationExpression operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitEmptyStatement(Microsoft.CodeAnalysis.Semantics.IEmptyStatement operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitEndStatement(Microsoft.CodeAnalysis.Semantics.IEndStatement operation, TArgument argument) -> TResult
......@@ -894,7 +897,6 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.Vi
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitIsTypeExpression(Microsoft.CodeAnalysis.Semantics.IIsTypeExpression operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitLabelStatement(Microsoft.CodeAnalysis.Semantics.ILabelStatement operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitLambdaExpression(Microsoft.CodeAnalysis.Semantics.ILambdaExpression operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitLateBoundMemberReferenceExpression(Microsoft.CodeAnalysis.Semantics.ILateBoundMemberReferenceExpression operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitLiteralExpression(Microsoft.CodeAnalysis.Semantics.ILiteralExpression operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitLocalFunctionStatement(Microsoft.CodeAnalysis.Semantics.ILocalFunctionStatement operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitLocalReferenceExpression(Microsoft.CodeAnalysis.Semantics.ILocalReferenceExpression operation, TArgument argument) -> TResult
......
......@@ -639,13 +639,27 @@ Namespace Microsoft.CodeAnalysis.Semantics
Return New LocalReferenceExpression(local, syntax, type, constantValue)
End Function
Private Function CreateBoundLateMemberAccessOperation(boundLateMemberAccess As BoundLateMemberAccess) As ILateBoundMemberReferenceExpression
Private Function CreateBoundLateMemberAccessOperation(boundLateMemberAccess As BoundLateMemberAccess) As IDynamicMemberReferenceExpression
Dim instance As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundLateMemberAccess.ReceiverOpt))
Dim memberName As String = boundLateMemberAccess.NameOpt
Dim typeArguments As ImmutableArray(Of ITypeSymbol) = ImmutableArray(Of ITypeSymbol).Empty
If boundLateMemberAccess.TypeArgumentsOpt IsNot Nothing Then
typeArguments = ImmutableArray(Of ITypeSymbol).CastUp(boundLateMemberAccess.TypeArgumentsOpt.Arguments)
End If
Dim containingType As ITypeSymbol = Nothing
' If there's nothing being late-bound against, something is very wrong
Debug.Assert(boundLateMemberAccess.ReceiverOpt IsNot Nothing OrElse boundLateMemberAccess.ContainerTypeOpt IsNot Nothing)
' Only set containing type if the container is set to something, and either there is no reciever, or the receiver's type
' does not match the type of the containing type.
If (boundLateMemberAccess.ContainerTypeOpt IsNot Nothing AndAlso
(boundLateMemberAccess.ReceiverOpt Is Nothing OrElse
boundLateMemberAccess.ContainerTypeOpt <> boundLateMemberAccess.ReceiverOpt.Type)) Then
containingType = boundLateMemberAccess.ContainerTypeOpt
End If
Dim syntax As SyntaxNode = boundLateMemberAccess.Syntax
Dim type As ITypeSymbol = boundLateMemberAccess.Type
Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundLateMemberAccess.ConstantValueOpt)
Return New LazyLateBoundMemberReferenceExpression(instance, memberName, syntax, type, constantValue)
Return New LazyDynamicMemberReferenceExpression(instance, memberName, typeArguments, containingType, syntax, type, constantValue)
End Function
Private Function CreateBoundFieldInitializerOperation(boundFieldInitializer As BoundFieldInitializer) As IFieldInitializer
......
......@@ -84,4 +84,4 @@
<Compile Remove="Semantics\PrintResultTestSource.vb" />
</ItemGroup>
<Import Project="..\..\..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
</Project>
' 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
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
Partial Public Class IOperationTests
Inherits SemanticModelTestBase
<Fact()>
Public Sub IDynamicMemberReferenceExpression_SimplePropertyAccess()
Dim source = <![CDATA[
Option Strict Off
Module Program
Sub Main(args As String())
Dim d = Nothing
d.Foo'BIND:"d.Foo"
End Sub
End Module
]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'd.Foo')
Children(1):
IDynamicMemberReferenceExpression (Member Name: "Foo", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'd.Foo')
Type Arguments(0)
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'd')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact()>
Public Sub IDynamicMemberReferenceExpression_GenericPropertyAccess()
Dim source = <![CDATA[
Option Strict Off
Module Program
Sub Main(args As String())
Dim d = Nothing
d.Foo(Of String)'BIND:"d.Foo(Of String)"
End Sub
End Module
]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'd.Foo(Of String)')
Children(1):
IDynamicMemberReferenceExpression (Member Name: "Foo", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'd.Foo(Of String)')
Type Arguments(1):
Symbol: System.String
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'd')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact()>
Public Sub IDynamicMemberReferenceExpression_InvalidGenericPropertyAccess()
Dim source = <![CDATA[
Option Strict Off
Module Program
Sub Main(args As String())
Dim d = Nothing
d.Foo(Of)'BIND:"d.Foo(Of)"
End Sub
End Module
]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None, IsInvalid) (Syntax: 'd.Foo(Of)')
Children(1):
IDynamicMemberReferenceExpression (Member Name: "Foo", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object, IsInvalid) (Syntax: 'd.Foo(Of)')
Type Arguments(1):
Symbol: ?
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'd')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30182: Type expected.
d.Foo(Of)'BIND:"d.Foo(Of)"
~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact()>
Public Sub IDynamicMemberReferenceExpression_SimpleMethodCall()
Dim source = <![CDATA[
Option Strict Off
Module Program
Sub Main(args As String())
Dim d = Nothing
d.Foo()'BIND:"d.Foo()"
End Sub
End Module
]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'd.Foo()')
Children(1):
IDynamicMemberReferenceExpression (Member Name: "Foo", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'd.Foo')
Type Arguments(0)
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'd')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact()>
Public Sub IDynamicMemberReferenceExpression_InvalidMethodCall_MissingParen()
Dim source = <![CDATA[
Option Strict Off
Module Program
Sub Main(args As String())
Dim d = Nothing
d.Foo('BIND:"d.Foo("
End Sub
End Module
]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None, IsInvalid) (Syntax: 'd.Foo(')
Children(2):
IDynamicMemberReferenceExpression (Member Name: "Foo", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'd.Foo')
Type Arguments(0)
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'd')
IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Object, IsInvalid) (Syntax: '')
Operand: IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '')
Children(0)
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30198: ')' expected.
d.Foo('BIND:"d.Foo("
~
BC30201: Expression expected.
d.Foo('BIND:"d.Foo("
~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact()>
Public Sub IDynamicMemberReferenceExpression_GenericMethodCall_SingleGeneric()
Dim source = <![CDATA[
Option Strict Off
Module Program
Sub Main(args As String())
Dim d = Nothing
d.GetValue(Of String)()'BIND:"d.GetValue(Of String)()"
End Sub
End Module
]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'd.GetValue(Of String)()')
Children(1):
IDynamicMemberReferenceExpression (Member Name: "GetValue", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'd.GetValue(Of String)')
Type Arguments(1):
Symbol: System.String
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'd')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact()>
Public Sub IDynamicMemberReferenceExpression_GenericMethodCall_MultipleGeneric()
Dim source = <![CDATA[
Option Strict Off
Module Program
Sub Main(args As String())
Dim d = Nothing
d.GetValue(Of String, Integer)()'BIND:"d.GetValue(Of String, Integer)()"
End Sub
End Module
]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'd.GetValue( ... Integer)()')
Children(1):
IDynamicMemberReferenceExpression (Member Name: "GetValue", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'd.GetValue( ... g, Integer)')
Type Arguments(2):
Symbol: System.String
Symbol: System.Int32
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'd')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact()>
Public Sub IDynamicMemberReferenceExpression_GenericMethodCall_InvalidGenericParameter()
Dim source = <![CDATA[
Option Strict Off
Module Program
Sub Main(args As String())
Dim d = Nothing
d.GetValue(Of String,)()'BIND:"d.GetValue(Of String,)()"
End Sub
End Module
]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None, IsInvalid) (Syntax: 'd.GetValue(Of String,)()')
Children(1):
IDynamicMemberReferenceExpression (Member Name: "GetValue", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object, IsInvalid) (Syntax: 'd.GetValue(Of String,)')
Type Arguments(2):
Symbol: System.String
Symbol: ?
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'd')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30182: Type expected.
d.GetValue(Of String,)()'BIND:"d.GetValue(Of String,)()"
~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact()>
Public Sub IDynamicMemberReferenceExpression_NestedPropertyAccess()
Dim source = <![CDATA[
Option Strict Off
Module Program
Sub Main(args As String())
Dim d = Nothing
d.Prop1.Prop2'BIND:"d.Prop1.Prop2"
End Sub
End Module
]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'd.Prop1.Prop2')
Children(1):
IDynamicMemberReferenceExpression (Member Name: "Prop2", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'd.Prop1.Prop2')
Type Arguments(0)
Instance Receiver: IDynamicMemberReferenceExpression (Member Name: "Prop1", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'd.Prop1')
Type Arguments(0)
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'd')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact()>
Public Sub IDynamicMemberReferenceExpression_NestedMethodAccess()
Dim source = <![CDATA[
Option Strict Off
Module Program
Sub Main(args As String())
Dim d = Nothing
d.Method1().Method2()'BIND:"d.Method1().Method2()"
End Sub
End Module
]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'd.Method1().Method2()')
Children(1):
IDynamicMemberReferenceExpression (Member Name: "Method2", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'd.Method1().Method2')
Type Arguments(0)
Instance Receiver: IOperation: (OperationKind.None) (Syntax: 'd.Method1()')
Children(1):
IDynamicMemberReferenceExpression (Member Name: "Method1", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'd.Method1')
Type Arguments(0)
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'd')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact()>
Public Sub IDynamicMemberReferenceExpression_NestedPropertyAndMethodAccess()
Dim source = <![CDATA[
Option Strict Off
Module Program
Sub Main(args As String())
Dim d = Nothing
d.Prop1.Method2()'BIND:"d.Prop1.Method2()"
End Sub
End Module
]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'd.Prop1.Method2()')
Children(1):
IDynamicMemberReferenceExpression (Member Name: "Method2", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'd.Prop1.Method2')
Type Arguments(0)
Instance Receiver: IDynamicMemberReferenceExpression (Member Name: "Prop1", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'd.Prop1')
Type Arguments(0)
Instance Receiver: ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'd')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact()>
Public Sub IDynamicMemberReferenceExpression_LateBoundModuleFunction()
Dim source = <![CDATA[
Option Strict Off
Imports System.Collections.Generic
Module Module1
Sub Main()
Dim x As Object = New List(Of Integer)()
fun(x)'BIND:"fun(x)"
End Sub
Sub fun(Of X)(ByVal a As List(Of X))
End Sub
End Module
]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'fun(x)')
Children(2):
IDynamicMemberReferenceExpression (Member Name: "fun", Containing Type: Module1) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'fun')
Type Arguments(0)
Instance Receiver: null
ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<Fact()>
Public Sub IDynamicMemberReferenceExpression_LateBoundClassFunction()
Dim source = <![CDATA[
Option Strict Off
Imports System.Collections.Generic
Module Module1
Sub Main()
Dim x As Object = New List(Of Integer)()
Dim c1 As New C1
c1.fun(x)'BIND:"c1.fun(x)"
End Sub
Class C1
Sub fun(Of X)(ByVal a As List(Of X))
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'c1.fun(x)')
Children(2):
IDynamicMemberReferenceExpression (Member Name: "fun", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'c1.fun')
Type Arguments(0)
Instance Receiver: ILocalReferenceExpression: c1 (OperationKind.LocalReferenceExpression, Type: Module1.C1) (Syntax: 'c1')
ILocalReferenceExpression: x (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
End Class
End Namespace
......@@ -85,7 +85,7 @@ End Class
]]>.Value
Dim expectedOperationTree = <![CDATA[
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'From cust I ... t cust.Name')
Children(1):
IOperation: (OperationKind.None) (Syntax: 'Select cust.Name')
......@@ -132,7 +132,7 @@ Class C
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'Aggregate y ... nto Count()')
Children(1):
IOperation: (OperationKind.None) (Syntax: 'Aggregate y ... nto Count()')
......@@ -178,7 +178,7 @@ Class C
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
Dim expectedOperationTree = <![CDATA[
IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Object) (Syntax: 'From y In x ... By y.Length')
Operand: IOperation: (OperationKind.None) (Syntax: 'From y In x ... By y.Length')
Children(1):
......@@ -226,7 +226,7 @@ Class C
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'From y In x ... nto Count()')
Children(1):
IOperation: (OperationKind.None) (Syntax: 'Group By w ... nto Count()')
......@@ -298,7 +298,7 @@ Friend Class [Class]
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
Dim expectedOperationTree = <![CDATA[
IObjectCreationExpression (Constructor: Sub [Class]..ctor()) (OperationKind.ObjectCreationExpression, Type: [Class]) (Syntax: 'New [Class] ... }')
Arguments(0)
Initializer: IObjectOrCollectionInitializerExpression (OperationKind.ObjectOrCollectionInitializerExpression, Type: [Class]) (Syntax: 'With {'BIND ... }')
......@@ -360,7 +360,7 @@ Class Class1
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
Dim expectedOperationTree = <![CDATA[
IConversionExpression (ConversionKind.Basic, Implicit) (OperationKind.ConversionExpression, Type: System.EventHandler) (Syntax: 'New EventHa ... nction() x)')
Operand: ILambdaExpression (Signature: Function () As System.Object) (OperationKind.LambdaExpression, Type: null) (Syntax: 'Function() x')
IBlockStatement (3 statements, 1 locals) (OperationKind.BlockStatement) (Syntax: 'Function() x')
......@@ -389,7 +389,7 @@ Class Class1
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
Dim expectedOperationTree = <![CDATA[
IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: System.EventHandler) (Syntax: 'New EventHa ... essOf Me.M)')
Operand: IOperation: (OperationKind.None) (Syntax: 'AddressOf Me.M')
Children(1):
......@@ -414,7 +414,7 @@ Class Class1
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
Dim expectedOperationTree = <![CDATA[
IInvalidExpression (OperationKind.InvalidExpression, Type: System.EventHandler, IsInvalid) (Syntax: 'New EventHandler(x)')
Children(1):
IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object, IsInvalid) (Syntax: 'x')
......@@ -438,7 +438,7 @@ Class Class1
End Function
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
Dim expectedOperationTree = <![CDATA[
INameOfExpression (OperationKind.NameOfExpression, Type: System.String, Constant: "x") (Syntax: 'NameOf(x)')
IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'x')
]]>.Value
......@@ -485,7 +485,7 @@ Class Class1
End Class
]]>.Value
Dim expectedOperationTree = <![CDATA[
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'd(x)')
Children(2):
IParameterReferenceExpression: d (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'd')
......@@ -513,7 +513,8 @@ End Class
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'x.M(y)')
Children(2):
ILateBoundMemberReferenceExpression (Member name: M) (OperationKind.LateBoundMemberReferenceExpression, Type: System.Object) (Syntax: 'x.M')
IDynamicMemberReferenceExpression (Member Name: "M", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'x.M')
Type Arguments(0)
Instance Receiver: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x')
IParameterReferenceExpression: y (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'y')
]]>.Value
......@@ -535,7 +536,7 @@ Class Class1
End Class
]]>.Value
Dim expectedOperationTree = <![CDATA[
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'x(y)')
Children(2):
IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x')
......@@ -598,7 +599,7 @@ Friend Class [Class]
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
Dim expectedOperationTree = <![CDATA[
IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Mid(str, st ... ngth) = str')
Expression: ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Void) (Syntax: 'Mid(str, st ... ngth) = str')
Left: IParameterReferenceExpression: str (OperationKind.ParameterReferenceExpression, Type: System.String) (Syntax: 'str')
......@@ -627,7 +628,7 @@ Friend Class [Class]
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
Dim expectedOperationTree = <![CDATA[
IInvalidStatement (OperationKind.InvalidStatement, IsInvalid) (Syntax: 'Case x')
Children(1):
IOperation: (OperationKind.None, IsInvalid) (Syntax: 'Case x')
......@@ -690,7 +691,7 @@ Friend Class [Class]
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'Erase x')
Children(1):
ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32()) (Syntax: 'x')
......@@ -743,7 +744,8 @@ End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None) (Syntax: 'AddressOf x.Method')
Children(1):
ILateBoundMemberReferenceExpression (Member name: Method) (OperationKind.LateBoundMemberReferenceExpression, Type: System.Object) (Syntax: 'x.Method')
IDynamicMemberReferenceExpression (Member Name: "Method", Containing Type: null) (OperationKind.DynamicMemberReferenceExpression, Type: System.Object) (Syntax: 'x.Method')
Type Arguments(0)
Instance Receiver: IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'x')
]]>.Value
......
......@@ -187,10 +187,10 @@ private void LogSymbol(ISymbol symbol, string header, bool logDisplayString = tr
LogString($"{symbolStr}");
}
private void LogType(ITypeSymbol type)
private void LogType(ITypeSymbol type, string header = "Type")
{
var typeStr = type != null ? type.ToTestDisplayString() : "null";
LogString($"Type: {typeStr}");
LogString($"{header}: {typeStr}");
}
#endregion
......@@ -1087,12 +1087,19 @@ public override void VisitParenthesizedExpression(IParenthesizedExpression opera
Visit(operation.Operand, "Operand");
}
public override void VisitLateBoundMemberReferenceExpression(ILateBoundMemberReferenceExpression operation)
public override void VisitDynamicMemberReferenceExpression(IDynamicMemberReferenceExpression operation)
{
LogString(nameof(ILateBoundMemberReferenceExpression));
LogString($" (Member name: {operation.MemberName})");
LogString(nameof(IDynamicMemberReferenceExpression));
// (Member Name: "quoted name", Containing Type: type)
LogString(" (");
LogConstant((object)operation.MemberName, "Member Name");
LogString(", ");
LogType(operation.ContainingType, "Containing Type");
LogString(")");
LogCommonPropertiesAndNewLine(operation);
VisitArrayCommon(operation.TypeArguments, "Type Arguments", true, VisitSymbolArrayElement);
VisitInstanceExpression(operation.Instance);
}
......
......@@ -526,11 +526,13 @@ public override void VisitParenthesizedExpression(IParenthesizedExpression opera
base.VisitParenthesizedExpression(operation);
}
public override void VisitLateBoundMemberReferenceExpression(ILateBoundMemberReferenceExpression operation)
public override void VisitDynamicMemberReferenceExpression(IDynamicMemberReferenceExpression operation)
{
var memberName = operation.MemberName;
var typeArgs = operation.TypeArguments;
var containingType = operation.ContainingType;
base.VisitLateBoundMemberReferenceExpression(operation);
base.VisitDynamicMemberReferenceExpression(operation);
}
public override void VisitDefaultValueExpression(IDefaultValueExpression operation)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册