@@ -8280,5 +8280,336 @@ void M(int? start)
82808280 var operation = ( IRangeOperation ) VerifyOperationTreeForTest < RangeExpressionSyntax > ( compilation , expectedOperationTree ) ;
82818281 Assert . Equal ( RangeStartAtSignature , operation . Method . ToTestDisplayString ( ) ) ;
82828282 }
8283+
8284+ [ CompilerTrait ( CompilerFeature . IOperation ) ]
8285+ [ Fact ]
8286+ public void Extensions_01 ( )
8287+ {
8288+ var source = @"
8289+ struct C
8290+ {
8291+ void F(C x, C y)
8292+ {
8293+ var z = /*<bind>*/x + y/*</bind>*/;
8294+ }
8295+ }
8296+
8297+ static class Extensions
8298+ {
8299+ extension(C)
8300+ {
8301+ public static C operator +(C c1, C c2) { }
8302+ }
8303+ }
8304+ " ;
8305+
8306+ string expectedOperationTree =
8307+ @"
8308+ IBinaryOperation (BinaryOperatorKind.Add) (OperatorMethod: C Extensions.<>E__0.op_Addition(C c1, C c2)) (OperationKind.Binary, Type: C) (Syntax: 'x + y')
8309+ Left:
8310+ IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: C) (Syntax: 'x')
8311+ Right:
8312+ IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: C) (Syntax: 'y')
8313+ " ;
8314+
8315+ VerifyOperationTreeForTest < BinaryExpressionSyntax > ( source , expectedOperationTree ) ;
8316+ }
8317+
8318+ [ CompilerTrait ( CompilerFeature . IOperation ) ]
8319+ [ Fact ]
8320+ public void Extensions_02_Logical ( )
8321+ {
8322+ var source = @"
8323+ struct C
8324+ {
8325+ void F(C x, C y)
8326+ {
8327+ var z = /*<bind>*/x || y/*</bind>*/;
8328+ }
8329+ }
8330+
8331+ static class Extensions
8332+ {
8333+ extension(C)
8334+ {
8335+ public static C operator &(C x, C y) => throw null;
8336+ public static C operator |(C x, C y) => throw null;
8337+ public static bool operator true(C c) => throw null;
8338+ public static bool operator false(C c) => throw null;
8339+ }
8340+ }
8341+ " ;
8342+
8343+ string expectedOperationTree =
8344+ @"
8345+ IBinaryOperation (BinaryOperatorKind.ConditionalOr) (OperatorMethod: C Extensions.<>E__0.op_BitwiseOr(C x, C y)) (OperationKind.Binary, Type: C) (Syntax: 'x || y')
8346+ Left:
8347+ IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: C) (Syntax: 'x')
8348+ Right:
8349+ IParameterReferenceOperation: y (OperationKind.ParameterReference, Type: C) (Syntax: 'y')
8350+ " ;
8351+
8352+ VerifyOperationTreeForTest < BinaryExpressionSyntax > ( source , expectedOperationTree ) ;
8353+ }
8354+
8355+ [ CompilerTrait ( CompilerFeature . IOperation , CompilerFeature . Dataflow ) ]
8356+ [ Fact ]
8357+ public void Extensions_03_Flow ( )
8358+ {
8359+ string source = @"
8360+ using System;
8361+ class C
8362+ {
8363+ void M(C a, C b)
8364+ /*<bind>*/{
8365+ GetArray()[0] = (a ?? b) + (a ?? b);
8366+ }/*</bind>*/
8367+
8368+ static int[] GetArray() => null;
8369+ }
8370+
8371+ static class Extensions
8372+ {
8373+ extension(C)
8374+ {
8375+ public static int operator +(C c1, C c2) => 0;
8376+ }
8377+ }
8378+ " ;
8379+ var expectedDiagnostics = DiagnosticDescription . None ;
8380+
8381+ string expectedGraph = @"
8382+ Block[B0] - Entry
8383+ Statements (0)
8384+ Next (Regular) Block[B1]
8385+ Entering: {R1}
8386+
8387+ .locals {R1}
8388+ {
8389+ CaptureIds: [0] [2] [4]
8390+ Block[B1] - Block
8391+ Predecessors: [B0]
8392+ Statements (1)
8393+ IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'GetArray()[0]')
8394+ Value:
8395+ IArrayElementReferenceOperation (OperationKind.ArrayElementReference, Type: System.Int32) (Syntax: 'GetArray()[0]')
8396+ Array reference:
8397+ IInvocationOperation (System.Int32[] C.GetArray()) (OperationKind.Invocation, Type: System.Int32[]) (Syntax: 'GetArray()')
8398+ Instance Receiver:
8399+ null
8400+ Arguments(0)
8401+ Indices(1):
8402+ ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0')
8403+
8404+ Next (Regular) Block[B2]
8405+ Entering: {R2}
8406+
8407+ .locals {R2}
8408+ {
8409+ CaptureIds: [1]
8410+ Block[B2] - Block
8411+ Predecessors: [B1]
8412+ Statements (1)
8413+ IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a')
8414+ Value:
8415+ IParameterReferenceOperation: a (OperationKind.ParameterReference, Type: C) (Syntax: 'a')
8416+
8417+ Jump if True (Regular) to Block[B4]
8418+ IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'a')
8419+ Operand:
8420+ IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: C, IsImplicit) (Syntax: 'a')
8421+ Leaving: {R2}
8422+
8423+ Next (Regular) Block[B3]
8424+ Block[B3] - Block
8425+ Predecessors: [B2]
8426+ Statements (1)
8427+ IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a')
8428+ Value:
8429+ IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: C, IsImplicit) (Syntax: 'a')
8430+
8431+ Next (Regular) Block[B5]
8432+ Leaving: {R2}
8433+ Entering: {R3}
8434+ }
8435+
8436+ Block[B4] - Block
8437+ Predecessors: [B2]
8438+ Statements (1)
8439+ IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
8440+ Value:
8441+ IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: C) (Syntax: 'b')
8442+
8443+ Next (Regular) Block[B5]
8444+ Entering: {R3}
8445+
8446+ .locals {R3}
8447+ {
8448+ CaptureIds: [3]
8449+ Block[B5] - Block
8450+ Predecessors: [B3] [B4]
8451+ Statements (1)
8452+ IFlowCaptureOperation: 3 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a')
8453+ Value:
8454+ IParameterReferenceOperation: a (OperationKind.ParameterReference, Type: C) (Syntax: 'a')
8455+
8456+ Jump if True (Regular) to Block[B7]
8457+ IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 'a')
8458+ Operand:
8459+ IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: C, IsImplicit) (Syntax: 'a')
8460+ Leaving: {R3}
8461+
8462+ Next (Regular) Block[B6]
8463+ Block[B6] - Block
8464+ Predecessors: [B5]
8465+ Statements (1)
8466+ IFlowCaptureOperation: 4 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a')
8467+ Value:
8468+ IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: C, IsImplicit) (Syntax: 'a')
8469+
8470+ Next (Regular) Block[B8]
8471+ Leaving: {R3}
8472+ }
8473+
8474+ Block[B7] - Block
8475+ Predecessors: [B5]
8476+ Statements (1)
8477+ IFlowCaptureOperation: 4 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'b')
8478+ Value:
8479+ IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: C) (Syntax: 'b')
8480+
8481+ Next (Regular) Block[B8]
8482+ Block[B8] - Block
8483+ Predecessors: [B6] [B7]
8484+ Statements (1)
8485+ IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'GetArray()[ ... + (a ?? b);')
8486+ Expression:
8487+ ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: 'GetArray()[ ... + (a ?? b)')
8488+ Left:
8489+ IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Int32, IsImplicit) (Syntax: 'GetArray()[0]')
8490+ Right:
8491+ IBinaryOperation (BinaryOperatorKind.Add) (OperatorMethod: System.Int32 Extensions.<>E__0.op_Addition(C c1, C c2)) (OperationKind.Binary, Type: System.Int32) (Syntax: '(a ?? b) + (a ?? b)')
8492+ Left:
8493+ IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: C, IsImplicit) (Syntax: 'a ?? b')
8494+ Right:
8495+ IFlowCaptureReferenceOperation: 4 (OperationKind.FlowCaptureReference, Type: C, IsImplicit) (Syntax: 'a ?? b')
8496+
8497+ Next (Regular) Block[B9]
8498+ Leaving: {R1}
8499+ }
8500+
8501+ Block[B9] - Exit
8502+ Predecessors: [B8]
8503+ Statements (0)
8504+ " ;
8505+ VerifyFlowGraphAndDiagnosticsForTest < BlockSyntax > ( source , expectedGraph , expectedDiagnostics ) ;
8506+ }
8507+
8508+ [ CompilerTrait ( CompilerFeature . IOperation , CompilerFeature . Dataflow ) ]
8509+ [ Fact ]
8510+ public void Extensions_04_Logical_Flow ( )
8511+ {
8512+ string source = @"
8513+ class C
8514+ {
8515+ void M(C a, C b, C result)
8516+ /*<bind>*/{
8517+ result = a || b;
8518+ }/*</bind>*/
8519+ }
8520+
8521+ static class Extensions
8522+ {
8523+ extension(C)
8524+ {
8525+ public static C operator &(C x, C y) => throw null;
8526+ public static C operator |(C x, C y) => throw null;
8527+ public static bool operator true(C c) => throw null;
8528+ public static bool operator false(C c) => throw null;
8529+ }
8530+ }
8531+ " ;
8532+ string expectedGraph = @"
8533+ Block[B0] - Entry
8534+ Statements (0)
8535+ Next (Regular) Block[B1]
8536+ Entering: {R1}
8537+
8538+ .locals {R1}
8539+ {
8540+ CaptureIds: [0] [2]
8541+ Block[B1] - Block
8542+ Predecessors: [B0]
8543+ Statements (1)
8544+ IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'result')
8545+ Value:
8546+ IParameterReferenceOperation: result (OperationKind.ParameterReference, Type: C) (Syntax: 'result')
8547+
8548+ Next (Regular) Block[B2]
8549+ Entering: {R2}
8550+
8551+ .locals {R2}
8552+ {
8553+ CaptureIds: [1]
8554+ Block[B2] - Block
8555+ Predecessors: [B1]
8556+ Statements (1)
8557+ IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a')
8558+ Value:
8559+ IParameterReferenceOperation: a (OperationKind.ParameterReference, Type: C) (Syntax: 'a')
8560+
8561+ Jump if False (Regular) to Block[B4]
8562+ IUnaryOperation (UnaryOperatorKind.True) (OperatorMethod: System.Boolean Extensions.<>E__0.op_True(C c)) (OperationKind.Unary, Type: System.Boolean, IsImplicit) (Syntax: 'a')
8563+ Operand:
8564+ IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: C, IsImplicit) (Syntax: 'a')
8565+
8566+ Next (Regular) Block[B3]
8567+ Block[B3] - Block
8568+ Predecessors: [B2]
8569+ Statements (1)
8570+ IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a || b')
8571+ Value:
8572+ IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: C, IsImplicit) (Syntax: 'a')
8573+
8574+ Next (Regular) Block[B5]
8575+ Leaving: {R2}
8576+ Block[B4] - Block
8577+ Predecessors: [B2]
8578+ Statements (1)
8579+ IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 'a || b')
8580+ Value:
8581+ IBinaryOperation (BinaryOperatorKind.Or) (OperatorMethod: C Extensions.<>E__0.op_BitwiseOr(C x, C y)) (OperationKind.Binary, Type: C) (Syntax: 'a || b')
8582+ Left:
8583+ IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: C, IsImplicit) (Syntax: 'a')
8584+ Right:
8585+ IParameterReferenceOperation: b (OperationKind.ParameterReference, Type: C) (Syntax: 'b')
8586+
8587+ Next (Regular) Block[B5]
8588+ Leaving: {R2}
8589+ }
8590+
8591+ Block[B5] - Block
8592+ Predecessors: [B3] [B4]
8593+ Statements (1)
8594+ IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'result = a || b;')
8595+ Expression:
8596+ ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: C) (Syntax: 'result = a || b')
8597+ Left:
8598+ IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: C, IsImplicit) (Syntax: 'result')
8599+ Right:
8600+ IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: C, IsImplicit) (Syntax: 'a || b')
8601+
8602+ Next (Regular) Block[B6]
8603+ Leaving: {R1}
8604+ }
8605+
8606+ Block[B6] - Exit
8607+ Predecessors: [B5]
8608+ Statements (0)
8609+ " ;
8610+ var expectedDiagnostics = DiagnosticDescription . None ;
8611+
8612+ VerifyFlowGraphAndDiagnosticsForTest < BlockSyntax > ( source , expectedGraph , expectedDiagnostics ) ;
8613+ }
82838614 }
82848615}
0 commit comments