diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 834f5ced3716cc62906b405a145c9156e2bf31a3..194559215b436fd5bc031b65839ace4fbbf756bb 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -4469,6 +4469,7 @@ private bool IsConstructorAccessible(MethodSymbol constructor, ref HashSet + diff --git a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs index 20b92f9f30b5f4d9f7a274d6288adf6fdb8c8efd..5b233f6ae5b657390d31677443290b3994e3f67b 100644 --- a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs @@ -4650,14 +4650,16 @@ public BoundConvertedTupleLiteral Update(TypeSymbol naturalTypeOpt, ImmutableArr internal sealed partial class BoundDynamicObjectCreationExpression : BoundExpression { - public BoundDynamicObjectCreationExpression(SyntaxNode syntax, ImmutableArray arguments, ImmutableArray argumentNamesOpt, ImmutableArray argumentRefKindsOpt, BoundExpression initializerExpressionOpt, ImmutableArray applicableMethods, TypeSymbol type, bool hasErrors = false) + public BoundDynamicObjectCreationExpression(SyntaxNode syntax, string name, ImmutableArray arguments, ImmutableArray argumentNamesOpt, ImmutableArray argumentRefKindsOpt, BoundExpression initializerExpressionOpt, ImmutableArray applicableMethods, TypeSymbol type, bool hasErrors = false) : base(BoundKind.DynamicObjectCreationExpression, syntax, type, hasErrors || arguments.HasErrors() || initializerExpressionOpt.HasErrors()) { + Debug.Assert(name != null, "Field 'name' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); Debug.Assert(!arguments.IsDefault, "Field 'arguments' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); Debug.Assert(!applicableMethods.IsDefault, "Field 'applicableMethods' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); Debug.Assert(type != null, "Field 'type' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); + this.Name = name; this.Arguments = arguments; this.ArgumentNamesOpt = argumentNamesOpt; this.ArgumentRefKindsOpt = argumentRefKindsOpt; @@ -4666,6 +4668,8 @@ public BoundDynamicObjectCreationExpression(SyntaxNode syntax, ImmutableArray Arguments { get; } public ImmutableArray ArgumentNamesOpt { get; } @@ -4681,11 +4685,11 @@ public override BoundNode Accept(BoundTreeVisitor visitor) return visitor.VisitDynamicObjectCreationExpression(this); } - public BoundDynamicObjectCreationExpression Update(ImmutableArray arguments, ImmutableArray argumentNamesOpt, ImmutableArray argumentRefKindsOpt, BoundExpression initializerExpressionOpt, ImmutableArray applicableMethods, TypeSymbol type) + public BoundDynamicObjectCreationExpression Update(string name, ImmutableArray arguments, ImmutableArray argumentNamesOpt, ImmutableArray argumentRefKindsOpt, BoundExpression initializerExpressionOpt, ImmutableArray applicableMethods, TypeSymbol type) { - if (arguments != this.Arguments || argumentNamesOpt != this.ArgumentNamesOpt || argumentRefKindsOpt != this.ArgumentRefKindsOpt || initializerExpressionOpt != this.InitializerExpressionOpt || applicableMethods != this.ApplicableMethods || type != this.Type) + if (name != this.Name || arguments != this.Arguments || argumentNamesOpt != this.ArgumentNamesOpt || argumentRefKindsOpt != this.ArgumentRefKindsOpt || initializerExpressionOpt != this.InitializerExpressionOpt || applicableMethods != this.ApplicableMethods || type != this.Type) { - var result = new BoundDynamicObjectCreationExpression(this.Syntax, arguments, argumentNamesOpt, argumentRefKindsOpt, initializerExpressionOpt, applicableMethods, type, this.HasErrors); + var result = new BoundDynamicObjectCreationExpression(this.Syntax, name, arguments, argumentNamesOpt, argumentRefKindsOpt, initializerExpressionOpt, applicableMethods, type, this.HasErrors); result.WasCompilerGenerated = this.WasCompilerGenerated; return result; } @@ -9020,7 +9024,7 @@ public override BoundNode VisitDynamicObjectCreationExpression(BoundDynamicObjec ImmutableArray arguments = (ImmutableArray)this.VisitList(node.Arguments); BoundExpression initializerExpressionOpt = (BoundExpression)this.Visit(node.InitializerExpressionOpt); TypeSymbol type = this.VisitType(node.Type); - return node.Update(arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, initializerExpressionOpt, node.ApplicableMethods, type); + return node.Update(node.Name, arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, initializerExpressionOpt, node.ApplicableMethods, type); } public override BoundNode VisitNoPiaObjectCreationExpression(BoundNoPiaObjectCreationExpression node) { @@ -10402,6 +10406,7 @@ public override TreeDumperNode VisitDynamicObjectCreationExpression(BoundDynamic { return new TreeDumperNode("dynamicObjectCreationExpression", null, new TreeDumperNode[] { + new TreeDumperNode("name", node.Name, null), new TreeDumperNode("arguments", null, from x in node.Arguments select Visit(x, null)), new TreeDumperNode("argumentNamesOpt", node.ArgumentNamesOpt, null), new TreeDumperNode("argumentRefKindsOpt", node.ArgumentRefKindsOpt, null), diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs index e1a81a888e2cf6b045e6aa441de0d84f98949dd7..23d1ca4e4c08096a47cf1b1f1fc4bd6aa7914603 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs @@ -59,6 +59,8 @@ private IOperation CreateInternal(BoundNode boundNode) return CreateBoundLiteralOperation((BoundLiteral)boundNode); case BoundKind.ObjectCreationExpression: return CreateBoundObjectCreationExpressionOperation((BoundObjectCreationExpression)boundNode); + case BoundKind.DynamicObjectCreationExpression: + return CreateBoundDynamicObjectCreationExpressionOperation((BoundDynamicObjectCreationExpression)boundNode); case BoundKind.ObjectInitializerExpression: return CreateBoundObjectInitializerExpressionOperation((BoundObjectInitializerExpression)boundNode); case BoundKind.CollectionInitializerExpression: @@ -425,6 +427,20 @@ private IObjectCreationExpression CreateBoundObjectCreationExpressionOperation(B return new LazyObjectCreationExpression(constructor, initializer, argumentsInEvaluationOrder, syntax, type, constantValue); } + private IDynamicObjectCreationExpression CreateBoundDynamicObjectCreationExpressionOperation(BoundDynamicObjectCreationExpression boundDynamicObjectCreationExpression) + { + string name = boundDynamicObjectCreationExpression.Name; + ImmutableArray applicableSymbols = StaticCast.From(boundDynamicObjectCreationExpression.ApplicableMethods); + Lazy> arguments = new Lazy>(() => boundDynamicObjectCreationExpression.Arguments.SelectAsArray(n => Create(n))); + ImmutableArray argumentNames = boundDynamicObjectCreationExpression.ArgumentNamesOpt.NullToEmpty(); + ImmutableArray argumentRefKinds = boundDynamicObjectCreationExpression.ArgumentRefKindsOpt.NullToEmpty(); + Lazy initializer = new Lazy(() => (IObjectOrCollectionInitializerExpression)Create(boundDynamicObjectCreationExpression.InitializerExpressionOpt)); + SyntaxNode syntax = boundDynamicObjectCreationExpression.Syntax; + ITypeSymbol type = boundDynamicObjectCreationExpression.Type; + Optional constantValue = ConvertToOptional(boundDynamicObjectCreationExpression.ConstantValue); + return new LazyDynamicObjectCreationExpression(name, applicableSymbols, arguments, argumentNames, argumentRefKinds, initializer, syntax, type, constantValue); + } + private IObjectOrCollectionInitializerExpression CreateBoundObjectInitializerExpressionOperation(BoundObjectInitializerExpression boundObjectInitializerExpression) { Lazy> initializers = new Lazy>(() => BoundObjectCreationExpression.GetChildInitializers(boundObjectInitializerExpression).SelectAsArray(n => Create(n))); @@ -733,10 +749,11 @@ private IInvalidExpression CreateBoundBadExpressionOperation(BoundBadExpression private ITypeParameterObjectCreationExpression CreateBoundNewTOperation(BoundNewT boundNewT) { + Lazy initializer = new Lazy(() => (IObjectOrCollectionInitializerExpression)Create(boundNewT.InitializerExpressionOpt)); SyntaxNode syntax = boundNewT.Syntax; ITypeSymbol type = boundNewT.Type; Optional constantValue = ConvertToOptional(boundNewT.ConstantValue); - return new TypeParameterObjectCreationExpression(syntax, type, constantValue); + return new LazyTypeParameterObjectCreationExpression(initializer, syntax, type, constantValue); } private IUnaryOperatorExpression CreateBoundUnaryOperatorOperation(BoundUnaryOperator boundUnaryOperator) diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IConversionExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IConversionExpression.cs index bf0541082d101a73d4688e9b95a6b6ee573b7257..66dbfe111ba47848dbcc3c5e6a1a26ee3c6c470f 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IConversionExpression.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IConversionExpression.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; @@ -1904,6 +1904,7 @@ class C2 : C1 Variables: Local_1: C1 c1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: C1) (Syntax: 'new T()') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T) (Syntax: 'new T()') + null "; var expectedDiagnostics = DiagnosticDescription.None; @@ -1935,6 +1936,7 @@ class C2 : C1 Variables: Local_1: C1 c1 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: C1, IsInvalid) (Syntax: 'new T()') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T, IsInvalid) (Syntax: 'new T()') + null "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'T' to 'C1' @@ -1969,6 +1971,7 @@ static void M1() Variables: Local_1: I1 i1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: I1) (Syntax: 'new T()') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T) (Syntax: 'new T()') + null "; var expectedDiagnostics = DiagnosticDescription.None; @@ -1999,6 +2002,7 @@ static void M1() Variables: Local_1: I1 i1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: I1, IsInvalid) (Syntax: 'new T()') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T, IsInvalid) (Syntax: 'new T()') + null "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'T' to 'I1'. An explicit conversion exists (are you missing a cast?) @@ -2034,6 +2038,7 @@ class C1 Variables: Local_1: U u Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: U) (Syntax: 'new T()') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T) (Syntax: 'new T()') + null "; var expectedDiagnostics = DiagnosticDescription.None; @@ -2065,6 +2070,7 @@ class C1 Variables: Local_1: U u Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: U, IsInvalid) (Syntax: 'new T()') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T, IsInvalid) (Syntax: 'new T()') + null "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'T' to 'U' diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IDynamicObjectCreationExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IDynamicObjectCreationExpression.cs new file mode 100644 index 0000000000000000000000000000000000000000..933c133eb116f815c3409833b37152821148fa4e --- /dev/null +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IDynamicObjectCreationExpression.cs @@ -0,0 +1,357 @@ +// 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 Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public partial class IOperationTests : SemanticModelTestBase + { + [Fact] + public void DynamicObjectCreation_DynamicArgument() + { + string source = @" +class C +{ + public C(int i) + { + } + + void M(dynamic d) + { + var x = /**/new C(d)/**/; + } +} +"; + string expectedOperationTree = @" +IDynamicObjectCreationExpression (Name: C) (OperationKind.TypeParameterObjectCreationExpression, Type: C) (Syntax: 'new C(d)') + ApplicableSymbols(1): + Symbol: C..ctor(System.Int32 i) + Arguments(1): + IParameterReferenceExpression: d (OperationKind.ParameterReferenceExpression, Type: dynamic) (Syntax: 'd') + ArgumentNames(0) + ArgumentRefKinds(0) + Initializer: null +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void DynamicObjectCreation_MultipleApplicableSymbols() + { + string source = @" +class C +{ + public C(int i) + { + } + + public C(long i) + { + } + + void M(dynamic d) + { + var x = /**/new C(d)/**/; + } +} +"; + string expectedOperationTree = @" +IDynamicObjectCreationExpression (Name: C) (OperationKind.TypeParameterObjectCreationExpression, Type: C) (Syntax: 'new C(d)') + ApplicableSymbols(2): + Symbol: C..ctor(System.Int32 i) + Symbol: C..ctor(System.Int64 i) + Arguments(1): + IParameterReferenceExpression: d (OperationKind.ParameterReferenceExpression, Type: dynamic) (Syntax: 'd') + ArgumentNames(0) + ArgumentRefKinds(0) + Initializer: null +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void DynamicObjectCreation_MultipleArgumentsAndApplicableSymbols() + { + string source = @" +class C +{ + public C(int i, char c) + { + } + + public C(long i, char c) + { + } + + void M(dynamic d) + { + char c = 'c'; + var x = /**/new C(d, c)/**/; + } +} +"; + string expectedOperationTree = @" +IDynamicObjectCreationExpression (Name: C) (OperationKind.TypeParameterObjectCreationExpression, Type: C) (Syntax: 'new C(d, c)') + ApplicableSymbols(2): + Symbol: C..ctor(System.Int32 i, System.Char c) + Symbol: C..ctor(System.Int64 i, System.Char c) + Arguments(2): + IParameterReferenceExpression: d (OperationKind.ParameterReferenceExpression, Type: dynamic) (Syntax: 'd') + ILocalReferenceExpression: c (OperationKind.LocalReferenceExpression, Type: System.Char) (Syntax: 'c') + ArgumentNames(0) + ArgumentRefKinds(0) + Initializer: null +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void DynamicObjectCreation_ArgumentNames() + { + string source = @" +class C +{ + public C(int i, char c) + { + } + + public C(long i, char c) + { + } + + void M(dynamic d, dynamic e) + { + var x = /**/new C(i: d, c: e)/**/; + } +} +"; + string expectedOperationTree = @" +IDynamicObjectCreationExpression (Name: C) (OperationKind.TypeParameterObjectCreationExpression, Type: C) (Syntax: 'new C(i: d, c: e)') + ApplicableSymbols(2): + Symbol: C..ctor(System.Int32 i, System.Char c) + Symbol: C..ctor(System.Int64 i, System.Char c) + Arguments(2): + IParameterReferenceExpression: d (OperationKind.ParameterReferenceExpression, Type: dynamic) (Syntax: 'd') + IParameterReferenceExpression: e (OperationKind.ParameterReferenceExpression, Type: dynamic) (Syntax: 'e') + ArgumentNames(2): + ""i"" + ""c"" + ArgumentRefKinds(0) + Initializer: null +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void DynamicObjectCreation_ArgumentRefKinds() + { + string source = @" +class C +{ + public C(ref object i, out int j, char c) + { + j = 0; + } + + void M(object d, dynamic e) + { + int k; + var x = /**/new C(ref d, out k, e)/**/; + } +} +"; + string expectedOperationTree = @" +IDynamicObjectCreationExpression (Name: C) (OperationKind.TypeParameterObjectCreationExpression, Type: C) (Syntax: 'new C(ref d, out k, e)') + ApplicableSymbols(1): + Symbol: C..ctor(ref System.Object i, out System.Int32 j, System.Char c) + Arguments(3): + IParameterReferenceExpression: d (OperationKind.ParameterReferenceExpression, Type: System.Object) (Syntax: 'd') + ILocalReferenceExpression: k (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'k') + IParameterReferenceExpression: e (OperationKind.ParameterReferenceExpression, Type: dynamic) (Syntax: 'e') + ArgumentNames(0) + ArgumentRefKinds(3): + Ref + Out + None + Initializer: null +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void DynamicObjectCreation_Initializer() + { + string source = @" +class C +{ + public int X; + + public C(char c) + { + } + + void M(dynamic d) + { + var x = /**/new C(d) { X = 0 }/**/; + } +} +"; + string expectedOperationTree = @" +IDynamicObjectCreationExpression (Name: C) (OperationKind.TypeParameterObjectCreationExpression, Type: C) (Syntax: 'new C(d) { X = 0 }') + ApplicableSymbols(1): + Symbol: C..ctor(System.Char c) + Arguments(1): + IParameterReferenceExpression: d (OperationKind.ParameterReferenceExpression, Type: dynamic) (Syntax: 'd') + ArgumentNames(0) + ArgumentRefKinds(0) + Initializer: IObjectOrCollectionInitializerExpression (OperationKind.ObjectOrCollectionInitializerExpression, Type: C) (Syntax: '{ X = 0 }') + Initializers(1): + ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'X = 0') + Left: IFieldReferenceExpression: System.Int32 C.X (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: 'X') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C) (Syntax: 'X') + Right: ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void DynamicObjectCreation_AllFields() + { + string source = @" +class C +{ + public int X; + + public C(ref int i, char c) + { + } + + public C(ref int i, long c) + { + } + + void M(dynamic d) + { + int i = 0; + var x = /**/new C(ref i, c: d) { X = 0 }/**/; + } +} +"; + string expectedOperationTree = @" +IDynamicObjectCreationExpression (Name: C) (OperationKind.TypeParameterObjectCreationExpression, Type: C) (Syntax: 'new C(ref i ... ) { X = 0 }') + ApplicableSymbols(2): + Symbol: C..ctor(ref System.Int32 i, System.Char c) + Symbol: C..ctor(ref System.Int32 i, System.Int64 c) + Arguments(2): + ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i') + IParameterReferenceExpression: d (OperationKind.ParameterReferenceExpression, Type: dynamic) (Syntax: 'd') + ArgumentNames(2): + ""null"" + ""c"" + ArgumentRefKinds(2): + Ref + None + Initializer: IObjectOrCollectionInitializerExpression (OperationKind.ObjectOrCollectionInitializerExpression, Type: C) (Syntax: '{ X = 0 }') + Initializers(1): + ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'X = 0') + Left: IFieldReferenceExpression: System.Int32 C.X (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: 'X') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C) (Syntax: 'X') + Right: ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void DynamicObjectCreation_ErrorBadDynamicMethodArgLambda() + { + string source = @" +using System; + +class C +{ + static void Main() + { + dynamic y = null; + /**/new C(delegate { }, y)/**/; + } + + public C(Action a, Action y) + { + } +} +"; + string expectedOperationTree = @" +IDynamicObjectCreationExpression (Name: C) (OperationKind.TypeParameterObjectCreationExpression, Type: C, IsInvalid) (Syntax: 'new C(delegate { }, y)') + ApplicableSymbols(1): + Symbol: C..ctor(System.Action a, System.Action y) + Arguments(2): + ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'delegate { }') + IBlockStatement (1 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: '{ }') + IReturnStatement (OperationKind.ReturnStatement, IsInvalid) (Syntax: '{ }') + null + ILocalReferenceExpression: y (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'y') + ArgumentNames(0) + ArgumentRefKinds(0) + Initializer: null +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS1977: Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type. + // /**/new C(delegate { }, y)/**/; + Diagnostic(ErrorCode.ERR_BadDynamicMethodArgLambda, "delegate { }").WithLocation(9, 25) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [Fact] + public void DynamicObjectCreation_OVerloadResolutionFailure() + { + string source = @" +class C +{ + public C() + { + } + + public C(int i, int j) + { + } + + void M(dynamic d) + { + var x = /**/new C(d)/**/; + } +} +"; + string expectedOperationTree = @" +IInvalidExpression (OperationKind.InvalidExpression, Type: C, IsInvalid) (Syntax: 'new C(d)') + Children(1): + IParameterReferenceExpression: d (OperationKind.ParameterReferenceExpression, Type: dynamic) (Syntax: 'd') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS7036: There is no argument given that corresponds to the required formal parameter 'j' of 'C.C(int, int)' + // var x = /**/new C(d)/**/; + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "C").WithArguments("j", "C.C(int, int)").WithLocation(14, 31) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + } +} diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs index 2d95ad35ba3b8a844a311959412e00772c4b47b1..8f702257b19a133592896a07498f705615a8ae59 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs @@ -598,9 +598,15 @@ public void M(dynamic x) } "; string expectedOperationTree = @" -IOperation: (OperationKind.None) (Syntax: 'new Class(x)') - Children(1): +IDynamicObjectCreationExpression (Name: Class) (OperationKind.TypeParameterObjectCreationExpression, Type: Class) (Syntax: 'new Class(x)') + ApplicableSymbols(2): + Symbol: Class..ctor(Class x) + Symbol: Class..ctor(System.String x) + Arguments(1): IParameterReferenceExpression: x (OperationKind.ParameterReferenceExpression, Type: dynamic) (Syntax: 'x') + ArgumentNames(0) + ArgumentRefKinds(0) + Initializer: null "; var expectedDiagnostics = DiagnosticDescription.None; diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/ObjectAndCollectionInitializerTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/ObjectAndCollectionInitializerTests.cs index 5b8af207a8a643b785467a66fafbf3a7ca00a9e6..0bdc9f8511b4ad89e0118063404ccf854841c2d5 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/ObjectAndCollectionInitializerTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/ObjectAndCollectionInitializerTests.cs @@ -113,11 +113,18 @@ public static void Foo() } } "; - - // Expected operation tree should expose the object initializer. - // See https://github.com/dotnet/roslyn/issues/20491. -string expectedOperationTree = @" + string expectedOperationTree = @" ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T) (Syntax: 'new T() { x = 0, y = 0 }') + IObjectOrCollectionInitializerExpression (OperationKind.ObjectOrCollectionInitializerExpression, Type: T) (Syntax: '{ x = 0, y = 0 }') + Initializers(2): + ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'x = 0') + Left: IFieldReferenceExpression: System.Int32 Base.x (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: 'x') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: Base) (Syntax: 'x') + Right: ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') + ISimpleAssignmentExpression (OperationKind.SimpleAssignmentExpression, Type: System.Int32) (Syntax: 'y = 0') + Left: IPropertyReferenceExpression: System.Int32 Base.y { get; set; } (OperationKind.PropertyReferenceExpression, Type: System.Int32) (Syntax: 'y') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: Base) (Syntax: 'y') + Right: ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') "; var expectedDiagnostics = DiagnosticDescription.None; diff --git a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs index 0619a9684c584ba2ac1211ab64384409aee63541..996d93475c3c02faae68f2a7fdd4b75387772872 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs @@ -4867,13 +4867,12 @@ internal abstract partial class TypeOperationExpression : Operation, ITypeOperat public ITypeSymbol TypeOperand { get; } } - /// - /// This interface is reserved for implementation by its associated APIs. We reserve the right to - /// change it in the future. - /// - internal sealed partial class TypeParameterObjectCreationExpression : Operation, ITypeParameterObjectCreationExpression + /// + /// Represents a type parameter object creation expression, i.e. new T(), where T is a type parameter with new constraint. + /// + internal abstract partial class BaseTypeParameterObjectCreationExpression : Operation, ITypeParameterObjectCreationExpression { - public TypeParameterObjectCreationExpression(SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + public BaseTypeParameterObjectCreationExpression(SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : base(OperationKind.TypeParameterObjectCreationExpression, syntax, type, constantValue) { } @@ -4881,9 +4880,13 @@ public override IEnumerable Children { get { - yield break; + yield return Initializer; } } + /// + /// Object or collection initializer, if any. + /// + public abstract IObjectOrCollectionInitializerExpression Initializer { get; } public override void Accept(OperationVisitor visitor) { visitor.VisitTypeParameterObjectCreationExpression(this); @@ -4894,6 +4897,137 @@ public override void Accept(OperationVisitor visitor) } } + /// + /// Represents a type parameter object creation expression, i.e. new T(), where T is a type parameter with new constraint. + /// + internal sealed partial class TypeParameterObjectCreationExpression : BaseTypeParameterObjectCreationExpression, ITypeParameterObjectCreationExpression + { + public TypeParameterObjectCreationExpression(IObjectOrCollectionInitializerExpression initializer, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + base(syntax, type, constantValue) + { + Initializer = initializer; + } + /// + /// Object or collection initializer, if any. + /// + public override IObjectOrCollectionInitializerExpression Initializer { get; } + } + + /// + /// Represents a type parameter object creation expression, i.e. new T(), where T is a type parameter with new constraint. + /// + internal sealed partial class LazyTypeParameterObjectCreationExpression : BaseTypeParameterObjectCreationExpression, ITypeParameterObjectCreationExpression + { + private readonly Lazy _lazyInitializer; + public LazyTypeParameterObjectCreationExpression(Lazy initializer, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + base(syntax, type, constantValue) + { + _lazyInitializer = initializer ?? throw new System.ArgumentNullException(nameof(initializer)); + } + /// + /// Object or collection initializer, if any. + /// + public override IObjectOrCollectionInitializerExpression Initializer => _lazyInitializer.Value; + } + + /// + /// Represents a dynamically bound new/New expression. + /// + internal abstract partial class BaseDynamicObjectCreationExpression : Operation, IHasDynamicArgumentsExpression, IDynamicObjectCreationExpression + { + public BaseDynamicObjectCreationExpression(string name, ImmutableArray applicableSymbols, ImmutableArray argumentNames, ImmutableArray argumentRefKinds, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + base(OperationKind.TypeParameterObjectCreationExpression, syntax, type, constantValue) + { + Name = name; + ApplicableSymbols = applicableSymbols; + ArgumentNames = argumentNames; + ArgumentRefKinds = argumentRefKinds; + } + public override IEnumerable Children + { + get + { + yield return Initializer; + } + } + /// + /// Name of the dynamically invoked member. + /// + public string Name { get; } + /// + /// List of applicable symbols that are dynamically bound to the . + /// + public ImmutableArray ApplicableSymbols { get; } + /// + /// Dynamically bound arguments, excluding the instance argument. + /// + public abstract ImmutableArray Arguments { get; } + /// + /// Optional argument names for named arguments. + /// + public ImmutableArray ArgumentNames { get; } + /// + /// Optional argument ref kinds. + /// + public ImmutableArray ArgumentRefKinds { get; } + /// + /// Object or collection initializer, if any. + /// + public abstract IObjectOrCollectionInitializerExpression Initializer { get; } + public override void Accept(OperationVisitor visitor) + { + visitor.VisitDynamicObjectCreationExpression(this); + } + public override TResult Accept(OperationVisitor visitor, TArgument argument) + { + return visitor.VisitDynamicObjectCreationExpression(this, argument); + } + } + + /// + /// Represents a dynamically bound new/New expression. + /// + internal sealed partial class DynamicObjectCreationExpression : BaseDynamicObjectCreationExpression, IHasDynamicArgumentsExpression, IDynamicObjectCreationExpression + { + public DynamicObjectCreationExpression(string name, ImmutableArray applicableSymbols, ImmutableArray arguments, ImmutableArray argumentNames, ImmutableArray argumentRefKinds, IObjectOrCollectionInitializerExpression initializer, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + base(name, applicableSymbols, argumentNames, argumentRefKinds, syntax, type, constantValue) + { + Arguments = arguments; + Initializer = initializer; + } + /// + /// Dynamically bound arguments, excluding the instance argument. + /// + public override ImmutableArray Arguments { get; } + /// + /// Object or collection initializer, if any. + /// + public override IObjectOrCollectionInitializerExpression Initializer { get; } + } + + /// + /// Represents a dynamically bound new/New expression. + /// + internal sealed partial class LazyDynamicObjectCreationExpression : BaseDynamicObjectCreationExpression, IHasDynamicArgumentsExpression, IDynamicObjectCreationExpression + { + private readonly Lazy _lazyInitializer; + private readonly Lazy> _lazyArguments; + public LazyDynamicObjectCreationExpression(string name, ImmutableArray applicableSymbols, Lazy> arguments, ImmutableArray argumentNames, ImmutableArray argumentRefKinds, Lazy initializer, SyntaxNode syntax, ITypeSymbol type, Optional constantValue) : + base(name, applicableSymbols, argumentNames, argumentRefKinds, syntax, type, constantValue) + { + _lazyArguments = arguments ?? throw new System.ArgumentNullException(nameof(arguments)); + _lazyInitializer = initializer ?? throw new System.ArgumentNullException(nameof(initializer)); + } + /// + /// Dynamically bound arguments, excluding the instance argument. + /// + public override ImmutableArray Arguments => _lazyArguments.Value; + /// + /// Object or collection initializer, if any. + /// + public override IObjectOrCollectionInitializerExpression Initializer => _lazyInitializer.Value; + } + /// /// Represents an operation with one operand. /// diff --git a/src/Compilers/Core/Portable/Operations/IDynamicObjectCreationExpression.cs b/src/Compilers/Core/Portable/Operations/IDynamicObjectCreationExpression.cs new file mode 100644 index 0000000000000000000000000000000000000000..e0ebb01cf4285604bd6f9e3c75519c5bdae60e6b --- /dev/null +++ b/src/Compilers/Core/Portable/Operations/IDynamicObjectCreationExpression.cs @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.CodeAnalysis.Semantics +{ + /// + /// Represents a dynamically bound new/New expression. + /// + /// + /// This interface is reserved for implementation by its associated APIs. We reserve the right to + /// change it in the future. + /// + public interface IDynamicObjectCreationExpression : IHasDynamicArgumentsExpression + { + /// + /// Object or collection initializer, if any. + /// + IObjectOrCollectionInitializerExpression Initializer { get; } + } +} diff --git a/src/Compilers/Core/Portable/Operations/IHasDynamicArgumentsExpression.cs b/src/Compilers/Core/Portable/Operations/IHasDynamicArgumentsExpression.cs new file mode 100644 index 0000000000000000000000000000000000000000..8f35f6c0b3de9e729c21d6de8449fd89b3a36434 --- /dev/null +++ b/src/Compilers/Core/Portable/Operations/IHasDynamicArgumentsExpression.cs @@ -0,0 +1,39 @@ +// 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.Immutable; + +namespace Microsoft.CodeAnalysis.Semantics +{ + /// + /// This interface is reserved for implementation by its associated APIs. We reserve the right to + /// change it in the future. + /// + public interface IHasDynamicArgumentsExpression : IOperation + { + /// + /// Name of the dynamically invoked member. + /// + string Name { get; } + + /// + /// List of applicable symbols that are dynamically bound to the . + /// + ImmutableArray ApplicableSymbols { get; } + + /// + /// Dynamically bound arguments, excluding the instance argument. + /// + ImmutableArray Arguments { get; } + + /// + /// Optional argument names for named arguments. + /// + ImmutableArray ArgumentNames { get; } + + /// + /// Optional argument ref kinds. + /// + ImmutableArray ArgumentRefKinds { get; } + } +} + diff --git a/src/Compilers/Core/Portable/Operations/ITypeParameterObjectCreationExpression.cs b/src/Compilers/Core/Portable/Operations/ITypeParameterObjectCreationExpression.cs index 2af0057f29f9d8cc59bdc4208826230817ccdd19..2dc1a482a4a1291b1d0457e4914b67e1640e3455 100644 --- a/src/Compilers/Core/Portable/Operations/ITypeParameterObjectCreationExpression.cs +++ b/src/Compilers/Core/Portable/Operations/ITypeParameterObjectCreationExpression.cs @@ -1,15 +1,20 @@ // 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.Immutable; - namespace Microsoft.CodeAnalysis.Semantics { + /// + /// Represents a type parameter object creation expression, i.e. new T(), where T is a type parameter with new constraint. + /// /// /// This interface is reserved for implementation by its associated APIs. We reserve the right to /// change it in the future. /// public interface ITypeParameterObjectCreationExpression : IOperation { + /// + /// Object or collection initializer, if any. + /// + IObjectOrCollectionInitializerExpression Initializer { get; } } } diff --git a/src/Compilers/Core/Portable/Operations/OperationKind.cs b/src/Compilers/Core/Portable/Operations/OperationKind.cs index d961bfc3a65140d21a7b7effb1acac7dafd78e32..eb6b182e6f92605eb00393ef9cd0efe970fe1737 100644 --- a/src/Compilers/Core/Portable/Operations/OperationKind.cs +++ b/src/Compilers/Core/Portable/Operations/OperationKind.cs @@ -138,6 +138,8 @@ public enum OperationKind NameOfExpression = 0x123, /// Indicates an . TupleExpression = 0x124, + /// Indicates an . + DynamicObjectCreationExpression = 0x125, // Expressions that occur only in C#. diff --git a/src/Compilers/Core/Portable/Operations/OperationVisitor.cs b/src/Compilers/Core/Portable/Operations/OperationVisitor.cs index 5df10f272d0f6aefa4d1d38f830108ff0513b2b9..eb3e7c0e947e12792cdd4035ab6f2866ba3e5e5d 100644 --- a/src/Compilers/Core/Portable/Operations/OperationVisitor.cs +++ b/src/Compilers/Core/Portable/Operations/OperationVisitor.cs @@ -330,6 +330,11 @@ public virtual void VisitAnonymousObjectCreationExpression(IAnonymousObjectCreat DefaultVisit(operation); } + public virtual void VisitDynamicObjectCreationExpression(IDynamicObjectCreationExpression operation) + { + DefaultVisit(operation); + } + public virtual void VisitObjectOrCollectionInitializerExpression(IObjectOrCollectionInitializerExpression operation) { DefaultVisit(operation); @@ -795,6 +800,11 @@ public virtual TResult VisitAnonymousObjectCreationExpression(IAnonymousObjectCr return DefaultVisit(operation, argument); } + public virtual TResult VisitDynamicObjectCreationExpression(IDynamicObjectCreationExpression operation, TArgument argument) + { + return DefaultVisit(operation, argument); + } + public virtual TResult VisitObjectOrCollectionInitializerExpression(IObjectOrCollectionInitializerExpression operation, TArgument argument) { return DefaultVisit(operation, argument); diff --git a/src/Compilers/Core/Portable/Operations/OperationWalker.cs b/src/Compilers/Core/Portable/Operations/OperationWalker.cs index fab3c9c335591ed262081141d47d8fdd597de1b5..a87846fca74f7f0ca8cfcf94f14cf40a237587c7 100644 --- a/src/Compilers/Core/Portable/Operations/OperationWalker.cs +++ b/src/Compilers/Core/Portable/Operations/OperationWalker.cs @@ -16,10 +16,15 @@ public abstract class OperationWalker : OperationVisitor { foreach (var operation in operations) { - Visit(operation); + VisitOperationArrayElement(operation); } } + internal void VisitOperationArrayElement(T operation) where T : IOperation + { + Visit(operation); + } + public override void Visit(IOperation operation) { if (operation != null) diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index b43b8fcdf56d47917f925b8f5c474e1fcebb98d4..7a7dcb29527e67eecf8e81ec509a862ad49fdcd4 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -1,7 +1,6 @@ *REMOVED*Microsoft.CodeAnalysis.Compilation.Emit(System.IO.Stream peStream, System.IO.Stream pdbStream = null, System.IO.Stream xmlDocumentationStream = null, System.IO.Stream win32Resources = null, System.Collections.Generic.IEnumerable manifestResources = null, Microsoft.CodeAnalysis.Emit.EmitOptions options = null, Microsoft.CodeAnalysis.IMethodSymbol debugEntryPoint = null, System.IO.Stream sourceLinkStream = null, System.Collections.Generic.IEnumerable embeddedTexts = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.Emit.EmitResult *REMOVED*Microsoft.CodeAnalysis.Emit.EmitOptions.EmitOptions(bool metadataOnly = false, Microsoft.CodeAnalysis.Emit.DebugInformationFormat debugInformationFormat = (Microsoft.CodeAnalysis.Emit.DebugInformationFormat)0, string pdbFilePath = null, string outputNameOverride = null, int fileAlignment = 0, ulong baseAddress = 0, bool highEntropyVirtualAddressSpace = false, Microsoft.CodeAnalysis.SubsystemVersion subsystemVersion = default(Microsoft.CodeAnalysis.SubsystemVersion), string runtimeMetadataVersion = null, bool tolerateErrors = false, bool includePrivateMembers = false, System.Collections.Immutable.ImmutableArray instrumentationKinds = default(System.Collections.Immutable.ImmutableArray)) -> void *REMOVED*Microsoft.CodeAnalysis.IOperation.IsInvalid.get -> bool -Microsoft.CodeAnalysis.IOperation.Children.get -> System.Collections.Generic.IEnumerable Microsoft.CodeAnalysis.CommandLineArguments.DisplayLangVersions.get -> bool Microsoft.CodeAnalysis.Diagnostics.AnalysisContext.RegisterOperationAction(System.Action action, params Microsoft.CodeAnalysis.OperationKind[] operationKinds) -> void Microsoft.CodeAnalysis.Diagnostics.CompilationStartAnalysisContext.RegisterOperationAction(System.Action action, params Microsoft.CodeAnalysis.OperationKind[] operationKinds) -> void @@ -40,6 +39,7 @@ Microsoft.CodeAnalysis.Diagnostics.Telemetry.AnalyzerTelemetryInfo.OperationBloc Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.IOperation.Accept(Microsoft.CodeAnalysis.Semantics.OperationVisitor visitor) -> void Microsoft.CodeAnalysis.IOperation.Accept(Microsoft.CodeAnalysis.Semantics.OperationVisitor visitor, TArgument argument) -> TResult +Microsoft.CodeAnalysis.IOperation.Children.get -> System.Collections.Generic.IEnumerable Microsoft.CodeAnalysis.IOperation.ConstantValue.get -> Microsoft.CodeAnalysis.Optional Microsoft.CodeAnalysis.IOperation.Kind.get -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.IOperation.Syntax.get -> Microsoft.CodeAnalysis.SyntaxNode @@ -66,6 +66,7 @@ Microsoft.CodeAnalysis.OperationKind.ConversionExpression = 258 -> Microsoft.Cod Microsoft.CodeAnalysis.OperationKind.DeclarationPattern = 1040 -> Microsoft.CodeAnalysis.OperationKind 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.EmptyStatement = 9 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.EndStatement = 81 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.EventAssignmentExpression = 283 -> Microsoft.CodeAnalysis.OperationKind @@ -393,6 +394,8 @@ Microsoft.CodeAnalysis.Semantics.IDeclarationPattern Microsoft.CodeAnalysis.Semantics.IDeclarationPattern.DeclaredSymbol.get -> Microsoft.CodeAnalysis.ISymbol Microsoft.CodeAnalysis.Semantics.IDefaultCaseClause Microsoft.CodeAnalysis.Semantics.IDefaultValueExpression +Microsoft.CodeAnalysis.Semantics.IDynamicObjectCreationExpression +Microsoft.CodeAnalysis.Semantics.IDynamicObjectCreationExpression.Initializer.get -> Microsoft.CodeAnalysis.Semantics.IObjectOrCollectionInitializerExpression Microsoft.CodeAnalysis.Semantics.IEmptyStatement Microsoft.CodeAnalysis.Semantics.IEndStatement Microsoft.CodeAnalysis.Semantics.IEventAssignmentExpression @@ -422,6 +425,12 @@ Microsoft.CodeAnalysis.Semantics.IForWhileUntilLoopStatement Microsoft.CodeAnalysis.Semantics.IForWhileUntilLoopStatement.Condition.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.IHasArgumentsExpression Microsoft.CodeAnalysis.Semantics.IHasArgumentsExpression.ArgumentsInEvaluationOrder.get -> System.Collections.Immutable.ImmutableArray +Microsoft.CodeAnalysis.Semantics.IHasDynamicArgumentsExpression +Microsoft.CodeAnalysis.Semantics.IHasDynamicArgumentsExpression.ApplicableSymbols.get -> System.Collections.Immutable.ImmutableArray +Microsoft.CodeAnalysis.Semantics.IHasDynamicArgumentsExpression.ArgumentNames.get -> System.Collections.Immutable.ImmutableArray +Microsoft.CodeAnalysis.Semantics.IHasDynamicArgumentsExpression.ArgumentRefKinds.get -> System.Collections.Immutable.ImmutableArray +Microsoft.CodeAnalysis.Semantics.IHasDynamicArgumentsExpression.Arguments.get -> System.Collections.Immutable.ImmutableArray +Microsoft.CodeAnalysis.Semantics.IHasDynamicArgumentsExpression.Name.get -> string Microsoft.CodeAnalysis.Semantics.IHasOperatorMethodExpression Microsoft.CodeAnalysis.Semantics.IHasOperatorMethodExpression.OperatorMethod.get -> Microsoft.CodeAnalysis.IMethodSymbol Microsoft.CodeAnalysis.Semantics.IHasOperatorMethodExpression.UsesOperatorMethod.get -> bool @@ -554,6 +563,7 @@ Microsoft.CodeAnalysis.Semantics.ITypeOfExpression Microsoft.CodeAnalysis.Semantics.ITypeOperationExpression Microsoft.CodeAnalysis.Semantics.ITypeOperationExpression.TypeOperand.get -> Microsoft.CodeAnalysis.ITypeSymbol Microsoft.CodeAnalysis.Semantics.ITypeParameterObjectCreationExpression +Microsoft.CodeAnalysis.Semantics.ITypeParameterObjectCreationExpression.Initializer.get -> Microsoft.CodeAnalysis.Semantics.IObjectOrCollectionInitializerExpression Microsoft.CodeAnalysis.Semantics.IUnaryOperatorExpression Microsoft.CodeAnalysis.Semantics.IUnaryOperatorExpression.Operand.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.IUnaryOperatorExpression.UnaryOperationKind.get -> Microsoft.CodeAnalysis.Semantics.UnaryOperationKind @@ -722,8 +732,8 @@ abstract Microsoft.CodeAnalysis.Diagnostics.OperationBlockStartAnalysisContext.R abstract Microsoft.CodeAnalysis.Diagnostics.OperationBlockStartAnalysisContext.RegisterOperationBlockEndAction(System.Action action) -> void abstract Microsoft.CodeAnalysis.SemanticModel.GetOperationCore(Microsoft.CodeAnalysis.SyntaxNode node, System.Threading.CancellationToken cancellationToken) -> Microsoft.CodeAnalysis.IOperation override Microsoft.CodeAnalysis.Optional.ToString() -> string -override Microsoft.CodeAnalysis.Semantics.OperationWalker.Visit(Microsoft.CodeAnalysis.IOperation operation) -> void override Microsoft.CodeAnalysis.Semantics.OperationWalker.DefaultVisit(Microsoft.CodeAnalysis.IOperation operation) -> void +override Microsoft.CodeAnalysis.Semantics.OperationWalker.Visit(Microsoft.CodeAnalysis.IOperation operation) -> void static Microsoft.CodeAnalysis.Semantics.OperationExtensions.Descendants(this Microsoft.CodeAnalysis.IOperation operation) -> System.Collections.Generic.IEnumerable static Microsoft.CodeAnalysis.Semantics.OperationExtensions.DescendantsAndSelf(this Microsoft.CodeAnalysis.IOperation operation) -> System.Collections.Generic.IEnumerable static Microsoft.CodeAnalysis.Semantics.OperationExtensions.GetDeclaredVariables(this Microsoft.CodeAnalysis.Semantics.IVariableDeclarationStatement declarationStatement) -> System.Collections.Immutable.ImmutableArray @@ -770,6 +780,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.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 virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitEventAssignmentExpression(Microsoft.CodeAnalysis.Semantics.IEventAssignmentExpression operation) -> void @@ -859,6 +870,7 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.Vi virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitDeclarationPattern(Microsoft.CodeAnalysis.Semantics.IDeclarationPattern operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitDefaultCaseClause(Microsoft.CodeAnalysis.Semantics.IDefaultCaseClause operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitDefaultValueExpression(Microsoft.CodeAnalysis.Semantics.IDefaultValueExpression operation, TArgument argument) -> TResult +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitDynamicObjectCreationExpression(Microsoft.CodeAnalysis.Semantics.IDynamicObjectCreationExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitEmptyStatement(Microsoft.CodeAnalysis.Semantics.IEmptyStatement operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitEndStatement(Microsoft.CodeAnalysis.Semantics.IEndStatement operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitEventAssignmentExpression(Microsoft.CodeAnalysis.Semantics.IEventAssignmentExpression operation, TArgument argument) -> TResult diff --git a/src/Compilers/Core/Portable/Symbols/Attributes/WellKnownAttributeData.cs b/src/Compilers/Core/Portable/Symbols/Attributes/WellKnownAttributeData.cs index f7fa18aaab386e6239836348c325ecd2057104fc..c277879c3a12417916d45626f0a32fa636dbaf66 100644 --- a/src/Compilers/Core/Portable/Symbols/Attributes/WellKnownAttributeData.cs +++ b/src/Compilers/Core/Portable/Symbols/Attributes/WellKnownAttributeData.cs @@ -11,12 +11,14 @@ namespace Microsoft.CodeAnalysis /// internal abstract class WellKnownAttributeData { +#pragma warning disable CA1802 // Remove suppression once https://github.com/dotnet/roslyn/issues/20894 is fixed /// /// Used to distinguish cases when attribute is applied with null value and when attribute is not applied. /// For some well-known attributes, the latter case will return string stored in /// field. /// public static readonly string StringMissingValue = nameof(StringMissingValue); +#pragma warning restore CA1802 #if DEBUG private bool _isSealed; diff --git a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb index 6d1bb62aee84d8158a6f9d1863c03c0975ff597a..f4d75f9c279b3bcebf29ad454c69efbc6e131d46 100644 --- a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb +++ b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb @@ -522,10 +522,11 @@ Namespace Microsoft.CodeAnalysis.Semantics End Function Private Function CreateBoundNewTOperation(boundNewT As BoundNewT) As ITypeParameterObjectCreationExpression + Dim initializer As Lazy(Of IObjectOrCollectionInitializerExpression) = New Lazy(Of IObjectOrCollectionInitializerExpression)(Function() DirectCast(Create(boundNewT.InitializerOpt), IObjectOrCollectionInitializerExpression)) Dim syntax As SyntaxNode = boundNewT.Syntax Dim type As ITypeSymbol = boundNewT.Type Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundNewT.ConstantValueOpt) - Return New TypeParameterObjectCreationExpression(syntax, type, constantValue) + Return New LazyTypeParameterObjectCreationExpression(initializer, syntax, type, constantValue) End Function Private Function CreateBoundArrayCreationOperation(boundArrayCreation As BoundArrayCreation) As IArrayCreationExpression diff --git a/src/Compilers/VisualBasic/Test/Semantic/Binding/BindingCollectionInitializerTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Binding/BindingCollectionInitializerTests.vb index 571c1175d1b1488fce2dc2c3fa7f42e6c113722f..4c28a9a83ff6428487ee44e5d4e52bd7b044bba1 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Binding/BindingCollectionInitializerTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Binding/BindingCollectionInitializerTests.vb @@ -1,4 +1,4 @@ -' 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. Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Test.Utilities @@ -1048,6 +1048,20 @@ End Class]]>.Value Dim expectedOperationTree = .Value Dim expectedDiagnostics = .Value Dim expectedOperationTree = .Value Dim expectedDiagnostics = String.Empty @@ -850,6 +856,7 @@ IObjectCreationExpression (Constructor: Sub C1(Of T)..ctor()) (OperationKind.Obj Left: IFieldReferenceExpression: C1(Of T).Field As T (OperationKind.FieldReferenceExpression, Type: T) (Syntax: 'Field') Instance Receiver: IOperation: (OperationKind.None) (Syntax: 'New C1(Of T ... ld = New T}') Right: ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T) (Syntax: 'New T') + null ]]>.Value Dim expectedDiagnostics = String.Empty diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IConversionExpression.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IConversionExpression.vb index 1ba9c97af75f3969a5a1864875a078943c73f41d..a97971bfef6353a1205f3ccb06af192ec6be0f3a 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IConversionExpression.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IConversionExpression.vb @@ -1,4 +1,4 @@ -' 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. Imports Microsoft.CodeAnalysis.Semantics Imports Microsoft.CodeAnalysis.VisualBasic.Syntax @@ -1681,6 +1681,7 @@ IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclaratio Variables: Local_1: c1 As Module1.C1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: Module1.C1) (Syntax: 'New T') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T) (Syntax: 'New T') + null ]]>.Value Dim expectedDiagnostics = String.Empty @@ -1715,6 +1716,7 @@ IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclaratio Variables: Local_1: c1 As Module1.C1 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: Module1.C1, IsInvalid) (Syntax: 'New T') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T, IsInvalid) (Syntax: 'New T') + null ]]>.Value Dim expectedDiagnostics = .Value Dim expectedDiagnostics = String.Empty @@ -1780,6 +1783,7 @@ IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclaratio Variables: Local_1: t1 As T Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: T) (Syntax: 'New U') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: U) (Syntax: 'New U') + null ]]>.Value Dim expectedDiagnostics = String.Empty @@ -1807,6 +1811,7 @@ IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclaratio Variables: Local_1: t1 As T Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: T, IsInvalid) (Syntax: 'New U') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: U, IsInvalid) (Syntax: 'New U') + null ]]>.Value Dim expectedDiagnostics = (IEnumerable list, string header, bool logElementCount) - where T : IOperation + private void VisitArrayCommon(IEnumerable list, string header, bool logElementCount, Action arrayElementVisitor) { Debug.Assert(!string.IsNullOrEmpty(header)); @@ -241,7 +240,10 @@ private void VisitArray(IEnumerable list, string header, bool logElementCo LogString($"{header}{elementCount}:"); LogNewLine(); Indent(); - VisitArray(list); + foreach (var element in list) + { + arrayElementVisitor(element); + } Unindent(); } else @@ -253,6 +255,47 @@ private void VisitArray(IEnumerable list, string header, bool logElementCo Unindent(); } + internal void VisitSymbolArrayElement(ISymbol element) + { + LogSymbol(element, header: "Symbol"); + LogNewLine(); + } + + internal void VisitStringArrayElement(string element) + { + var valueStr = element != null ? element.ToString() : "null"; + valueStr = @"""" + valueStr + @""""; + LogString(valueStr); + LogNewLine(); + } + + internal void VisitRefKindArrayElement(RefKind element) + { + LogString(element.ToString()); + LogNewLine(); + } + + private void VisitArray(IEnumerable list, string header, bool logElementCount) + where T: IOperation + { + VisitArrayCommon(list, header, logElementCount, VisitOperationArrayElement); + } + + private void VisitArray(IEnumerable list, string header, bool logElementCount) + { + VisitArrayCommon(list, header, logElementCount, VisitSymbolArrayElement); + } + + private void VisitArray(IEnumerable list, string header, bool logElementCount) + { + VisitArrayCommon(list, header, logElementCount, VisitStringArrayElement); + } + + private void VisitArray(IEnumerable list, string header, bool logElementCount) + { + VisitArrayCommon(list, header, logElementCount, VisitRefKindArrayElement); + } + private void VisitInstanceExpression(IOperation instance) { Visit(instance, header: "Instance Receiver"); @@ -554,6 +597,14 @@ private void VisitArguments(IHasArgumentsExpression operation) VisitArray(operation.ArgumentsInEvaluationOrder, "Arguments", logElementCount: true); } + private void VisitDynamicArguments(IHasDynamicArgumentsExpression operation) + { + VisitArray(operation.ApplicableSymbols, "ApplicableSymbols", logElementCount: true); + VisitArray(operation.Arguments, "Arguments", logElementCount: true); + VisitArray(operation.ArgumentNames, "ArgumentNames", logElementCount: true); + VisitArray(operation.ArgumentRefKinds, "ArgumentRefKinds", logElementCount: true); + } + public override void VisitArgument(IArgument operation) { LogString($"{nameof(IArgument)} ("); @@ -903,6 +954,18 @@ public override void VisitAnonymousObjectCreationExpression(IAnonymousObjectCrea VisitArray(operation.Initializers, "Initializers", logElementCount: true); } + public override void VisitDynamicObjectCreationExpression(IDynamicObjectCreationExpression operation) + { + LogString(nameof(IDynamicObjectCreationExpression)); + + var name = operation.Name; + LogString($" (Name: {operation.Name})"); + LogCommonPropertiesAndNewLine(operation); + + VisitDynamicArguments(operation); + Visit(operation.Initializer, "Initializer"); + } + public override void VisitObjectOrCollectionInitializerExpression(IObjectOrCollectionInitializerExpression operation) { LogString(nameof(IObjectOrCollectionInitializerExpression)); @@ -1061,8 +1124,6 @@ public override void VisitDefaultValueExpression(IDefaultValueExpression operati { LogString(nameof(IDefaultValueExpression)); LogCommonPropertiesAndNewLine(operation); - - base.VisitDefaultValueExpression(operation); } public override void VisitTypeParameterObjectCreationExpression(ITypeParameterObjectCreationExpression operation) @@ -1070,7 +1131,7 @@ public override void VisitTypeParameterObjectCreationExpression(ITypeParameterOb LogString(nameof(ITypeParameterObjectCreationExpression)); LogCommonPropertiesAndNewLine(operation); - base.VisitTypeParameterObjectCreationExpression(operation); + Visit(operation.Initializer); } public override void VisitInvalidStatement(IInvalidStatement operation) diff --git a/src/Test/Utilities/Portable/Compilation/TestOperationWalker.cs b/src/Test/Utilities/Portable/Compilation/TestOperationWalker.cs index 925e6fd4b8e916fc4f5cb6be6be84cbd03aefb74..2938196116bab636442a4487f11b39fc34a4a7f0 100644 --- a/src/Test/Utilities/Portable/Compilation/TestOperationWalker.cs +++ b/src/Test/Utilities/Portable/Compilation/TestOperationWalker.cs @@ -435,6 +435,16 @@ public override void VisitAnonymousObjectCreationExpression(IAnonymousObjectCrea base.VisitAnonymousObjectCreationExpression(operation); } + public override void VisitDynamicObjectCreationExpression(IDynamicObjectCreationExpression operation) + { + var name = operation.Name; + var applicableSymbols = operation.ApplicableSymbols; + var names = operation.ArgumentNames; + var refKinds = operation.ArgumentRefKinds; + + base.VisitDynamicObjectCreationExpression(operation); + } + public override void VisitObjectOrCollectionInitializerExpression(IObjectOrCollectionInitializerExpression operation) { base.VisitObjectOrCollectionInitializerExpression(operation);