提交 d3e22e90 编写于 作者: M Manish Vasani 提交者: GitHub

Merge pull request #21794 from mavasani/IsNotTypeOf

Add a new boolean flag to IIsTypeExpression to represent VB TypeOf Is…
......@@ -715,9 +715,10 @@ private IIsTypeExpression CreateBoundIsOperatorOperation(BoundIsOperator boundIs
ITypeSymbol isType = boundIsOperator.TargetType.Type;
SyntaxNode syntax = boundIsOperator.Syntax;
ITypeSymbol type = boundIsOperator.Type;
bool isNotTypeExpression = false;
Optional<object> constantValue = ConvertToOptional(boundIsOperator.ConstantValue);
bool isImplicit = boundIsOperator.WasCompilerGenerated;
return new LazyIsTypeExpression(operand, isType, _semanticModel, syntax, type, constantValue, isImplicit);
return new LazyIsTypeExpression(operand, isType, isNotTypeExpression, _semanticModel, syntax, type, constantValue, isImplicit);
}
private ISizeOfExpression CreateBoundSizeOfOperatorOperation(BoundSizeOfOperator boundSizeOfOperator)
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public partial class IOperationTests : SemanticModelTestBase
{
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void TestIsOperator_ObjectExpressionStringType()
{
string source = @"
namespace TestIsOperator
{
class TestType
{
}
class C
{
static void M(string myStr)
{
object o = myStr;
bool b = /*<bind>*/o is string/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IIsTypeExpression (OperationKind.IsTypeExpression, Type: System.Boolean) (Syntax: 'o is string')
Operand: ILocalReferenceExpression: o (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'o')
IsType: System.String
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<BinaryExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void TestIsOperator_IntExpressionIntType()
{
string source = @"
namespace TestIsOperator
{
class TestType
{
}
class C
{
static void M(string myStr)
{
int myInt = 3;
bool b = /*<bind>*/myInt is int/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IIsTypeExpression (OperationKind.IsTypeExpression, Type: System.Boolean) (Syntax: 'myInt is int')
Operand: ILocalReferenceExpression: myInt (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'myInt')
IsType: System.Int32
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0183: The given expression is always of the provided ('int') type
// bool b = /*<bind>*/myInt is int/*</bind>*/;
Diagnostic(ErrorCode.WRN_IsAlwaysTrue, "myInt is int").WithArguments("int").WithLocation(13, 32)
};
VerifyOperationTreeAndDiagnosticsForTest<BinaryExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void TestIsOperator_ObjectExpressionUserDefinedType()
{
string source = @"
namespace TestIsOperator
{
class TestType
{
}
class C
{
static void M(string myStr)
{
TestType tt = null;
object o = tt;
bool b = /*<bind>*/o is TestType/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IIsTypeExpression (OperationKind.IsTypeExpression, Type: System.Boolean) (Syntax: 'o is TestType')
Operand: ILocalReferenceExpression: o (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'o')
IsType: TestIsOperator.TestType
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<BinaryExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void TestIsOperator_NullExpressionUserDefinedType()
{
string source = @"
namespace TestIsOperator
{
class TestType
{
}
class C
{
static void M(string myStr)
{
TestType tt = null;
object o = tt;
bool b = /*<bind>*/null is TestType/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IIsTypeExpression (OperationKind.IsTypeExpression, Type: System.Boolean) (Syntax: 'null is TestType')
Operand: ILiteralExpression (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null')
IsType: TestIsOperator.TestType
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0184: The given expression is never of the provided ('TestType') type
// bool b = /*<bind>*/null is TestType/*</bind>*/;
Diagnostic(ErrorCode.WRN_IsAlwaysFalse, "null is TestType").WithArguments("TestIsOperator.TestType").WithLocation(14, 32)
};
VerifyOperationTreeAndDiagnosticsForTest<BinaryExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void TestIsOperator_IntExpressionEnumType()
{
string source = @"
class IsTest
{
static void Main()
{
var b = /*<bind>*/1 is color/*</bind>*/;
System.Console.WriteLine(b);
}
}
enum color
{ }
";
string expectedOperationTree = @"
IIsTypeExpression (OperationKind.IsTypeExpression, Type: System.Boolean) (Syntax: '1 is color')
Operand: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1')
IsType: color
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0184: The given expression is never of the provided ('color') type
// var b = /*<bind>*/1 is color/*</bind>*/;
Diagnostic(ErrorCode.WRN_IsAlwaysFalse, "1 is color").WithArguments("color").WithLocation(6, 27)
};
VerifyOperationTreeAndDiagnosticsForTest<BinaryExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void TestIsOperatorGeneric_TypeParameterExpressionIntType()
{
string source = @"
namespace TestIsOperatorGeneric
{
class C
{
public static void M<T, U, W>(T t, U u)
where T : class
where U : class
{
bool test = /*<bind>*/t is int/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IIsTypeExpression (OperationKind.IsTypeExpression, Type: System.Boolean) (Syntax: 't is int')
Operand: IParameterReferenceExpression: t (OperationKind.ParameterReferenceExpression, Type: T) (Syntax: 't')
IsType: System.Int32
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<BinaryExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void TestIsOperatorGeneric_TypeParameterExpressionObjectType()
{
string source = @"
namespace TestIsOperatorGeneric
{
class C
{
public static void M<T, U, W>(T t, U u)
where T : class
where U : class
{
bool test = /*<bind>*/u is object/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IIsTypeExpression (OperationKind.IsTypeExpression, Type: System.Boolean) (Syntax: 'u is object')
Operand: IParameterReferenceExpression: u (OperationKind.ParameterReferenceExpression, Type: U) (Syntax: 'u')
IsType: System.Object
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<BinaryExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void TestIsOperatorGeneric_TypeParameterExpressionDifferentTypeParameterType()
{
string source = @"
namespace TestIsOperatorGeneric
{
class C
{
public static void M<T, U, W>(T t, U u)
where T : class
where U : class
{
bool test = /*<bind>*/t is U/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IIsTypeExpression (OperationKind.IsTypeExpression, Type: System.Boolean) (Syntax: 't is U')
Operand: IParameterReferenceExpression: t (OperationKind.ParameterReferenceExpression, Type: T) (Syntax: 't')
IsType: U
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<BinaryExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void TestIsOperatorGeneric_TypeParameterExpressionSameTypeParameterType()
{
string source = @"
namespace TestIsOperatorGeneric
{
class C
{
public static void M<T, U, W>(T t, U u)
where T : class
where U : class
{
bool test = /*<bind>*/t is T/*</bind>*/;
}
}
}
";
string expectedOperationTree = @"
IIsTypeExpression (OperationKind.IsTypeExpression, Type: System.Boolean) (Syntax: 't is T')
Operand: IParameterReferenceExpression: t (OperationKind.ParameterReferenceExpression, Type: T) (Syntax: 't')
IsType: T
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<BinaryExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
}
}
// 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 Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Test.Utilities;
......
......@@ -2553,10 +2553,11 @@ public LazyInvocationExpression(IMethodSymbol targetMethod, Lazy<IOperation> ins
/// </summary>
internal abstract partial class BaseIsTypeExpression : Operation, IIsTypeExpression
{
protected BaseIsTypeExpression(ITypeSymbol isType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
protected BaseIsTypeExpression(ITypeSymbol isType, bool isNotTypeExpression, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(OperationKind.IsTypeExpression, semanticModel, syntax, type, constantValue, isImplicit)
{
IsType = isType;
IsNotTypeExpression = isNotTypeExpression;
}
protected abstract IOperation OperandImpl { get; }
......@@ -2564,6 +2565,12 @@ internal abstract partial class BaseIsTypeExpression : Operation, IIsTypeExpress
/// Type for which to test.
/// </summary>
public ITypeSymbol IsType { get; }
/// <summary>
/// Flag indicating if this is an "is not" type expression.
/// True for VB "TypeOf ... IsNot ..." expression.
/// False, otherwise.
/// </summary>
public bool IsNotTypeExpression { get; }
public override IEnumerable<IOperation> Children
{
get
......@@ -2590,8 +2597,8 @@ public override void Accept(OperationVisitor visitor)
/// </summary>
internal sealed partial class IsTypeExpression : BaseIsTypeExpression, IIsTypeExpression
{
public IsTypeExpression(IOperation operand, ITypeSymbol isType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(isType, semanticModel, syntax, type, constantValue, isImplicit)
public IsTypeExpression(IOperation operand, ITypeSymbol isType, bool isNotTypeExpression, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(isType, isNotTypeExpression, semanticModel, syntax, type, constantValue, isImplicit)
{
OperandImpl = operand;
}
......@@ -2606,7 +2613,7 @@ internal sealed partial class LazyIsTypeExpression : BaseIsTypeExpression, IIsTy
{
private readonly Lazy<IOperation> _lazyOperand;
public LazyIsTypeExpression(Lazy<IOperation> operand, ITypeSymbol isType, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) : base(isType, semanticModel, syntax, type, constantValue, isImplicit)
public LazyIsTypeExpression(Lazy<IOperation> operand, ITypeSymbol isType, bool isNotTypeExpression, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) : base(isType, isNotTypeExpression, semanticModel, syntax, type, constantValue, isImplicit)
{
_lazyOperand = operand ?? throw new System.ArgumentNullException(nameof(operand));
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
namespace Microsoft.CodeAnalysis.Semantics
{
/// <summary>
......@@ -17,10 +15,17 @@ public interface IIsTypeExpression : IOperation
/// Value to test.
/// </summary>
IOperation Operand { get; }
/// <summary>
/// Type for which to test.
/// </summary>
ITypeSymbol IsType { get; }
/// <summary>
/// Flag indicating if this is an "is not" type expression.
/// True for VB "TypeOf ... IsNot ..." expression.
/// False, otherwise.
/// </summary>
bool IsNotTypeExpression { get; }
}
}
......@@ -276,7 +276,7 @@ public override IOperation VisitCoalesceExpression(ICoalesceExpression operation
public override IOperation VisitIsTypeExpression(IIsTypeExpression operation, object argument)
{
return new IsTypeExpression(Visit(operation.Operand), operation.IsType, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
return new IsTypeExpression(Visit(operation.Operand), operation.IsType, operation.IsNotTypeExpression, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
}
public override IOperation VisitSizeOfExpression(ISizeOfExpression operation, object argument)
......
......@@ -344,6 +344,7 @@ Microsoft.CodeAnalysis.Semantics.IIsPatternExpression.Expression.get -> Microsof
Microsoft.CodeAnalysis.Semantics.IIsPatternExpression.Pattern.get -> Microsoft.CodeAnalysis.Semantics.IPattern
Microsoft.CodeAnalysis.Semantics.IIsTypeExpression
Microsoft.CodeAnalysis.Semantics.IIsTypeExpression.IsType.get -> Microsoft.CodeAnalysis.ITypeSymbol
Microsoft.CodeAnalysis.Semantics.IIsTypeExpression.IsNotTypeExpression.get -> bool
Microsoft.CodeAnalysis.Semantics.IIsTypeExpression.Operand.get -> Microsoft.CodeAnalysis.IOperation
Microsoft.CodeAnalysis.Semantics.ILabeledStatement
Microsoft.CodeAnalysis.Semantics.ILabeledStatement.Label.get -> Microsoft.CodeAnalysis.ILabelSymbol
......
......@@ -565,11 +565,12 @@ Namespace Microsoft.CodeAnalysis.Semantics
Private Function CreateBoundTypeOfOperation(boundTypeOf As BoundTypeOf) As IIsTypeExpression
Dim operand As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundTypeOf.Operand))
Dim isType As ITypeSymbol = boundTypeOf.TargetType
Dim isNotTypeExpression As Boolean = boundTypeOf.IsTypeOfIsNotExpression
Dim syntax As SyntaxNode = boundTypeOf.Syntax
Dim type As ITypeSymbol = boundTypeOf.Type
Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundTypeOf.ConstantValueOpt)
Dim isImplicit As Boolean = boundTypeOf.WasCompilerGenerated
Return New LazyIsTypeExpression(operand, isType, _semanticModel, syntax, type, constantValue, isImplicit)
Return New LazyIsTypeExpression(operand, isType, isNotTypeExpression, _semanticModel, syntax, type, constantValue, isImplicit)
End Function
Private Function CreateBoundObjectCreationExpressionOperation(boundObjectCreationExpression As BoundObjectCreationExpression) As IObjectCreationExpression
......
......@@ -886,12 +886,18 @@ public override void VisitCoalesceExpression(ICoalesceExpression operation)
public override void VisitIsTypeExpression(IIsTypeExpression operation)
{
LogString(nameof(IIsTypeExpression));
if (operation.IsNotTypeExpression)
{
LogString(" (IsNotExpression)");
}
LogCommonPropertiesAndNewLine(operation);
Visit(operation.Operand, "Operand");
Indent();
LogType(operation.Type);
LogType(operation.IsType, "IsType");
LogNewLine();
Unindent();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册