未验证 提交 a604cefe 编写于 作者: F Fred Silberberg 提交者: GitHub

Merge pull request #23041 from 333fred/compound-expressions-conversions

Compound expressions conversions
...@@ -706,6 +706,58 @@ public static Conversion GetConversion(this IConversionOperation conversionExpre ...@@ -706,6 +706,58 @@ public static Conversion GetConversion(this IConversionOperation conversionExpre
} }
} }
/// <summary>
/// Gets the underlying <see cref="Conversion"/> information from this <see cref="ICompoundAssignmentOperation"/>. This
/// conversion is applied before the operator is applied to the result of this conversion and <see cref="IAssignmentOperation.Value"/>.
/// </summary>
/// <remarks>
/// This compound assignment must have been created from C# code.
/// </remarks>
public static Conversion GetInConversion(this ICompoundAssignmentOperation compoundAssignment)
{
if (compoundAssignment == null)
{
throw new ArgumentNullException(nameof(compoundAssignment));
}
if (compoundAssignment is BaseCSharpCompoundAssignmentOperation csharpCompoundAssignment)
{
return csharpCompoundAssignment.InConversionInternal;
}
else
{
throw new ArgumentException(string.Format(CSharpResources.ICompoundAssignmentOperationIsNotCSharpCompoundAssignment,
nameof(compoundAssignment)),
nameof(compoundAssignment));
}
}
/// <summary>
/// Gets the underlying <see cref="Conversion"/> information from this <see cref="ICompoundAssignmentOperation"/>. This
/// conversion is applied after the operator is applied, before the result is assigned to <see cref="IAssignmentOperation.Target"/>.
/// </summary>
/// <remarks>
/// This compound assignment must have been created from C# code.
/// </remarks>
public static Conversion GetOutConversion(this ICompoundAssignmentOperation compoundAssignment)
{
if (compoundAssignment == null)
{
throw new ArgumentNullException(nameof(compoundAssignment));
}
if (compoundAssignment is BaseCSharpCompoundAssignmentOperation csharpCompoundAssignemnt)
{
return csharpCompoundAssignemnt.OutConversionInternal;
}
else
{
throw new ArgumentException(string.Format(CSharpResources.ICompoundAssignmentOperationIsNotCSharpCompoundAssignment,
nameof(compoundAssignment)),
nameof(compoundAssignment));
}
}
public static Conversion GetSpeculativeConversion(this SemanticModel semanticModel, int position, ExpressionSyntax expression, SpeculativeBindingOption bindingOption) public static Conversion GetSpeculativeConversion(this SemanticModel semanticModel, int position, ExpressionSyntax expression, SpeculativeBindingOption bindingOption)
{ {
var csmodel = semanticModel as CSharpSemanticModel; var csmodel = semanticModel as CSharpSemanticModel;
......
...@@ -10069,6 +10069,15 @@ internal class CSharpResources { ...@@ -10069,6 +10069,15 @@ internal class CSharpResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to {0} is not a valid C# compound assignment operation.
/// </summary>
internal static string ICompoundAssignmentOperationIsNotCSharpCompoundAssignment {
get {
return ResourceManager.GetString("ICompoundAssignmentOperationIsNotCSharpCompoundAssignment", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to {0} is not a valid C# conversion expression. /// Looks up a localized string similar to {0} is not a valid C# conversion expression.
/// </summary> /// </summary>
......
...@@ -5207,4 +5207,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ ...@@ -5207,4 +5207,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_RefExtensionMustBeValueTypeOrConstrainedToOne" xml:space="preserve"> <data name="ERR_RefExtensionMustBeValueTypeOrConstrainedToOne" xml:space="preserve">
<value>The first parameter of a 'ref' extension method '{0}' must be a value type or a generic type constrained to struct.</value> <value>The first parameter of a 'ref' extension method '{0}' must be a value type or a generic type constrained to struct.</value>
</data> </data>
<data name="ICompoundAssignmentOperationIsNotCSharpCompoundAssignment" xml:space="preserve">
<value>{0} is not a valid C# compound assignment operation</value>
</data>
</root> </root>
\ No newline at end of file
using System;
using Microsoft.CodeAnalysis.Operations;
namespace Microsoft.CodeAnalysis.CSharp
{
internal abstract class BaseCSharpCompoundAssignmentOperation : BaseCompoundAssignmentExpression
{
protected BaseCSharpCompoundAssignmentOperation(Conversion inConversion, Conversion outConversion, Operations.BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) : base(operatorKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit)
{
InConversionInternal = inConversion;
OutConversionInternal = outConversion;
}
internal Conversion InConversionInternal { get; }
internal Conversion OutConversionInternal { get; }
public override CommonConversion InConversion => InConversionInternal.ToCommonConversion();
public override CommonConversion OutConversion => OutConversionInternal.ToCommonConversion();
}
internal sealed class CSharpCompoundAssignmentOperation : BaseCSharpCompoundAssignmentOperation
{
public CSharpCompoundAssignmentOperation(IOperation target, IOperation value, Conversion inConversion, Conversion outConversion, Operations.BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(inConversion, outConversion, operatorKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit)
{
TargetImpl = target;
ValueImpl = value;
}
protected override IOperation TargetImpl { get; }
protected override IOperation ValueImpl { get; }
}
internal sealed class LazyCSharpCompoundAssignmentOperation : BaseCSharpCompoundAssignmentOperation
{
private readonly Lazy<IOperation> _lazyTarget;
private readonly Lazy<IOperation> _lazyValue;
public LazyCSharpCompoundAssignmentOperation(Lazy<IOperation> target, Lazy<IOperation> value, Conversion inConversion, Conversion outConversion, Operations.BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(inConversion, outConversion, operatorKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit)
{
_lazyTarget = target;
_lazyValue = value;
}
protected override IOperation TargetImpl => _lazyTarget.Value;
protected override IOperation ValueImpl => _lazyValue.Value;
}
}
...@@ -17,5 +17,11 @@ public override IOperation VisitConversion(IConversionOperation operation, objec ...@@ -17,5 +17,11 @@ public override IOperation VisitConversion(IConversionOperation operation, objec
{ {
return new CSharpConversionExpression(Visit(operation.Operand), operation.GetConversion(), operation.IsTryCast, operation.IsChecked, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); return new CSharpConversionExpression(Visit(operation.Operand), operation.GetConversion(), operation.IsTryCast, operation.IsChecked, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
} }
public override IOperation VisitCompoundAssignment(ICompoundAssignmentOperation operation, object argument)
{
var compoundAssignment = (BaseCSharpCompoundAssignmentOperation)operation;
return new CSharpCompoundAssignmentOperation(Visit(operation.Target), Visit(operation.Value), compoundAssignment.InConversionInternal, compoundAssignment.OutConversionInternal, operation.OperatorKind, operation.IsLifted, operation.IsChecked, operation.OperatorMethod, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
}
} }
} }
...@@ -974,6 +974,8 @@ private ICompoundAssignmentOperation CreateBoundCompoundAssignmentOperatorOperat ...@@ -974,6 +974,8 @@ private ICompoundAssignmentOperation CreateBoundCompoundAssignmentOperatorOperat
BinaryOperatorKind operatorKind = Helper.DeriveBinaryOperatorKind(boundCompoundAssignmentOperator.Operator.Kind); BinaryOperatorKind operatorKind = Helper.DeriveBinaryOperatorKind(boundCompoundAssignmentOperator.Operator.Kind);
Lazy<IOperation> target = new Lazy<IOperation>(() => Create(boundCompoundAssignmentOperator.Left)); Lazy<IOperation> target = new Lazy<IOperation>(() => Create(boundCompoundAssignmentOperator.Left));
Lazy<IOperation> value = new Lazy<IOperation>(() => Create(boundCompoundAssignmentOperator.Right)); Lazy<IOperation> value = new Lazy<IOperation>(() => Create(boundCompoundAssignmentOperator.Right));
Conversion inConversion = boundCompoundAssignmentOperator.LeftConversion;
Conversion outConversion = boundCompoundAssignmentOperator.FinalConversion;
bool isLifted = boundCompoundAssignmentOperator.Operator.Kind.IsLifted(); bool isLifted = boundCompoundAssignmentOperator.Operator.Kind.IsLifted();
bool isChecked = boundCompoundAssignmentOperator.Operator.Kind.IsChecked(); bool isChecked = boundCompoundAssignmentOperator.Operator.Kind.IsChecked();
IMethodSymbol operatorMethod = boundCompoundAssignmentOperator.Operator.Method; IMethodSymbol operatorMethod = boundCompoundAssignmentOperator.Operator.Method;
...@@ -981,7 +983,7 @@ private ICompoundAssignmentOperation CreateBoundCompoundAssignmentOperatorOperat ...@@ -981,7 +983,7 @@ private ICompoundAssignmentOperation CreateBoundCompoundAssignmentOperatorOperat
ITypeSymbol type = boundCompoundAssignmentOperator.Type; ITypeSymbol type = boundCompoundAssignmentOperator.Type;
Optional<object> constantValue = ConvertToOptional(boundCompoundAssignmentOperator.ConstantValue); Optional<object> constantValue = ConvertToOptional(boundCompoundAssignmentOperator.ConstantValue);
bool isImplicit = boundCompoundAssignmentOperator.WasCompilerGenerated; bool isImplicit = boundCompoundAssignmentOperator.WasCompilerGenerated;
return new LazyCompoundAssignmentExpression(operatorKind, isLifted, isChecked, target, value, operatorMethod, _semanticModel, syntax, type, constantValue, isImplicit); return new LazyCSharpCompoundAssignmentOperation(target, value, inConversion, outConversion, operatorKind, isLifted, isChecked, operatorMethod, _semanticModel, syntax, type, constantValue, isImplicit);
} }
private IIncrementOrDecrementOperation CreateBoundIncrementOperatorOperation(BoundIncrementOperator boundIncrementOperator) private IIncrementOrDecrementOperation CreateBoundIncrementOperatorOperation(BoundIncrementOperator boundIncrementOperator)
......
...@@ -5,4 +5,6 @@ Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax.ReadOnlyKeyword.get -> Micros ...@@ -5,4 +5,6 @@ Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax.ReadOnlyKeyword.get -> Micros
Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.SyntaxToken readOnlyKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.SyntaxToken readOnlyKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax.WithReadOnlyKeyword(Microsoft.CodeAnalysis.SyntaxToken readOnlyKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax.WithReadOnlyKeyword(Microsoft.CodeAnalysis.SyntaxToken readOnlyKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax
static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetConversion(this Microsoft.CodeAnalysis.Operations.IConversionOperation conversionExpression) -> Microsoft.CodeAnalysis.CSharp.Conversion static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetConversion(this Microsoft.CodeAnalysis.Operations.IConversionOperation conversionExpression) -> Microsoft.CodeAnalysis.CSharp.Conversion
static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetInConversion(this Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation compoundAssignment) -> Microsoft.CodeAnalysis.CSharp.Conversion
static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetOutConversion(this Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation compoundAssignment) -> Microsoft.CodeAnalysis.CSharp.Conversion
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.RefType(Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.SyntaxToken readOnlyKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.RefType(Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.SyntaxToken readOnlyKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.RefTypeSyntax
\ No newline at end of file
// 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;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public partial class IOperationTests : SemanticModelTestBase
{
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_NullArgumentToGetConversionThrows()
{
ICompoundAssignmentOperation nullAssignment = null;
Assert.Throws<ArgumentNullException>("compoundAssignment", () => nullAssignment.GetInConversion());
Assert.Throws<ArgumentNullException>("compoundAssignment", () => nullAssignment.GetOutConversion());
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_BinaryOperatorInOutConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator C(int i)
{
return null;
}
public static implicit operator int(C c)
{
return 0;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperationKind.CompoundAssignment, Type: C) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 C.op_Implicit(C c))
OutConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: C C.op_Implicit(System.Int32 i))
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C) (Syntax: 'c')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_BinaryOperatorInConversion_InvalidMissingOutConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator int(C c)
{
return 0;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperationKind.CompoundAssignment, Type: C, IsInvalid) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 C.op_Implicit(C c))
OutConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0029: Cannot implicitly convert type 'int' to 'C'
// /*<bind>*/c += x/*</bind>*/;
Diagnostic(ErrorCode.ERR_NoImplicitConv, "c += x").WithArguments("int", "C").WithLocation(8, 19)
};
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_BinaryOperatorOutConversion_InvalidMissingInConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator C(int i)
{
return null;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.None) (OperationKind.CompoundAssignment, Type: ?, IsInvalid) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0019: Operator '+=' cannot be applied to operands of type 'C' and 'int'
// /*<bind>*/c += x/*</bind>*/;
Diagnostic(ErrorCode.ERR_BadBinaryOps, "c += x").WithArguments("+=", "C", "int").WithLocation(8, 19)
};
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_UserDefinedBinaryOperator_InConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator C(int i)
{
return null;
}
public static implicit operator int(C c)
{
return 0;
}
public static C operator +(int c1, C c2)
{
return null;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperatorMethod: C C.op_Addition(System.Int32 c1, C c2)) (OperationKind.CompoundAssignment, Type: C) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 C.op_Implicit(C c))
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C) (Syntax: 'c')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: C C.op_Implicit(System.Int32 i)) (OperationKind.Conversion, Type: C, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: C C.op_Implicit(System.Int32 i))
Operand:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_UserDefinedBinaryOperator_OutConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator C(int i)
{
return null;
}
public static implicit operator int(C c)
{
return 0;
}
public static int operator +(C c1, C c2)
{
return 0;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperatorMethod: System.Int32 C.op_Addition(C c1, C c2)) (OperationKind.CompoundAssignment, Type: C) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: C C.op_Implicit(System.Int32 i))
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C) (Syntax: 'c')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: C C.op_Implicit(System.Int32 i)) (OperationKind.Conversion, Type: C, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: C C.op_Implicit(System.Int32 i))
Operand:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_UserDefinedBinaryOperator_InOutConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator C(int i)
{
return null;
}
public static implicit operator int(C c)
{
return 0;
}
public static int operator +(int c1, C c2)
{
return 0;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperatorMethod: System.Int32 C.op_Addition(System.Int32 c1, C c2)) (OperationKind.CompoundAssignment, Type: C) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 C.op_Implicit(C c))
OutConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: C C.op_Implicit(System.Int32 i))
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C) (Syntax: 'c')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: C C.op_Implicit(System.Int32 i)) (OperationKind.Conversion, Type: C, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: C C.op_Implicit(System.Int32 i))
Operand:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_UserDefinedBinaryOperator_InvalidMissingInConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator C(int i)
{
return null;
}
public static int operator +(int c1, C c2)
{
return 0;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.None) (OperationKind.CompoundAssignment, Type: ?, IsInvalid) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0019: Operator '+=' cannot be applied to operands of type 'C' and 'int'
// /*<bind>*/c += x/*</bind>*/;
Diagnostic(ErrorCode.ERR_BadBinaryOps, "c += x").WithArguments("+=", "C", "int").WithLocation(8, 19)
};
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void ICompoundAssignment_UserDefinedBinaryOperator_InvalidMissingOutConversion()
{
string source = @"
class C
{
static void M()
{
var c = new C();
var x = 1;
/*<bind>*/c += x/*</bind>*/;
}
public static implicit operator int(C c)
{
return 0;
}
public static int operator +(int c1, C c2)
{
return 0;
}
}
";
string expectedOperationTree = @"
ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperationKind.CompoundAssignment, Type: C, IsInvalid) (Syntax: 'c += x')
InConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 C.op_Implicit(C c))
OutConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0029: Cannot implicitly convert type 'int' to 'C'
// /*<bind>*/c += x/*</bind>*/;
Diagnostic(ErrorCode.ERR_NoImplicitConv, "c += x").WithArguments("int", "C").WithLocation(8, 19)
};
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
}
}
...@@ -45,6 +45,8 @@ static void Main() ...@@ -45,6 +45,8 @@ static void Main()
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'sum += ids[i];') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'sum += ids[i];')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperationKind.CompoundAssignment, Type: System.Int32) (Syntax: 'sum += ids[i]') ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperationKind.CompoundAssignment, Type: System.Int32) (Syntax: 'sum += ids[i]')
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)
Left: Left:
ILocalReferenceOperation: sum (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'sum') ILocalReferenceOperation: sum (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'sum')
Right: Right:
...@@ -100,6 +102,8 @@ static int SumWhile() ...@@ -100,6 +102,8 @@ static int SumWhile()
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'sum += i;') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'sum += i;')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperationKind.CompoundAssignment, Type: System.Int32) (Syntax: 'sum += i') ICompoundAssignmentOperation (BinaryOperatorKind.Add) (OperationKind.CompoundAssignment, Type: System.Int32) (Syntax: 'sum += i')
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)
Left: Left:
ILocalReferenceOperation: sum (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'sum') ILocalReferenceOperation: sum (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'sum')
Right: Right:
......
...@@ -1127,6 +1127,8 @@ internal abstract partial class BaseCompoundAssignmentExpression : AssignmentExp ...@@ -1127,6 +1127,8 @@ internal abstract partial class BaseCompoundAssignmentExpression : AssignmentExp
/// Operator method used by the operation, null if the operation does not use an operator method. /// Operator method used by the operation, null if the operation does not use an operator method.
/// </summary> /// </summary>
public IMethodSymbol OperatorMethod { get; } public IMethodSymbol OperatorMethod { get; }
public abstract CommonConversion InConversion { get; }
public abstract CommonConversion OutConversion { get; }
public override void Accept(OperationVisitor visitor) public override void Accept(OperationVisitor visitor)
{ {
...@@ -1138,39 +1140,6 @@ public override void Accept(OperationVisitor visitor) ...@@ -1138,39 +1140,6 @@ public override void Accept(OperationVisitor visitor)
} }
} }
/// <summary>
/// Represents an assignment expression that includes a binary operation.
/// </summary>
internal sealed partial class CompoundAssignmentExpression : BaseCompoundAssignmentExpression, ICompoundAssignmentOperation
{
public CompoundAssignmentExpression(BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, IOperation target, IOperation value, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(operatorKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit)
{
TargetImpl = target;
ValueImpl = value;
}
protected override IOperation TargetImpl { get; }
protected override IOperation ValueImpl { get; }
}
/// <summary>
/// Represents an assignment expression that includes a binary operation.
/// </summary>
internal sealed partial class LazyCompoundAssignmentExpression : BaseCompoundAssignmentExpression, ICompoundAssignmentOperation
{
private readonly Lazy<IOperation> _lazyTarget;
private readonly Lazy<IOperation> _lazyValue;
public LazyCompoundAssignmentExpression(BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, Lazy<IOperation> target, Lazy<IOperation> value, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(operatorKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit)
{
_lazyTarget = target ?? throw new System.ArgumentNullException(nameof(target));
_lazyValue = value ?? throw new System.ArgumentNullException(nameof(value));
}
protected override IOperation TargetImpl => _lazyTarget.Value;
protected override IOperation ValueImpl => _lazyValue.Value;
}
/// <summary> /// <summary>
/// Represents an expression that includes a ? or ?. conditional access instance expression. /// Represents an expression that includes a ? or ?. conditional access instance expression.
/// </summary> /// </summary>
......
...@@ -35,5 +35,16 @@ public interface ICompoundAssignmentOperation : IAssignmentOperation ...@@ -35,5 +35,16 @@ public interface ICompoundAssignmentOperation : IAssignmentOperation
/// <code>true</code> if overflow checking is performed for the arithmetic operation. /// <code>true</code> if overflow checking is performed for the arithmetic operation.
/// </summary> /// </summary>
bool IsChecked { get; } bool IsChecked { get; }
/// <summary>
/// Conversion applied to <see cref="IAssignmentOperation.Target"/> before the operation occurs.
/// </summary>
CommonConversion InConversion { get; }
/// <summary>
/// Conversion applied to the result of the binary operation, before it is assigned back to
/// <see cref="IAssignmentOperation.Target"/>.
/// </summary>
CommonConversion OutConversion { get; }
} }
} }
...@@ -385,11 +385,6 @@ public override IOperation VisitDeclarationExpression(IDeclarationExpressionOper ...@@ -385,11 +385,6 @@ public override IOperation VisitDeclarationExpression(IDeclarationExpressionOper
return new DeclarationExpression(Visit(operation.Expression), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); return new DeclarationExpression(Visit(operation.Expression), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
} }
public override IOperation VisitCompoundAssignment(ICompoundAssignmentOperation operation, object argument)
{
return new CompoundAssignmentExpression(operation.OperatorKind, operation.IsLifted, operation.IsChecked, Visit(operation.Target), Visit(operation.Value), operation.OperatorMethod, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
}
public override IOperation VisitIncrementOrDecrement(IIncrementOrDecrementOperation operation, object argument) public override IOperation VisitIncrementOrDecrement(IIncrementOrDecrementOperation operation, object argument)
{ {
bool isDecrement = operation.Kind == OperationKind.Decrement; bool isDecrement = operation.Kind == OperationKind.Decrement;
......
...@@ -32,25 +32,6 @@ public static IExpressionStatementOperation CreateSimpleAssignmentExpressionStat ...@@ -32,25 +32,6 @@ public static IExpressionStatementOperation CreateSimpleAssignmentExpressionStat
return new ExpressionStatement(expression, semanticModel, syntax, type: null, constantValue: default(Optional<object>), isImplicit: isImplicit); return new ExpressionStatement(expression, semanticModel, syntax, type: null, constantValue: default(Optional<object>), isImplicit: isImplicit);
} }
public static IExpressionStatementOperation CreateCompoundAssignmentExpressionStatement(
IOperation target, IOperation value, BinaryOperatorKind operatorKind, bool isLifted, bool isChecked, IMethodSymbol operatorMethod, SemanticModel semanticModel, SyntaxNode syntax, bool isImplicit)
{
var expression = new CompoundAssignmentExpression(
operatorKind,
isLifted,
isChecked,
target,
value,
operatorMethod,
semanticModel,
syntax,
target.Type,
default(Optional<object>),
isImplicit);
return new ExpressionStatement(expression, semanticModel, syntax, type: null, constantValue: default(Optional<object>), isImplicit: isImplicit);
}
public static ILiteralOperation CreateLiteralExpression(long value, ITypeSymbol resultType, SemanticModel semanticModel, SyntaxNode syntax, bool isImplicit) public static ILiteralOperation CreateLiteralExpression(long value, ITypeSymbol resultType, SemanticModel semanticModel, SyntaxNode syntax, bool isImplicit)
{ {
return new LiteralExpression(semanticModel, syntax, resultType, constantValue: new Optional<object>(value), isImplicit: isImplicit); return new LiteralExpression(semanticModel, syntax, resultType, constantValue: new Optional<object>(value), isImplicit: isImplicit);
......
...@@ -245,10 +245,12 @@ Microsoft.CodeAnalysis.Operations.ICollectionElementInitializerOperation.AddMeth ...@@ -245,10 +245,12 @@ Microsoft.CodeAnalysis.Operations.ICollectionElementInitializerOperation.AddMeth
Microsoft.CodeAnalysis.Operations.ICollectionElementInitializerOperation.Arguments.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.IOperation> Microsoft.CodeAnalysis.Operations.ICollectionElementInitializerOperation.Arguments.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.IOperation>
Microsoft.CodeAnalysis.Operations.ICollectionElementInitializerOperation.IsDynamic.get -> bool Microsoft.CodeAnalysis.Operations.ICollectionElementInitializerOperation.IsDynamic.get -> bool
Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation
Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation.InConversion.get -> Microsoft.CodeAnalysis.Operations.CommonConversion
Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation.IsChecked.get -> bool Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation.IsChecked.get -> bool
Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation.IsLifted.get -> bool Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation.IsLifted.get -> bool
Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation.OperatorKind.get -> Microsoft.CodeAnalysis.Operations.BinaryOperatorKind Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation.OperatorKind.get -> Microsoft.CodeAnalysis.Operations.BinaryOperatorKind
Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation.OperatorMethod.get -> Microsoft.CodeAnalysis.IMethodSymbol Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation.OperatorMethod.get -> Microsoft.CodeAnalysis.IMethodSymbol
Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation.OutConversion.get -> Microsoft.CodeAnalysis.Operations.CommonConversion
Microsoft.CodeAnalysis.Operations.IConditionalAccessInstanceOperation Microsoft.CodeAnalysis.Operations.IConditionalAccessInstanceOperation
Microsoft.CodeAnalysis.Operations.IConditionalAccessOperation Microsoft.CodeAnalysis.Operations.IConditionalAccessOperation
Microsoft.CodeAnalysis.Operations.IConditionalAccessOperation.Operation.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Operations.IConditionalAccessOperation.Operation.get -> Microsoft.CodeAnalysis.IOperation
......
...@@ -1997,16 +1997,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1997,16 +1997,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim placeholder As BoundCompoundAssignmentTargetPlaceholder = Nothing Dim placeholder As BoundCompoundAssignmentTargetPlaceholder = Nothing
If Not isError Then If isError Then
placeholder = New BoundCompoundAssignmentTargetPlaceholder(left.Syntax, targetType).MakeCompilerGenerated() ' Suppress all additional diagnostics. This ensures that we still generate the appropriate tree shape
right = BindBinaryOperator(node, placeholder, right, operatorTokenKind, operatorKind, isOperandOfConditionalBranch:=False, diagnostics:=diagnostics) ' even in error scenarios
right.SetWasCompilerGenerated() diagnostics = New DiagnosticBag()
right = ApplyImplicitConversion(node, targetType, right, diagnostics)
Else
' Try to reclassify 'right' if we still can.
right = MakeRValueAndIgnoreDiagnostics(right)
End If End If
placeholder = New BoundCompoundAssignmentTargetPlaceholder(left.Syntax, targetType).MakeCompilerGenerated()
right = BindBinaryOperator(node, placeholder, right, operatorTokenKind, operatorKind, isOperandOfConditionalBranch:=False, diagnostics:=diagnostics)
right.SetWasCompilerGenerated()
right = ApplyImplicitConversion(node, targetType, right, diagnostics)
left = left.SetGetSetAccessKindIfAppropriate() left = left.SetGetSetAccessKindIfAppropriate()
Return New BoundAssignmentOperator(node, left, placeholder, right, False, hasErrors:=isError) Return New BoundAssignmentOperator(node, left, placeholder, right, False, hasErrors:=isError)
......
...@@ -11,6 +11,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -11,6 +11,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Property End Property
End Class End Class
Partial Friend Class BoundAssignmentOperator
Protected Overrides ReadOnly Property Children As ImmutableArray(Of BoundNode)
Get
Return ImmutableArray.Create(Of BoundNode)(Me.Left, Me.Right)
End Get
End Property
End Class
Partial Friend Class BoundDelegateCreationExpression Partial Friend Class BoundDelegateCreationExpression
Protected Overrides ReadOnly Property Children As ImmutableArray(Of BoundNode) Protected Overrides ReadOnly Property Children As ImmutableArray(Of BoundNode)
Get Get
......
' 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 System.Runtime.CompilerServices
Imports Microsoft.CodeAnalysis.Operations
Namespace Microsoft.CodeAnalysis.VisualBasic
Friend MustInherit Class BaseVisualBasicCompoundAssignmentOperation
Inherits BaseCompoundAssignmentExpression
Protected Sub New(inConversion As Conversion, outConversion As Conversion, operatorKind As Operations.BinaryOperatorKind, isLifted As Boolean, isChecked As Boolean, operatorMethod As IMethodSymbol, semanticModel As SemanticModel, syntax As SyntaxNode, type As ITypeSymbol, constantValue As [Optional](Of Object), isImplicit As Boolean)
MyBase.New(operatorKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit)
InConversionInternal = inConversion
OutConversionInternal = outConversion
End Sub
Friend ReadOnly Property InConversionInternal As Conversion
Friend ReadOnly Property OutConversionInternal As Conversion
Public Overrides ReadOnly Property InConversion As CommonConversion
Get
Return InConversionInternal.ToCommonConversion()
End Get
End Property
Public Overrides ReadOnly Property OutConversion As CommonConversion
Get
Return OutConversionInternal.ToCommonConversion()
End Get
End Property
End Class
Friend NotInheritable Class VisualBasicCompoundAssignmentOperation
Inherits BaseVisualBasicCompoundAssignmentOperation
Public Sub New(target As IOperation, value As IOperation, inConversion As Conversion, outConversion As Conversion, operatorKind As Operations.BinaryOperatorKind, isLifted As Boolean, isChecked As Boolean, operatorMethod As IMethodSymbol, semanticModel As SemanticModel, syntax As SyntaxNode, type As ITypeSymbol, constantValue As [Optional](Of Object), isImplicit As Boolean)
MyBase.New(inConversion, outConversion, operatorKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit)
TargetImpl = target
ValueImpl = value
End Sub
Protected Overrides ReadOnly Property TargetImpl As IOperation
Protected Overrides ReadOnly Property ValueImpl As IOperation
End Class
Friend NotInheritable Class LazyVisualBasicCompoundAssignmentOperation
Inherits BaseVisualBasicCompoundAssignmentOperation
Private ReadOnly _lazyTarget As Lazy(Of IOperation)
Private ReadOnly _lazyValue As Lazy(Of IOperation)
Public Sub New(target As Lazy(Of IOperation), value As Lazy(Of IOperation), inConversion As Conversion, outConversion As Conversion, operatorKind As Operations.BinaryOperatorKind, isLifted As Boolean, isChecked As Boolean, operatorMethod As IMethodSymbol, semanticModel As SemanticModel, syntax As SyntaxNode, type As ITypeSymbol, constantValue As [Optional](Of Object), isImplicit As Boolean)
MyBase.New(inConversion, outConversion, operatorKind, isLifted, isChecked, operatorMethod, semanticModel, syntax, type, constantValue, isImplicit)
_lazyTarget = target
_lazyValue = value
End Sub
Protected Overrides ReadOnly Property TargetImpl As IOperation
Get
Return _lazyTarget.Value
End Get
End Property
Protected Overrides ReadOnly Property ValueImpl As IOperation
Get
Return _lazyValue.Value
End Get
End Property
End Class
End Namespace
...@@ -14,5 +14,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -14,5 +14,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Public Overrides Function VisitConversion(operation As IConversionOperation, argument As Object) As IOperation Public Overrides Function VisitConversion(operation As IConversionOperation, argument As Object) As IOperation
Return New VisualBasicConversionExpression(Visit(operation.Operand), operation.GetConversion(), operation.IsTryCast, operation.IsChecked, DirectCast(operation, Operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit) Return New VisualBasicConversionExpression(Visit(operation.Operand), operation.GetConversion(), operation.IsTryCast, operation.IsChecked, DirectCast(operation, Operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit)
End Function End Function
Public Overrides Function VisitCompoundAssignment(operation As ICompoundAssignmentOperation, argument As Object) As IOperation
Dim baseType = DirectCast(operation, BaseVisualBasicCompoundAssignmentOperation)
Return New VisualBasicCompoundAssignmentOperation(Visit(operation.Target), Visit(operation.Value), baseType.InConversionInternal, baseType.OutConversionInternal, operation.OperatorKind, operation.IsLifted, operation.IsChecked, operation.OperatorMethod, DirectCast(operation, Operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit)
End Function
End Class End Class
End Namespace End Namespace
...@@ -272,28 +272,15 @@ Namespace Microsoft.CodeAnalysis.Operations ...@@ -272,28 +272,15 @@ Namespace Microsoft.CodeAnalysis.Operations
End Function End Function
Private Function CreateBoundAssignmentOperatorOperation(boundAssignmentOperator As BoundAssignmentOperator) As IOperation Private Function CreateBoundAssignmentOperatorOperation(boundAssignmentOperator As BoundAssignmentOperator) As IOperation
Dim kind = GetAssignmentKind(boundAssignmentOperator) If boundAssignmentOperator.Syntax.IsKind(SyntaxKind.MidAssignmentStatement) Then
Dim isImplicit As Boolean = boundAssignmentOperator.WasCompilerGenerated ' We don't support mid statements currently. Return a none operation for them
If kind = OperationKind.CompoundAssignment Then Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundAssignmentOperator?.ConstantValueOpt)
' convert Right to IOperation temporarily. we do this to get right operand, operator method and etc Dim isImplicit As Boolean = boundAssignmentOperator.WasCompilerGenerated
Dim temporaryRight = DirectCast(Create(boundAssignmentOperator.Right), IBinaryOperation) Return Operation.CreateOperationNone(_semanticModel, boundAssignmentOperator.Syntax, constantValue, Function() GetIOperationChildren(boundAssignmentOperator), isImplicit)
ElseIf boundAssignmentOperator.LeftOnTheRightOpt IsNot Nothing Then
Dim operatorKind As BinaryOperatorKind = temporaryRight.OperatorKind Return CreateCompoundAssignment(boundAssignmentOperator)
Dim target As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundAssignmentOperator.Left))
' right now, parent of right operand is set to the temporary IOperation, reset the parent
' we basically need to do this since we skip BoundAssignmentOperator.Right from IOperation tree
Dim rightOperand = Operation.ResetParentOperation(temporaryRight.RightOperand)
Dim value As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() rightOperand)
Dim operatorMethod As IMethodSymbol = temporaryRight.OperatorMethod
Dim syntax As SyntaxNode = boundAssignmentOperator.Syntax
Dim type As ITypeSymbol = boundAssignmentOperator.Type
Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundAssignmentOperator.ConstantValueOpt)
Dim isLifted As Boolean = boundAssignmentOperator.Type.IsNullableType()
Dim isChecked As Boolean = temporaryRight.IsChecked
Return New LazyCompoundAssignmentExpression(operatorKind, isLifted, isChecked, target, value, operatorMethod, _semanticModel, syntax, type, constantValue, isImplicit)
Else Else
Dim isImplicit As Boolean = boundAssignmentOperator.WasCompilerGenerated
Dim target As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundAssignmentOperator.Left)) Dim target As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundAssignmentOperator.Left))
Dim value As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundAssignmentOperator.Right)) Dim value As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundAssignmentOperator.Right))
Dim isRef As Boolean = False Dim isRef As Boolean = False
...@@ -447,33 +434,31 @@ Namespace Microsoft.CodeAnalysis.Operations ...@@ -447,33 +434,31 @@ Namespace Microsoft.CodeAnalysis.Operations
End Function End Function
Private Function CreateBoundBinaryOperatorOperation(boundBinaryOperator As BoundBinaryOperator) As IBinaryOperation Private Function CreateBoundBinaryOperatorOperation(boundBinaryOperator As BoundBinaryOperator) As IBinaryOperation
Dim operatorKind As BinaryOperatorKind = Helper.DeriveBinaryOperatorKind(boundBinaryOperator.OperatorKind, boundBinaryOperator.Left) Dim binaryOperatorInfo = GetBinaryOperatorInfo(boundBinaryOperator)
Dim leftOperand As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundBinaryOperator.Left)) Dim leftOperand As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(binaryOperatorInfo.LeftOperand))
Dim rightOperand As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundBinaryOperator.Right)) Dim rightOperand As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(binaryOperatorInfo.RightOperand))
Dim operatorMethod As IMethodSymbol = Nothing
Dim syntax As SyntaxNode = boundBinaryOperator.Syntax Dim syntax As SyntaxNode = boundBinaryOperator.Syntax
Dim type As ITypeSymbol = boundBinaryOperator.Type Dim type As ITypeSymbol = boundBinaryOperator.Type
Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundBinaryOperator.ConstantValueOpt) Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundBinaryOperator.ConstantValueOpt)
Dim isLifted As Boolean = (boundBinaryOperator.OperatorKind And VisualBasic.BinaryOperatorKind.Lifted) <> 0
Dim isChecked As Boolean = boundBinaryOperator.Checked
Dim isCompareText As Boolean = (boundBinaryOperator.OperatorKind And VisualBasic.BinaryOperatorKind.CompareText) <> 0
Dim isImplicit As Boolean = boundBinaryOperator.WasCompilerGenerated Dim isImplicit As Boolean = boundBinaryOperator.WasCompilerGenerated
Return New LazyBinaryOperatorExpression(operatorKind, leftOperand, rightOperand, isLifted, isChecked, isCompareText, operatorMethod, _semanticModel, syntax, type, constantValue, isImplicit) Return New LazyBinaryOperatorExpression(binaryOperatorInfo.OperatorKind, leftOperand, rightOperand, binaryOperatorInfo.IsLifted,
binaryOperatorInfo.IsChecked, binaryOperatorInfo.IsCompareText, binaryOperatorInfo.OperatorMethod,
_semanticModel, syntax, type, constantValue, isImplicit)
End Function End Function
Private Function CreateBoundUserDefinedBinaryOperatorOperation(boundUserDefinedBinaryOperator As BoundUserDefinedBinaryOperator) As IBinaryOperation Private Function CreateBoundUserDefinedBinaryOperatorOperation(boundUserDefinedBinaryOperator As BoundUserDefinedBinaryOperator) As IBinaryOperation
Dim operatorKind As BinaryOperatorKind = Helper.DeriveBinaryOperatorKind(boundUserDefinedBinaryOperator.OperatorKind, leftOpt:=Nothing) Dim binaryOperatorInfo = GetUserDefinedBinaryOperatorInfo(boundUserDefinedBinaryOperator)
Dim leftOperand As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() GetUserDefinedBinaryOperatorChild(boundUserDefinedBinaryOperator, 0)) Dim leftOperand As Lazy(Of IOperation) =
Dim rightOperand As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() GetUserDefinedBinaryOperatorChild(boundUserDefinedBinaryOperator, 1)) New Lazy(Of IOperation)(Function() GetUserDefinedBinaryOperatorChild(boundUserDefinedBinaryOperator, binaryOperatorInfo.LeftOperand))
Dim operatorMethod As IMethodSymbol = If(boundUserDefinedBinaryOperator.UnderlyingExpression.Kind = BoundKind.Call, boundUserDefinedBinaryOperator.Call.Method, Nothing) Dim rightOperand As Lazy(Of IOperation) =
New Lazy(Of IOperation)(Function() GetUserDefinedBinaryOperatorChild(boundUserDefinedBinaryOperator, binaryOperatorInfo.RightOperand))
Dim syntax As SyntaxNode = boundUserDefinedBinaryOperator.Syntax Dim syntax As SyntaxNode = boundUserDefinedBinaryOperator.Syntax
Dim type As ITypeSymbol = boundUserDefinedBinaryOperator.Type Dim type As ITypeSymbol = boundUserDefinedBinaryOperator.Type
Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundUserDefinedBinaryOperator.ConstantValueOpt) Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundUserDefinedBinaryOperator.ConstantValueOpt)
Dim isLifted As Boolean = (boundUserDefinedBinaryOperator.OperatorKind And VisualBasic.BinaryOperatorKind.Lifted) <> 0
Dim isChecked As Boolean = boundUserDefinedBinaryOperator.Checked
Dim isCompareText As Boolean = False
Dim isImplicit As Boolean = boundUserDefinedBinaryOperator.WasCompilerGenerated Dim isImplicit As Boolean = boundUserDefinedBinaryOperator.WasCompilerGenerated
Return New LazyBinaryOperatorExpression(operatorKind, leftOperand, rightOperand, isLifted, isChecked, isCompareText, operatorMethod, _semanticModel, syntax, type, constantValue, isImplicit) Return New LazyBinaryOperatorExpression(binaryOperatorInfo.OperatorKind, leftOperand, rightOperand, binaryOperatorInfo.IsLifted,
binaryOperatorInfo.IsChecked, binaryOperatorInfo.IsCompareText, binaryOperatorInfo.OperatorMethod,
_semanticModel, syntax, type, constantValue, isImplicit)
End Function End Function
Private Function CreateBoundBinaryConditionalExpressionOperation(boundBinaryConditionalExpression As BoundBinaryConditionalExpression) As ICoalesceOperation Private Function CreateBoundBinaryConditionalExpressionOperation(boundBinaryConditionalExpression As BoundBinaryConditionalExpression) As ICoalesceOperation
...@@ -530,7 +515,7 @@ Namespace Microsoft.CodeAnalysis.Operations ...@@ -530,7 +515,7 @@ Namespace Microsoft.CodeAnalysis.Operations
Return New LazyDelegateCreationExpression(operand, _semanticModel, syntax, type, constantValue, isImplicit) Return New LazyDelegateCreationExpression(operand, _semanticModel, syntax, type, constantValue, isImplicit)
End If End If
Dim conversion As Conversion = New Conversion(New KeyValuePair(Of ConversionKind, MethodSymbol)(boundTryCast.ConversionKind, Nothing)) Dim conversion As Conversion = CreateConversion(boundTryCast)
Dim isTryCast As Boolean = True Dim isTryCast As Boolean = True
Dim isChecked As Boolean = False Dim isChecked As Boolean = False
Return New LazyVisualBasicConversionExpression(operand, conversion, isTryCast, isChecked, _semanticModel, syntax, type, constantValue, isImplicit) Return New LazyVisualBasicConversionExpression(operand, conversion, isTryCast, isChecked, _semanticModel, syntax, type, constantValue, isImplicit)
...@@ -552,7 +537,7 @@ Namespace Microsoft.CodeAnalysis.Operations ...@@ -552,7 +537,7 @@ Namespace Microsoft.CodeAnalysis.Operations
Return New LazyDelegateCreationExpression(operand, _semanticModel, syntax, type, constantValue, isImplicit) Return New LazyDelegateCreationExpression(operand, _semanticModel, syntax, type, constantValue, isImplicit)
End If End If
Dim conversion As Conversion = New Conversion(New KeyValuePair(Of ConversionKind, MethodSymbol)(boundDirectCast.ConversionKind, Nothing)) Dim conversion As Conversion = CreateConversion(boundDirectCast)
Dim isTryCast As Boolean = False Dim isTryCast As Boolean = False
Dim isChecked As Boolean = False Dim isChecked As Boolean = False
Return New LazyVisualBasicConversionExpression(operand, conversion, isTryCast, isChecked, _semanticModel, syntax, type, constantValue, isImplicit) Return New LazyVisualBasicConversionExpression(operand, conversion, isTryCast, isChecked, _semanticModel, syntax, type, constantValue, isImplicit)
...@@ -578,8 +563,9 @@ Namespace Microsoft.CodeAnalysis.Operations ...@@ -578,8 +563,9 @@ Namespace Microsoft.CodeAnalysis.Operations
Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundConversion.ConstantValueOpt) Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundConversion.ConstantValueOpt)
Dim isImplicit As Boolean = boundConversion.WasCompilerGenerated OrElse Not boundConversion.ExplicitCastInCode Dim isImplicit As Boolean = boundConversion.WasCompilerGenerated OrElse Not boundConversion.ExplicitCastInCode
Dim conversionInformation = CreateConversionOperand(boundConversion.Operand, boundConversion.ConversionKind, boundConversion.Syntax, boundConversion.Type) Dim conversionOperandAndMethod = GetConversionInfo(boundConversion)
Dim methodSymbol As MethodSymbol = conversionInformation.MethodSymbol Dim conversionInformation = CreateConversionOperand(conversionOperandAndMethod.Operand, boundConversion.ConversionKind, boundConversion.Syntax, boundConversion.Type)
Dim methodSymbol As MethodSymbol = conversionOperandAndMethod.Method
Dim operand As Lazy(Of IOperation) = conversionInformation.Operation Dim operand As Lazy(Of IOperation) = conversionInformation.Operation
Dim isDelegateCreation As Boolean = conversionInformation.IsDelegateCreation Dim isDelegateCreation As Boolean = conversionInformation.IsDelegateCreation
...@@ -589,7 +575,7 @@ Namespace Microsoft.CodeAnalysis.Operations ...@@ -589,7 +575,7 @@ Namespace Microsoft.CodeAnalysis.Operations
Return New LazyDelegateCreationExpression(operand, _semanticModel, syntax, type, constantValue, isImplicit) Return New LazyDelegateCreationExpression(operand, _semanticModel, syntax, type, constantValue, isImplicit)
End If End If
Dim conversion = New Conversion(New KeyValuePair(Of VisualBasic.ConversionKind, MethodSymbol)(boundConversion.ConversionKind, methodSymbol)) Dim conversion As Conversion = CreateConversion(boundConversion)
Dim isTryCast As Boolean = False Dim isTryCast As Boolean = False
Dim isChecked As Boolean = False Dim isChecked As Boolean = False
Return New LazyVisualBasicConversionExpression(operand, conversion, isTryCast, isChecked, _semanticModel, syntax, type, constantValue, isImplicit) Return New LazyVisualBasicConversionExpression(operand, conversion, isTryCast, isChecked, _semanticModel, syntax, type, constantValue, isImplicit)
......
...@@ -12,40 +12,115 @@ Namespace Microsoft.CodeAnalysis.Operations ...@@ -12,40 +12,115 @@ Namespace Microsoft.CodeAnalysis.Operations
Return If(value Is Nothing OrElse value.IsBad, New [Optional](Of Object)(), New [Optional](Of Object)(value.Value)) Return If(value Is Nothing OrElse value.IsBad, New [Optional](Of Object)(), New [Optional](Of Object)(value.Value))
End Function End Function
Private Shared Function GetAssignmentKind(value As BoundAssignmentOperator) As OperationKind Private Function CreateCompoundAssignment(boundAssignment As BoundAssignmentOperator) As ICompoundAssignmentOperation
If value.LeftOnTheRightOpt IsNot Nothing Then Debug.Assert(boundAssignment.LeftOnTheRightOpt IsNot Nothing)
Select Case value.Right.Kind Dim binaryOperator As BoundExpression = Nothing
Case BoundKind.BinaryOperator Dim inConversion = New Conversion(Conversions.Identity)
Dim rightBinary As BoundBinaryOperator = DirectCast(value.Right, BoundBinaryOperator) Dim outConversion As Conversion = inConversion
If rightBinary.Left Is value.LeftOnTheRightOpt Then Select Case boundAssignment.Right.Kind
Return OperationKind.CompoundAssignment Case BoundKind.Conversion
End If Dim inConversionNode = DirectCast(boundAssignment.Right, BoundConversion)
Case BoundKind.UserDefinedBinaryOperator Dim conversionInfo = GetConversionInfo(inConversionNode)
Dim rightOperatorBinary As BoundUserDefinedBinaryOperator = DirectCast(value.Right, BoundUserDefinedBinaryOperator) binaryOperator = conversionInfo.Operand
outConversion = CreateConversion(inConversionNode)
' It is not permissible to access the Left property of a BoundUserDefinedBinaryOperator unconditionally, Case BoundKind.UserDefinedBinaryOperator, BoundKind.BinaryOperator
' because that property can throw an exception if the operator expression is semantically invalid. binaryOperator = boundAssignment.Right
' get it through helper method Case Else
Dim leftOperand = GetUserDefinedBinaryOperatorChildBoundNode(rightOperatorBinary, 0) Throw ExceptionUtilities.UnexpectedValue(boundAssignment)
If leftOperand Is value.LeftOnTheRightOpt Then End Select
Return OperationKind.CompoundAssignment
End If Dim operatorInfo As BinaryOperatorInfo
End Select Dim rightOperand As Lazy(Of IOperation)
Select Case binaryOperator.Kind
Case BoundKind.BinaryOperator
operatorInfo = GetBinaryOperatorInfo(DirectCast(binaryOperator, BoundBinaryOperator))
rightOperand = New Lazy(Of IOperation)(Function() Create(operatorInfo.RightOperand))
Case BoundKind.UserDefinedBinaryOperator
Dim userDefinedOperator = DirectCast(binaryOperator, BoundUserDefinedBinaryOperator)
operatorInfo = GetUserDefinedBinaryOperatorInfo(userDefinedOperator)
rightOperand = New Lazy(Of IOperation)(Function() GetUserDefinedBinaryOperatorChild(userDefinedOperator, operatorInfo.RightOperand))
Case Else
Throw ExceptionUtilities.UnexpectedValue(boundAssignment)
End Select
Dim leftOnTheRight As BoundExpression = operatorInfo.LeftOperand
If leftOnTheRight.Kind = BoundKind.Conversion Then
Dim outConversionNode = DirectCast(leftOnTheRight, BoundConversion)
Dim conversionInfo = GetConversionInfo(outConversionNode)
inConversion = CreateConversion(outConversionNode)
leftOnTheRight = conversionInfo.Operand
End If End If
Return OperationKind.SimpleAssignment Debug.Assert(leftOnTheRight Is boundAssignment.LeftOnTheRightOpt)
Dim leftOperand As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundAssignment.Left))
Dim syntax As SyntaxNode = boundAssignment.Syntax
Dim type As ITypeSymbol = boundAssignment.Type
Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundAssignment.ConstantValueOpt)
Dim isImplicit As Boolean = boundAssignment.WasCompilerGenerated
Return New LazyVisualBasicCompoundAssignmentOperation(leftOperand, rightOperand, inConversion, outConversion, operatorInfo.OperatorKind,
operatorInfo.IsLifted, operatorInfo.IsChecked, operatorInfo.OperatorMethod,
_semanticModel, syntax, type, constantValue, isImplicit)
End Function
Private Structure BinaryOperatorInfo
Public Sub New(leftOperand As BoundExpression,
rightOperand As BoundExpression,
binaryOperatorKind As BinaryOperatorKind,
operatorMethod As MethodSymbol,
isLifted As Boolean,
isChecked As Boolean,
isCompareText As Boolean)
Me.LeftOperand = leftOperand
Me.RightOperand = rightOperand
Me.OperatorKind = binaryOperatorKind
Me.OperatorMethod = operatorMethod
Me.IsLifted = isLifted
Me.IsChecked = isChecked
Me.IsCompareText = isCompareText
End Sub
Public ReadOnly LeftOperand As BoundExpression
Public ReadOnly RightOperand As BoundExpression
Public ReadOnly OperatorKind As BinaryOperatorKind
Public ReadOnly OperatorMethod As MethodSymbol
Public ReadOnly IsLifted As Boolean
Public ReadOnly IsChecked As Boolean
Public ReadOnly IsCompareText As Boolean
End Structure
Private Shared Function GetBinaryOperatorInfo(boundBinaryOperator As BoundBinaryOperator) As BinaryOperatorInfo
Return New BinaryOperatorInfo(
leftOperand:=boundBinaryOperator.Left,
rightOperand:=boundBinaryOperator.Right,
binaryOperatorKind:=Helper.DeriveBinaryOperatorKind(boundBinaryOperator.OperatorKind, boundBinaryOperator.Left),
operatorMethod:=Nothing,
isLifted:=(boundBinaryOperator.OperatorKind And VisualBasic.BinaryOperatorKind.Lifted) <> 0,
isChecked:=boundBinaryOperator.Checked,
isCompareText:=(boundBinaryOperator.OperatorKind And VisualBasic.BinaryOperatorKind.CompareText) <> 0)
End Function
Private Shared Function GetUserDefinedBinaryOperatorInfo(boundUserDefinedBinaryOperator As BoundUserDefinedBinaryOperator) As BinaryOperatorInfo
Return New BinaryOperatorInfo(
leftOperand:=GetUserDefinedBinaryOperatorChildBoundNode(boundUserDefinedBinaryOperator, 0),
rightOperand:=GetUserDefinedBinaryOperatorChildBoundNode(boundUserDefinedBinaryOperator, 1),
binaryOperatorKind:=Helper.DeriveBinaryOperatorKind(boundUserDefinedBinaryOperator.OperatorKind, leftOpt:=Nothing),
operatorMethod:=If(boundUserDefinedBinaryOperator.UnderlyingExpression.Kind = BoundKind.Call, boundUserDefinedBinaryOperator.Call.Method, Nothing),
isLifted:=(boundUserDefinedBinaryOperator.OperatorKind And VisualBasic.BinaryOperatorKind.Lifted) <> 0,
isChecked:=boundUserDefinedBinaryOperator.Checked,
isCompareText:=False)
End Function End Function
Private Function GetUserDefinedBinaryOperatorChild([operator] As BoundUserDefinedBinaryOperator, index As Integer) As IOperation Private Function GetUserDefinedBinaryOperatorChild([operator] As BoundUserDefinedBinaryOperator, child As BoundExpression) As IOperation
Dim child = Create(GetUserDefinedBinaryOperatorChildBoundNode([operator], index))
If child IsNot Nothing Then If child IsNot Nothing Then
Return child Return Create(child)
End If End If
Dim isImplicit As Boolean = [operator].WasCompilerGenerated Dim isImplicit As Boolean = [operator].UnderlyingExpression.WasCompilerGenerated
Return OperationFactory.CreateInvalidExpression(_semanticModel, [operator].UnderlyingExpression.Syntax, ImmutableArray(Of IOperation).Empty, isImplicit) Return OperationFactory.CreateInvalidExpression(_semanticModel, [operator].UnderlyingExpression.Syntax, ImmutableArray(Of IOperation).Empty, isImplicit)
End Function End Function
Private Shared Function GetUserDefinedBinaryOperatorChildBoundNode([operator] As BoundUserDefinedBinaryOperator, index As Integer) As BoundNode Private Shared Function GetUserDefinedBinaryOperatorChildBoundNode([operator] As BoundUserDefinedBinaryOperator, index As Integer) As BoundExpression
If [operator].UnderlyingExpression.Kind = BoundKind.Call Then If [operator].UnderlyingExpression.Kind = BoundKind.Call Then
If index = 0 Then If index = 0 Then
Return [operator].Left Return [operator].Left
...@@ -80,6 +155,10 @@ Namespace Microsoft.CodeAnalysis.Operations ...@@ -80,6 +155,10 @@ Namespace Microsoft.CodeAnalysis.Operations
method = DirectCast(conversion.Operand, BoundUserDefinedConversion).Call.Method method = DirectCast(conversion.Operand, BoundUserDefinedConversion).Call.Method
End If End If
Return New Conversion(KeyValuePair.Create(conversionKind, method)) Return New Conversion(KeyValuePair.Create(conversionKind, method))
ElseIf expression.Kind = BoundKind.TryCast Then
Return New Conversion(KeyValuePair.Create(Of ConversionKind, MethodSymbol)(DirectCast(expression, BoundTryCast).ConversionKind, Nothing))
ElseIf expression.Kind = BoundKind.DirectCast Then
Return New Conversion(KeyValuePair.Create(Of ConversionKind, MethodSymbol)(DirectCast(expression, BoundDirectCast).ConversionKind, Nothing))
End If End If
Return New Conversion(Conversions.Identity) Return New Conversion(Conversions.Identity)
End Function End Function
...@@ -192,13 +271,10 @@ Namespace Microsoft.CodeAnalysis.Operations ...@@ -192,13 +271,10 @@ Namespace Microsoft.CodeAnalysis.Operations
Return OperationFactory.CreateInvalidExpression(_semanticModel, parent.Syntax, ImmutableArray(Of IOperation).Empty, isImplicit) Return OperationFactory.CreateInvalidExpression(_semanticModel, parent.Syntax, ImmutableArray(Of IOperation).Empty, isImplicit)
End Function End Function
Private Shared Function GetChildOfBadExpressionBoundNode(parent As BoundNode, index As Integer) As BoundNode Private Shared Function GetChildOfBadExpressionBoundNode(parent As BoundNode, index As Integer) As BoundExpression
Dim badParent As BoundBadExpression = TryCast(parent, BoundBadExpression) Dim badParent As BoundBadExpression = TryCast(parent, BoundBadExpression)
If badParent?.ChildBoundNodes.Length > index Then If badParent?.ChildBoundNodes.Length > index Then
Dim child As BoundNode = badParent.ChildBoundNodes(index) Return badParent.ChildBoundNodes(index)
If child IsNot Nothing Then
Return child
End If
End If End If
Return Nothing Return Nothing
...@@ -394,12 +470,8 @@ Namespace Microsoft.CodeAnalysis.Operations ...@@ -394,12 +470,8 @@ Namespace Microsoft.CodeAnalysis.Operations
''' is actually a delegate creation. ''' is actually a delegate creation.
''' </summary> ''' </summary>
Private Function CreateConversionOperand(operand As BoundNode, conversionKind As ConversionKind, conversionSyntax As SyntaxNode, targetType As TypeSymbol Private Function CreateConversionOperand(operand As BoundNode, conversionKind As ConversionKind, conversionSyntax As SyntaxNode, targetType As TypeSymbol
) As (MethodSymbol As MethodSymbol, Operation As Lazy(Of IOperation), IsDelegateCreation As Boolean) ) As (Operation As Lazy(Of IOperation), IsDelegateCreation As Boolean)
If (conversionKind And VisualBasic.ConversionKind.UserDefined) = VisualBasic.ConversionKind.UserDefined Then If IsDelegateCreation(conversionKind, conversionSyntax, operand, targetType) Then
Dim userDefinedConversion As BoundUserDefinedConversion = DirectCast(operand, BoundUserDefinedConversion)
Return (userDefinedConversion.Call.Method, New Lazy(Of IOperation)(Function() Create(userDefinedConversion.Operand)), IsDelegateCreation:=False)
ElseIf IsDelegateCreation(conversionKind, conversionSyntax, operand, targetType) Then
Dim methodSymbol As MethodSymbol = Nothing
Dim operandLazy As Lazy(Of IOperation) Dim operandLazy As Lazy(Of IOperation)
If operand.Kind = BoundKind.DelegateCreationExpression Then If operand.Kind = BoundKind.DelegateCreationExpression Then
' If the child is a BoundDelegateCreationExpression, we don't want to generate a nested IDelegateCreationExpression. ' If the child is a BoundDelegateCreationExpression, we don't want to generate a nested IDelegateCreationExpression.
...@@ -413,10 +485,22 @@ Namespace Microsoft.CodeAnalysis.Operations ...@@ -413,10 +485,22 @@ Namespace Microsoft.CodeAnalysis.Operations
' Delegate to standard operation handling for this. ' Delegate to standard operation handling for this.
operandLazy = New Lazy(Of IOperation)(Function() Create(operand)) operandLazy = New Lazy(Of IOperation)(Function() Create(operand))
End If End If
Return (methodSymbol, operandLazy, IsDelegateCreation:=True) Return (operandLazy, IsDelegateCreation:=True)
Else Else
Dim methodSymbol As MethodSymbol = Nothing Dim methodSymbol As MethodSymbol = Nothing
Return (methodSymbol, New Lazy(Of IOperation)(Function() Create(operand)), IsDelegateCreation:=False) Return (New Lazy(Of IOperation)(Function() Create(operand)), IsDelegateCreation:=False)
End If
End Function
''' <summary>
''' Gets the operand and method symbol from a BoundConversion, compensating for if the conversion is a user-defined conversion
''' </summary>
Private Shared Function GetConversionInfo(boundConversion As BoundConversion) As (Operand As BoundExpression, Method As MethodSymbol)
If (boundConversion.ConversionKind And ConversionKind.UserDefined) = ConversionKind.UserDefined Then
Dim userDefinedConversion = DirectCast(boundConversion.Operand, BoundUserDefinedConversion)
Return (Operand:=userDefinedConversion.Operand, Method:=userDefinedConversion.Call.Method)
Else
Return (Operand:=boundConversion.Operand, Method:=Nothing)
End If End If
End Function End Function
......
...@@ -2,4 +2,6 @@ Microsoft.CodeAnalysis.VisualBasic.Conversion.ToCommonConversion() -> Microsoft. ...@@ -2,4 +2,6 @@ Microsoft.CodeAnalysis.VisualBasic.Conversion.ToCommonConversion() -> Microsoft.
Microsoft.CodeAnalysis.VisualBasic.LanguageVersion.VisualBasic15_5 = 1505 -> Microsoft.CodeAnalysis.VisualBasic.LanguageVersion Microsoft.CodeAnalysis.VisualBasic.LanguageVersion.VisualBasic15_5 = 1505 -> Microsoft.CodeAnalysis.VisualBasic.LanguageVersion
Microsoft.CodeAnalysis.VisualBasic.VisualBasicExtensions.GetConversion(conversionExpression As Microsoft.CodeAnalysis.Operations.IConversionOperation) -> Microsoft.CodeAnalysis.VisualBasic.Conversion Microsoft.CodeAnalysis.VisualBasic.VisualBasicExtensions.GetConversion(conversionExpression As Microsoft.CodeAnalysis.Operations.IConversionOperation) -> Microsoft.CodeAnalysis.VisualBasic.Conversion
Microsoft.CodeAnalysis.VisualBasic.VisualBasicExtensions.GetInConversion(argument As Microsoft.CodeAnalysis.Operations.IArgumentOperation) -> Microsoft.CodeAnalysis.VisualBasic.Conversion Microsoft.CodeAnalysis.VisualBasic.VisualBasicExtensions.GetInConversion(argument As Microsoft.CodeAnalysis.Operations.IArgumentOperation) -> Microsoft.CodeAnalysis.VisualBasic.Conversion
Microsoft.CodeAnalysis.VisualBasic.VisualBasicExtensions.GetInConversion(compoundAssignment As Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation) -> Microsoft.CodeAnalysis.VisualBasic.Conversion
Microsoft.CodeAnalysis.VisualBasic.VisualBasicExtensions.GetOutConversion(argument As Microsoft.CodeAnalysis.Operations.IArgumentOperation) -> Microsoft.CodeAnalysis.VisualBasic.Conversion Microsoft.CodeAnalysis.VisualBasic.VisualBasicExtensions.GetOutConversion(argument As Microsoft.CodeAnalysis.Operations.IArgumentOperation) -> Microsoft.CodeAnalysis.VisualBasic.Conversion
Microsoft.CodeAnalysis.VisualBasic.VisualBasicExtensions.GetOutConversion(compoundAssignment As Microsoft.CodeAnalysis.Operations.ICompoundAssignmentOperation) -> Microsoft.CodeAnalysis.VisualBasic.Conversion
...@@ -12288,6 +12288,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -12288,6 +12288,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get End Get
End Property End Property
'''<summary>
''' Looks up a localized string similar to {0} is not a valid Visual Basic compound assignment operation.
'''</summary>
Friend ReadOnly Property ICompoundAssignmentOperationIsNotVisualBasicCompoundAssignment() As String
Get
Return ResourceManager.GetString("ICompoundAssignmentOperationIsNotVisualBasicCompoundAssignment", resourceCulture)
End Get
End Property
'''<summary> '''<summary>
''' Looks up a localized string similar to {0} is not a valid Visual Basic conversion expression. ''' Looks up a localized string similar to {0} is not a valid Visual Basic conversion expression.
'''</summary> '''</summary>
......
...@@ -5521,4 +5521,7 @@ ...@@ -5521,4 +5521,7 @@
<data name="FEATURE_LeadingDigitSeparator" xml:space="preserve"> <data name="FEATURE_LeadingDigitSeparator" xml:space="preserve">
<value>leading digit separator</value> <value>leading digit separator</value>
</data> </data>
</root> <data name="ICompoundAssignmentOperationIsNotVisualBasicCompoundAssignment" xml:space="preserve">
<value>{0} is not a valid Visual Basic compound assignment operation</value>
</data>
</root>
\ No newline at end of file
...@@ -1415,6 +1415,52 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1415,6 +1415,52 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End If End If
End Function End Function
''' <summary>
''' Gets the underlying <see cref="Conversion"/> information from this <see cref="ICompoundAssignmentOperation"/>. This
''' conversion is applied before the operator is applied to the result of this conversion and <see cref="IAssignmentOperation.Value"/>.
''' </summary>
''' <remarks>
''' This compound assignment must have been created from Visual Basic code.
''' </remarks>
<Extension>
Public Function GetInConversion(compoundAssignment As ICompoundAssignmentOperation) As Conversion
If compoundAssignment Is Nothing Then
Throw New ArgumentNullException(NameOf(compoundAssignment))
End If
Dim basicCompoundOperation = TryCast(compoundAssignment, BaseVisualBasicCompoundAssignmentOperation)
If basicCompoundOperation IsNot Nothing Then
Return basicCompoundOperation.InConversionInternal
Else
Throw New ArgumentException(String.Format(VBResources.ICompoundAssignmentOperationIsNotVisualBasicCompoundAssignment,
NameOf(compoundAssignment)),
NameOf(compoundAssignment))
End If
End Function
''' <summary>
''' Gets the underlying <see cref="Conversion"/> information from this <see cref="ICompoundAssignmentOperation"/>. This
''' conversion is applied after the operator is applied, before the result is assigned to <see cref="IAssignmentOperation.Target"/>.
''' </summary>
''' <remarks>
''' This compound assignment must have been created from Visual Basic code.
''' </remarks>
<Extension>
Public Function GetOutConversion(compoundAssignment As ICompoundAssignmentOperation) As Conversion
If compoundAssignment Is Nothing Then
Throw New ArgumentNullException(NameOf(compoundAssignment))
End If
Dim basicCompoundOperation = TryCast(compoundAssignment, BaseVisualBasicCompoundAssignmentOperation)
If basicCompoundOperation IsNot Nothing Then
Return basicCompoundOperation.OutConversionInternal
Else
Throw New ArgumentException(String.Format(VBResources.ICompoundAssignmentOperationIsNotVisualBasicCompoundAssignment,
NameOf(compoundAssignment)),
NameOf(compoundAssignment))
End If
End Function
<Extension> <Extension>
Public Function GetSpeculativeConversion(semanticModel As SemanticModel, position As Integer, expression As ExpressionSyntax, bindingOption As SpeculativeBindingOption) As Conversion Public Function GetSpeculativeConversion(semanticModel As SemanticModel, position As Integer, expression As ExpressionSyntax, bindingOption As SpeculativeBindingOption) As Conversion
Dim vbmodel = TryCast(semanticModel, VBSemanticModel) Dim vbmodel = TryCast(semanticModel, VBSemanticModel)
......
...@@ -198,6 +198,8 @@ End Module ...@@ -198,6 +198,8 @@ End Module
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x += y') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x += y')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x += y') ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x += y')
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)
Left: Left:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x') ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
Right: Right:
...@@ -225,6 +227,8 @@ IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (S ...@@ -225,6 +227,8 @@ IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (S
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a += b') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a += b')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperatorMethod: Function B2.op_Addition(x As B2, y As B2) As B2) (OperationKind.CompoundAssignment, Type: B2, IsImplicit) (Syntax: 'a += b') ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperatorMethod: Function B2.op_Addition(x As B2, y As B2) As B2) (OperationKind.CompoundAssignment, Type: B2, IsImplicit) (Syntax: 'a += b')
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)
Left: Left:
ILocalReferenceOperation: a (OperationKind.LocalReference, Type: B2) (Syntax: 'a') ILocalReferenceOperation: a (OperationKind.LocalReference, Type: B2) (Syntax: 'a')
Right: Right:
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.Operations
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
Partial Public Class IOperationTests
Inherits SemanticModelTestBase
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignment_NullArgumentToGetConversionThrows()
Dim nullAssignment As ICompoundAssignmentOperation = Nothing
Assert.Throws(Of ArgumentNullException)("compoundAssignment", Function() nullAssignment.GetInConversion())
Assert.Throws(Of ArgumentNullException)("compoundAssignment", Function() nullAssignment.GetOutConversion())
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentOperation_UserDefinedOperatorInConversion()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim a As New C, x As New Integer
a += x'BIND:"a += x"
End Sub
Class C
Public Shared Widening Operator CType(i As Integer) As C
Return Nothing
End Operator
Public Shared Widening Operator CType(c As C) As Integer
Return 1
End Operator
Public Shared Operator +(c As Integer, i As C) As C
Return 0
End Operator
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a += x')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperatorMethod: Function Module1.C.op_Addition(c As System.Int32, i As Module1.C) As Module1.C) (OperationKind.CompoundAssignment, Type: Module1.C, IsImplicit) (Syntax: 'a += x')
InConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: Function Module1.C.op_Implicit(c As Module1.C) As System.Int32)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: a (OperationKind.LocalReference, Type: Module1.C) (Syntax: 'a')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: Function Module1.C.op_Implicit(i As System.Int32) As Module1.C) (OperationKind.Conversion, Type: Module1.C, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: Function Module1.C.op_Implicit(i As System.Int32) As Module1.C)
Operand:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentOperation_UserDefinedOperatorOutConversion()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim a As New C, x As New Integer
a += x'BIND:"a += x"
End Sub
Class C
Public Shared Widening Operator CType(i As Integer) As C
Return Nothing
End Operator
Public Shared Widening Operator CType(c As C) As Integer
Return 1
End Operator
Public Shared Operator +(c As C, i As Integer) As Integer
Return 0
End Operator
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a += x')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperatorMethod: Function Module1.C.op_Addition(c As Module1.C, i As System.Int32) As System.Int32) (OperationKind.CompoundAssignment, Type: Module1.C, IsImplicit) (Syntax: 'a += x')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: Function Module1.C.op_Implicit(i As System.Int32) As Module1.C)
Left:
ILocalReferenceOperation: a (OperationKind.LocalReference, Type: Module1.C) (Syntax: 'a')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentOperation_UserDefinedOperatorInOutConversion()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim a As New C, x As New Integer
a += x'BIND:"a += x"
End Sub
Class C
Public Shared Widening Operator CType(i As Integer) As C
Return Nothing
End Operator
Public Shared Widening Operator CType(c As C) As Integer
Return 1
End Operator
Public Shared Operator +(c As Integer, i As C) As Integer
Return 0
End Operator
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'a += x')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperatorMethod: Function Module1.C.op_Addition(c As System.Int32, i As Module1.C) As System.Int32) (OperationKind.CompoundAssignment, Type: Module1.C, IsImplicit) (Syntax: 'a += x')
InConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: Function Module1.C.op_Implicit(c As Module1.C) As System.Int32)
OutConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: Function Module1.C.op_Implicit(i As System.Int32) As Module1.C)
Left:
ILocalReferenceOperation: a (OperationKind.LocalReference, Type: Module1.C) (Syntax: 'a')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: Function Module1.C.op_Implicit(i As System.Int32) As Module1.C) (OperationKind.Conversion, Type: Module1.C, IsImplicit) (Syntax: 'x')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: Function Module1.C.op_Implicit(i As System.Int32) As Module1.C)
Operand:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentExpression_BuiltInOperatorInOutConversion()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim x, y As New Integer
x /= y'BIND:"x /= y"
End Sub
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'x /= y')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Divide, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'x /= y')
InConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
Right:
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Double, IsImplicit) (Syntax: 'y')
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: True, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Operand:
ILocalReferenceOperation: y (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'y')
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentExpression_InvalidNoOperator()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim a As New C, x As New Integer
a += x'BIND:"a += x"
End Sub
Class C
Public Shared Widening Operator CType(i As Integer) As C
Return Nothing
End Operator
Public Shared Widening Operator CType(c As C) As Integer
Return 1
End Operator
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'a += x')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: Module1.C, IsInvalid, IsImplicit) (Syntax: 'a += x')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: a (OperationKind.LocalReference, Type: Module1.C, IsInvalid) (Syntax: 'a')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30452: Operator '+' is not defined for types 'Module1.C' and 'Integer'.
a += x'BIND:"a += x"
~~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentExpression_InvalidNoOutConversion()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim a As New C, x As New Integer
a += x'BIND:"a += x"
End Sub
Class C
Public Shared Widening Operator CType(c As C) As Integer
Return 1
End Operator
Public Shared Operator +(c As C, i As Integer) As Integer
Return 1
End Operator
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'a += x')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperatorMethod: Function Module1.C.op_Addition(c As Module1.C, i As System.Int32) As System.Int32) (OperationKind.CompoundAssignment, Type: Module1.C, IsInvalid, IsImplicit) (Syntax: 'a += x')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: a (OperationKind.LocalReference, Type: Module1.C, IsInvalid) (Syntax: 'a')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30311: Value of type 'Integer' cannot be converted to 'Module1.C'.
a += x'BIND:"a += x"
~~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentExpression_InvalidNoInConversion()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim a As New C, x As New Integer
a += x'BIND:"a += x"
End Sub
Class C
Public Shared Widening Operator CType(c As Integer) As C
Return 1
End Operator
Public Shared Operator +(c As Integer, i As C) As Integer
Return 1
End Operator
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'a += x')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: Module1.C, IsInvalid, IsImplicit) (Syntax: 'a += x')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: Function Module1.C.op_Implicit(c As System.Int32) As Module1.C)
Left:
ILocalReferenceOperation: a (OperationKind.LocalReference, Type: Module1.C, IsInvalid) (Syntax: 'a')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30311: Value of type 'Module1.C' cannot be converted to 'Integer'.
a += x'BIND:"a += x"
~
BC42004: Expression recursively calls the containing Operator 'Public Shared Widening Operator CType(c As Integer) As Module1.C'.
Return 1
~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub CompoundAssignmentExpression_InvalidNoOperatorOrConversions()
Dim source = <![CDATA[
Module Module1
Sub Main()
Dim a As New C, x As New Integer
a += x'BIND:"a += x"
End Sub
Class C
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, IsInvalid) (Syntax: 'a += x')
Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: Module1.C, IsInvalid, IsImplicit) (Syntax: 'a += x')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
Left:
ILocalReferenceOperation: a (OperationKind.LocalReference, Type: Module1.C, IsInvalid) (Syntax: 'a')
Right:
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32, IsInvalid) (Syntax: 'x')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30452: Operator '+' is not defined for types 'Module1.C' and 'Integer'.
a += x'BIND:"a += x"
~~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of AssignmentStatementSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
End Class
End Namespace
...@@ -672,18 +672,17 @@ End Class]]>.Value ...@@ -672,18 +672,17 @@ End Class]]>.Value
Dim expectedOperationTree = <![CDATA[ Dim expectedOperationTree = <![CDATA[
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'Mid(str, st ... ngth) = str') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'Mid(str, st ... ngth) = str')
Expression: Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Void, IsImplicit) (Syntax: 'Mid(str, st ... ngth) = str') IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: 'Mid(str, st ... ngth) = str')
Left: Children(2):
IParameterReferenceOperation: str (OperationKind.ParameterReference, Type: System.String) (Syntax: 'str') IParameterReferenceOperation: str (OperationKind.ParameterReference, Type: System.String) (Syntax: 'str')
Right: IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: 'Mid(str, st ... ngth) = str')
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: 'Mid(str, st ... ngth) = str') Children(4):
Children(4): IParenthesizedOperation (OperationKind.Parenthesized, Type: System.String) (Syntax: 'Mid(str, start, length)')
IParenthesizedOperation (OperationKind.Parenthesized, Type: System.String) (Syntax: 'Mid(str, start, length)') Operand:
Operand: IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: 'str')
IOperation: (OperationKind.None, Type: null, IsImplicit) (Syntax: 'str') IParameterReferenceOperation: start (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'start')
IParameterReferenceOperation: start (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'start') IParameterReferenceOperation: length (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'length')
IParameterReferenceOperation: length (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'length') IParameterReferenceOperation: str (OperationKind.ParameterReference, Type: System.String) (Syntax: 'str')
IParameterReferenceOperation: str (OperationKind.ParameterReference, Type: System.String) (Syntax: 'str')
]]>.Value ]]>.Value
Dim expectedDiagnostics = String.Empty Dim expectedDiagnostics = String.Empty
......
...@@ -41,6 +41,8 @@ IWhileLoopOperation (ConditionIsTop: False, ConditionIsUntil: False) (LoopKind.W ...@@ -41,6 +41,8 @@ IWhileLoopOperation (ConditionIsTop: False, ConditionIsUntil: False) (LoopKind.W
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'sum += ids(i)') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'sum += ids(i)')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'sum += ids(i)') ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'sum += ids(i)')
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)
Left: Left:
ILocalReferenceOperation: sum (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'sum') ILocalReferenceOperation: sum (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'sum')
Right: Right:
...@@ -52,6 +54,8 @@ IWhileLoopOperation (ConditionIsTop: False, ConditionIsUntil: False) (LoopKind.W ...@@ -52,6 +54,8 @@ IWhileLoopOperation (ConditionIsTop: False, ConditionIsUntil: False) (LoopKind.W
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i += 1') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i += 1')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'i += 1') ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'i += 1')
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)
Left: Left:
ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i') ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
Right: Right:
...@@ -211,6 +215,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh ...@@ -211,6 +215,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'sum += i') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'sum += i')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'sum += i') ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'sum += i')
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)
Left: Left:
ILocalReferenceOperation: sum (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'sum') ILocalReferenceOperation: sum (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'sum')
Right: Right:
...@@ -218,6 +224,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh ...@@ -218,6 +224,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i += 1') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i += 1')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'i += 1') ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'i += 1')
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)
Left: Left:
ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i') ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
Right: Right:
...@@ -458,6 +466,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh ...@@ -458,6 +466,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'value -= 1') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'value -= 1')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Subtract, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'value -= 1') ICompoundAssignmentOperation (BinaryOperatorKind.Subtract, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'value -= 1')
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)
Left: Left:
ILocalReferenceOperation: value (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'value') ILocalReferenceOperation: value (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'value')
Right: Right:
...@@ -547,6 +557,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh ...@@ -547,6 +557,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'number += 1') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'number += 1')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'number += 1') ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'number += 1')
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)
Left: Left:
IParameterReferenceOperation: number (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'number') IParameterReferenceOperation: number (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'number')
Right: Right:
...@@ -606,6 +618,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh ...@@ -606,6 +618,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'number += 1') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'number += 1')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'number += 1') ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'number += 1')
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)
Left: Left:
IParameterReferenceOperation: number (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'number') IParameterReferenceOperation: number (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'number')
Right: Right:
...@@ -751,6 +765,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh ...@@ -751,6 +765,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i += 1') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i += 1')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'i += 1') ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'i += 1')
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)
Left: Left:
ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i') ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
Right: Right:
...@@ -822,6 +838,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh ...@@ -822,6 +838,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i += 1') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i += 1')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'i += 1') ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'i += 1')
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)
Left: Left:
ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i') ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
Right: Right:
...@@ -877,6 +895,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh ...@@ -877,6 +895,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i += 1') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i += 1')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'i += 1') ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'i += 1')
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)
Left: Left:
ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i') ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
Right: Right:
...@@ -902,6 +922,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh ...@@ -902,6 +922,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'j += 1') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'j += 1')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'j += 1') ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'j += 1')
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)
Left: Left:
ILocalReferenceOperation: j (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'j') ILocalReferenceOperation: j (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'j')
Right: Right:
...@@ -970,6 +992,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh ...@@ -970,6 +992,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i += 1') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i += 1')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'i += 1') ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'i += 1')
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)
Left: Left:
ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i') ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
Right: Right:
...@@ -995,6 +1019,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh ...@@ -995,6 +1019,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'j += 1') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'j += 1')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'j += 1') ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'j += 1')
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)
Left: Left:
ILocalReferenceOperation: j (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'j') ILocalReferenceOperation: j (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'j')
Right: Right:
...@@ -1115,6 +1141,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh ...@@ -1115,6 +1141,8 @@ IWhileLoopOperation (ConditionIsTop: True, ConditionIsUntil: False) (LoopKind.Wh
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i += 1') IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: 'i += 1')
Expression: Expression:
ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'i += 1') ICompoundAssignmentOperation (BinaryOperatorKind.Add, Checked) (OperationKind.CompoundAssignment, Type: System.Int32, IsImplicit) (Syntax: 'i += 1')
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)
Left: Left:
ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i') ILocalReferenceOperation: i (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'i')
Right: Right:
......
...@@ -1321,6 +1321,12 @@ public override void VisitCompoundAssignment(ICompoundAssignmentOperation operat ...@@ -1321,6 +1321,12 @@ public override void VisitCompoundAssignment(ICompoundAssignmentOperation operat
LogString($" ({kindStr})"); LogString($" ({kindStr})");
LogHasOperatorMethodExpressionCommon(operation.OperatorMethod); LogHasOperatorMethodExpressionCommon(operation.OperatorMethod);
LogCommonPropertiesAndNewLine(operation); LogCommonPropertiesAndNewLine(operation);
Indent();
LogConversion(operation.InConversion, "InConversion");
LogNewLine();
LogConversion(operation.OutConversion, "OutConversion");
LogNewLine();
Unindent();
Visit(operation.Target, "Left"); Visit(operation.Target, "Left");
Visit(operation.Value, "Right"); Visit(operation.Value, "Right");
......
// 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.
using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp;
...@@ -539,6 +540,23 @@ public override void VisitCompoundAssignment(ICompoundAssignmentOperation operat ...@@ -539,6 +540,23 @@ public override void VisitCompoundAssignment(ICompoundAssignmentOperation operat
{ {
var operatorMethod = operation.OperatorMethod; var operatorMethod = operation.OperatorMethod;
var binaryOperationKind = operation.OperatorKind; var binaryOperationKind = operation.OperatorKind;
var inConversion = operation.InConversion;
var outConversion = operation.OutConversion;
if (operation.Syntax.Language == LanguageNames.CSharp)
{
Assert.Throws<ArgumentException>("compoundAssignment", () => VisualBasic.VisualBasicExtensions.GetInConversion(operation));
Assert.Throws<ArgumentException>("compoundAssignment", () => VisualBasic.VisualBasicExtensions.GetOutConversion(operation));
var inConversionInteranl = CSharp.CSharpExtensions.GetInConversion(operation);
var outConversionInteranl = CSharp.CSharpExtensions.GetOutConversion(operation);
}
else
{
Assert.Throws<ArgumentException>("compoundAssignment", () => CSharp.CSharpExtensions.GetInConversion(operation));
Assert.Throws<ArgumentException>("compoundAssignment", () => CSharp.CSharpExtensions.GetOutConversion(operation));
var inConversionInternal = VisualBasic.VisualBasicExtensions.GetInConversion(operation);
var outConversionInternal = VisualBasic.VisualBasicExtensions.GetOutConversion(operation);
}
base.VisitCompoundAssignment(operation); base.VisitCompoundAssignment(operation);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册