Skip to content

Commit

Permalink
Add IOperation support for variations of object creation expressions …
Browse files Browse the repository at this point in the history
…(type parameter, nopia and dynamic)

Fixes dotnet#20119 and dotnet#20491
  • Loading branch information
mavasani committed Jul 18, 2017
1 parent 027166f commit b4757ad
Show file tree
Hide file tree
Showing 20 changed files with 752 additions and 30 deletions.
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4469,6 +4469,7 @@ protected BoundExpression BindClassCreationExpression(

result = new BoundDynamicObjectCreationExpression(
node,
typeName,
argArray,
analyzedArguments.GetNames(),
analyzedArguments.RefKinds.ToImmutableOrNull(),
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1289,6 +1289,7 @@
<Node Name="BoundDynamicObjectCreationExpression" Base="BoundExpression">
<!-- Non-null type is required for this node kind -->
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="Name" Type="string" Null="disallow"/>
<Field Name="Arguments" Type="ImmutableArray&lt;BoundExpression&gt;"/>
<Field Name="ArgumentNamesOpt" Type="ImmutableArray&lt;string&gt;" Null="allow"/>
<Field Name="ArgumentRefKindsOpt" Type="ImmutableArray&lt;RefKind&gt;" Null="allow"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4650,14 +4650,16 @@ public BoundConvertedTupleLiteral Update(TypeSymbol naturalTypeOpt, ImmutableArr

internal sealed partial class BoundDynamicObjectCreationExpression : BoundExpression
{
public BoundDynamicObjectCreationExpression(SyntaxNode syntax, ImmutableArray<BoundExpression> arguments, ImmutableArray<string> argumentNamesOpt, ImmutableArray<RefKind> argumentRefKindsOpt, BoundExpression initializerExpressionOpt, ImmutableArray<MethodSymbol> applicableMethods, TypeSymbol type, bool hasErrors = false)
public BoundDynamicObjectCreationExpression(SyntaxNode syntax, string name, ImmutableArray<BoundExpression> arguments, ImmutableArray<string> argumentNamesOpt, ImmutableArray<RefKind> argumentRefKindsOpt, BoundExpression initializerExpressionOpt, ImmutableArray<MethodSymbol> 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;
Expand All @@ -4666,6 +4668,8 @@ public BoundDynamicObjectCreationExpression(SyntaxNode syntax, ImmutableArray<Bo
}


public string Name { get; }

public ImmutableArray<BoundExpression> Arguments { get; }

public ImmutableArray<string> ArgumentNamesOpt { get; }
Expand All @@ -4681,11 +4685,11 @@ public override BoundNode Accept(BoundTreeVisitor visitor)
return visitor.VisitDynamicObjectCreationExpression(this);
}

public BoundDynamicObjectCreationExpression Update(ImmutableArray<BoundExpression> arguments, ImmutableArray<string> argumentNamesOpt, ImmutableArray<RefKind> argumentRefKindsOpt, BoundExpression initializerExpressionOpt, ImmutableArray<MethodSymbol> applicableMethods, TypeSymbol type)
public BoundDynamicObjectCreationExpression Update(string name, ImmutableArray<BoundExpression> arguments, ImmutableArray<string> argumentNamesOpt, ImmutableArray<RefKind> argumentRefKindsOpt, BoundExpression initializerExpressionOpt, ImmutableArray<MethodSymbol> 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;
}
Expand Down Expand Up @@ -9020,7 +9024,7 @@ public override BoundNode VisitDynamicObjectCreationExpression(BoundDynamicObjec
ImmutableArray<BoundExpression> arguments = (ImmutableArray<BoundExpression>)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)
{
Expand Down Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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<ISymbol> applicableSymbols = StaticCast<ISymbol>.From(boundDynamicObjectCreationExpression.ApplicableMethods);
Lazy<ImmutableArray<IOperation>> arguments = new Lazy<ImmutableArray<IOperation>>(() => boundDynamicObjectCreationExpression.Arguments.SelectAsArray(n => Create(n)));
ImmutableArray<string> argumentNames = boundDynamicObjectCreationExpression.ArgumentNamesOpt.NullToEmpty();
ImmutableArray<RefKind> argumentRefKinds = boundDynamicObjectCreationExpression.ArgumentRefKindsOpt.NullToEmpty();
Lazy<IObjectOrCollectionInitializerExpression> initializer = new Lazy<IObjectOrCollectionInitializerExpression>(() => (IObjectOrCollectionInitializerExpression)Create(boundDynamicObjectCreationExpression.InitializerExpressionOpt));
SyntaxNode syntax = boundDynamicObjectCreationExpression.Syntax;
ITypeSymbol type = boundDynamicObjectCreationExpression.Type;
Optional<object> constantValue = ConvertToOptional(boundDynamicObjectCreationExpression.ConstantValue);
return new LazyDynamicObjectCreationExpression(name, applicableSymbols, arguments, argumentNames, argumentRefKinds, initializer, syntax, type, constantValue);
}

private IObjectOrCollectionInitializerExpression CreateBoundObjectInitializerExpressionOperation(BoundObjectInitializerExpression boundObjectInitializerExpression)
{
Lazy<ImmutableArray<IOperation>> initializers = new Lazy<ImmutableArray<IOperation>>(() => BoundObjectCreationExpression.GetChildInitializers(boundObjectInitializerExpression).SelectAsArray(n => Create(n)));
Expand Down Expand Up @@ -733,10 +749,11 @@ private IInvalidExpression CreateBoundBadExpressionOperation(BoundBadExpression

private ITypeParameterObjectCreationExpression CreateBoundNewTOperation(BoundNewT boundNewT)
{
Lazy<IObjectOrCollectionInitializerExpression> initializer = new Lazy<IObjectOrCollectionInitializerExpression>(() => (IObjectOrCollectionInitializerExpression)Create(boundNewT.InitializerExpressionOpt));
SyntaxNode syntax = boundNewT.Syntax;
ITypeSymbol type = boundNewT.Type;
Optional<object> constantValue = ConvertToOptional(boundNewT.ConstantValue);
return new TypeParameterObjectCreationExpression(syntax, type, constantValue);
return new LazyTypeParameterObjectCreationExpression(initializer, syntax, type, constantValue);
}

private IUnaryOperatorExpression CreateBoundUnaryOperatorOperation(BoundUnaryOperator boundUnaryOperator)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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'
Expand Down Expand Up @@ -1969,6 +1971,7 @@ static void M1<T>()
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;

Expand Down Expand Up @@ -1999,6 +2002,7 @@ static void M1<T>()
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?)
Expand Down Expand Up @@ -2034,6 +2038,7 @@ static void M1<T, U>()
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;

Expand Down Expand Up @@ -2065,6 +2070,7 @@ static void M1<T, U>()
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'
Expand Down
Loading

0 comments on commit b4757ad

Please sign in to comment.