Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IOperation Test Porting Pt 3 #51206

Merged
merged 14 commits into from
Feb 25, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 18 additions & 13 deletions src/Compilers/CSharp/Portable/Binder/Binder_Attributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ private BoundAttribute BindAttributeCore(AttributeSyntax node, NamedTypeSymbol a
}
diagnostics.Add(node, useSiteInfo);

var constructorArguments = analyzedArguments.ConstructorArguments;
ImmutableArray<BoundExpression> boundConstructorArguments;
if (attributeConstructor is object)
{
ReportDiagnosticsIfObsolete(diagnostics, attributeConstructor, node, hasBaseReceiver: false);
Expand All @@ -177,12 +179,21 @@ private BoundAttribute BindAttributeCore(AttributeSyntax node, NamedTypeSymbol a
{
Error(diagnostics, ErrorCode.ERR_AttributeCtorInParameter, node, attributeConstructor.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat));
}

boundConstructorArguments = BuildArgumentsForErrorRecovery(constructorArguments, ImmutableArray.Create(attributeConstructor));
333fred marked this conversation as resolved.
Show resolved Hide resolved
constructorArguments.Arguments.Free();
}
else
{
boundConstructorArguments = constructorArguments.Arguments.SelectAsArrayInPlaceAndFree(
(arg, @this) => @this.BindToTypeForErrorRecovery(arg), this);
}

var constructorArguments = analyzedArguments.ConstructorArguments;
ImmutableArray<BoundExpression> boundConstructorArguments = constructorArguments.Arguments.ToImmutableAndFree();
ImmutableArray<string> boundConstructorArgumentNamesOpt = constructorArguments.GetNames();
ImmutableArray<BoundExpression> boundNamedArguments = analyzedArguments.NamedArguments;
ImmutableArray<BoundExpression> boundNamedArguments =
analyzedArguments.NamedArguments?.SelectAsArrayInPlaceAndFree((namedArg, @this) => @this.BindToTypeForErrorRecovery(namedArg), this)
333fred marked this conversation as resolved.
Show resolved Hide resolved
?? ImmutableArray<BoundExpression>.Empty;

constructorArguments.Free();

return new BoundAttribute(node, attributeConstructor, boundConstructorArguments, boundConstructorArgumentNamesOpt, argsToParamsOpt, expanded,
Expand Down Expand Up @@ -301,11 +312,10 @@ private AnalyzedAttributeArguments BindAttributeArguments(
BindingDiagnosticBag diagnostics)
{
var boundConstructorArguments = AnalyzedArguments.GetInstance();
var boundNamedArguments = ImmutableArray<BoundExpression>.Empty;
ArrayBuilder<BoundExpression>? boundNamedArgumentsBuilder = null;

if (attributeArgumentList != null)
{
ArrayBuilder<BoundExpression>? boundNamedArgumentsBuilder = null;
HashSet<string>? boundNamedArgumentsSet = null;

// Only report the first "non-trailing named args required C# 7.2" error,
Expand Down Expand Up @@ -356,14 +366,9 @@ private AnalyzedAttributeArguments BindAttributeArguments(
boundNamedArgumentsSet.Add(argumentName);
}
}

if (boundNamedArgumentsBuilder != null)
{
boundNamedArguments = boundNamedArgumentsBuilder.ToImmutableAndFree();
}
}

return new AnalyzedAttributeArguments(boundConstructorArguments, boundNamedArguments);
return new AnalyzedAttributeArguments(boundConstructorArguments, boundNamedArgumentsBuilder);
}

private BoundExpression BindNamedAttributeArgument(AttributeArgumentSyntax namedArgument, NamedTypeSymbol attributeType, BindingDiagnosticBag diagnostics)
Expand Down Expand Up @@ -1248,9 +1253,9 @@ private static TypedConstant CreateTypedConstant(BoundExpression node, TypedCons
private struct AnalyzedAttributeArguments
{
internal readonly AnalyzedArguments ConstructorArguments;
internal readonly ImmutableArray<BoundExpression> NamedArguments;
internal readonly ArrayBuilder<BoundExpression>? NamedArguments;

internal AnalyzedAttributeArguments(AnalyzedArguments constructorArguments, ImmutableArray<BoundExpression> namedArguments)
internal AnalyzedAttributeArguments(AnalyzedArguments constructorArguments, ArrayBuilder<BoundExpression>? namedArguments)
{
this.ConstructorArguments = constructorArguments;
this.NamedArguments = namedArguments;
Expand Down
84 changes: 84 additions & 0 deletions src/Compilers/CSharp/Test/Emit/CodeGen/PatternTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#nullable disable

using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
Expand Down Expand Up @@ -4871,6 +4873,88 @@ public class B
// [My(1 switch { 1 => 1, _ => string.Empty })]
Diagnostic(ErrorCode.ERR_BadArgType, "1 switch { 1 => 1, _ => string.Empty }").WithArguments("1", "<switch expression>", "int").WithLocation(11, 9)
);

var tree = compilation.SyntaxTrees[0];
var model = compilation.GetSemanticModel(tree);

var switchExpressions = tree.GetRoot().DescendantNodes().OfType<SwitchExpressionSyntax>().ToArray();

VerifyOperationTreeForNode(compilation, model, switchExpressions[0], @"
ISwitchExpressionOperation (2 arms) (OperationKind.SwitchExpression, Type: System.Int32, IsInvalid) (Syntax: '1 switch { ... 1, _ => 2 }')
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
Arms(2):
ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '1 => 1')
Pattern:
IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsInvalid) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '_ => 2')
Pattern:
IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null, IsInvalid) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsInvalid) (Syntax: '2')
");

VerifyOperationTreeForNode(compilation, model, switchExpressions[1], @"
ISwitchExpressionOperation (2 arms) (OperationKind.SwitchExpression, Type: System.Int32, IsInvalid) (Syntax: '1 switch { ... > new B() }')
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
Arms(2):
ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '1 => new A()')
Pattern:
IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsInvalid) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
Value:
IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: System.Int32 A.op_Implicit(A a)) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: 'new A()')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 A.op_Implicit(A a))
Operand:
IObjectCreationOperation (Constructor: A..ctor()) (OperationKind.ObjectCreation, Type: A, IsInvalid) (Syntax: 'new A()')
Arguments(0)
Initializer:
null
ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '_ => new B()')
Pattern:
IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null, IsInvalid) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
Value:
IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: System.Int32 B.op_Implicit(B b)) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: 'new B()')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 B.op_Implicit(B b))
Operand:
IObjectCreationOperation (Constructor: B..ctor()) (OperationKind.ObjectCreation, Type: B, IsInvalid) (Syntax: 'new B()')
Arguments(0)
Initializer:
null
");

VerifyOperationTreeForNode(compilation, model, switchExpressions[2], @"
ISwitchExpressionOperation (2 arms) (OperationKind.SwitchExpression, Type: ?, IsInvalid) (Syntax: '1 switch { ... ing.Empty }')
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
Arms(2):
ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '1 => 1')
Pattern:
IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsInvalid) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
Value:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsInvalid, IsImplicit) (Syntax: '1')
Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '_ => string.Empty')
Pattern:
IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null, IsInvalid) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
Value:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsInvalid, IsImplicit) (Syntax: 'string.Empty')
Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
IFieldReferenceOperation: System.String System.String.Empty (Static) (OperationKind.FieldReference, Type: System.String, IsInvalid) (Syntax: 'string.Empty')
Instance Receiver:
null
");
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15183,5 +15183,135 @@ static void F(A a)
Predecessors: [B3]
Statements (0)");
}

[Fact]
public void IndexedPropertyWithDefaultArgumentInVB()
{
var source1 =
@"Imports System
Imports System.Collections.Generic
Imports System.Runtime.InteropServices
<Assembly: PrimaryInteropAssembly(0, 0)>
<Assembly: Guid(""165F752D-E9C4-4F7E-B0D0-CDFD7A36E210"")>
<ComImport()>
<Guid(""165F752D-E9C4-4F7E-B0D0-CDFD7A36E211"")>
<CoClass(GetType(A))>
Public Interface IA
Property P1(Optional index As Integer = 1) As Object
ReadOnly Property P2(Optional index As Integer = 2) As IA
End Interface
Public Class A
Implements IA
Property P1(Optional index As Integer = 1) As Object Implements IA.P1
Get
Return Nothing
End Get
Set(value As Object)
End Set
End Property
ReadOnly Property P2(Optional index As Integer = 2) As IA Implements IA.P2
Get
Return New A()
End Get
End Property
End Class";
var reference1 = BasicCompilationUtils.CompileToMetadata(source1, verify: Verification.Passes);
var source2 =
@"class B
{
static void M(IA a)
/*<bind>*/{
a = new IA() { P2 = { P1 = 5 } };
}/*</bind>*/
}";

VerifyFlowGraphAndDiagnosticsForTest<BlockSyntax>(source2, expectedDiagnostics: DiagnosticDescription.None, references: new[] { reference1 },
expectedFlowGraph: @"
Block[B0] - Entry
Statements (0)
Next (Regular) Block[B1]
Entering: {R1}
.locals {R1}
{
CaptureIds: [0] [1]
Block[B1] - Block
Predecessors: [B0]
Statements (2)
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a')
Value:
IParameterReferenceOperation: a (OperationKind.ParameterReference, Type: IA) (Syntax: 'a')
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'new IA() { ... P1 = 5 } }')
Value:
IObjectCreationOperation (Constructor: A..ctor()) (OperationKind.ObjectCreation, Type: IA) (Syntax: 'new IA() { ... P1 = 5 } }')
Arguments(0)
Initializer:
null
Next (Regular) Block[B2]
Entering: {R2}
.locals {R2}
{
CaptureIds: [2]
Block[B2] - Block
Predecessors: [B1]
Statements (1)
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'P2')
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsImplicit) (Syntax: 'P2')
Next (Regular) Block[B3]
Entering: {R3}
.locals {R3}
{
CaptureIds: [3]
Block[B3] - Block
Predecessors: [B2]
Statements (2)
IFlowCaptureOperation: 3 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'P1')
Value:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsImplicit) (Syntax: 'P1')
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Object) (Syntax: 'P1 = 5')
Left:
IPropertyReferenceOperation: System.Object IA.P1[[System.Int32 index = 1]] { get; set; } (OperationKind.PropertyReference, Type: System.Object) (Syntax: 'P1')
Instance Receiver:
IPropertyReferenceOperation: IA IA.P2[[System.Int32 index = 2]] { get; } (OperationKind.PropertyReference, Type: IA) (Syntax: 'P2')
Instance Receiver:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: IA, IsImplicit) (Syntax: 'new IA() { ... P1 = 5 } }')
Arguments(1):
IArgumentOperation (ArgumentKind.DefaultValue, Matching Parameter: index) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'P2')
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Int32, Constant: 2, IsImplicit) (Syntax: 'P2')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Arguments(1):
IArgumentOperation (ArgumentKind.DefaultValue, Matching Parameter: index) (OperationKind.Argument, Type: null, IsImplicit) (Syntax: 'P1')
IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: System.Int32, Constant: 1, IsImplicit) (Syntax: 'P1')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Right:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsImplicit) (Syntax: '5')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
(Boxing)
Operand:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 5) (Syntax: '5')
Next (Regular) Block[B4]
Leaving: {R3} {R2}
}
}
Block[B4] - Block
Predecessors: [B3]
Statements (1)
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a = new IA( ... P1 = 5 } };')
Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: IA) (Syntax: 'a = new IA( ... P1 = 5 } }')
Left:
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: IA, IsImplicit) (Syntax: 'a')
Right:
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: IA, IsImplicit) (Syntax: 'new IA() { ... P1 = 5 } }')
Next (Regular) Block[B5]
Leaving: {R1}
}
Block[B5] - Exit
Predecessors: [B4]
Statements (0)
");
}
}
}
Loading