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

Merge pull request #25820 from 333fred/discard-expression

Added IDiscardOperation to the IOperation API
......@@ -245,6 +245,8 @@ private IOperation CreateInternal(BoundNode boundNode)
return CreateConstructorBodyOperation((BoundConstructorMethodBody)boundNode);
case BoundKind.NonConstructorMethodBody:
return CreateMethodBodyOperation((BoundNonConstructorMethodBody)boundNode);
case BoundKind.DiscardExpression:
return CreateDiscardExpressionOperation((BoundDiscardExpression)boundNode);
default:
Optional<object> constantValue = ConvertToOptional((boundNode as BoundExpression)?.ConstantValue);
......@@ -1883,5 +1885,15 @@ private IOperation CreateBoundRangeVariableOperation(BoundRangeVariable boundRan
// We do not have operation nodes for the bound range variables, just it's value.
return Create(boundRangeVariable.Value);
}
private IOperation CreateDiscardExpressionOperation(BoundDiscardExpression boundNode)
{
return new DiscardOperation((IDiscardSymbol)boundNode.ExpressionSymbol,
_semanticModel,
boundNode.Syntax,
boundNode.Type,
ConvertToOptional(boundNode.ConstantValue),
isImplicit: boundNode.WasCompilerGenerated);
}
}
}
// 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
{
[CompilerTrait(CompilerFeature.IOperation)]
public partial class IOperationTests : SemanticModelTestBase
{
[Fact]
public void DiscardExpression_AsAssignment()
{
string source = @"
class C
{
int P { get; }
void M()
{
/*<bind>*/_/*</bind>*/ = P;
}
}
";
string expectedOperationTree = @"
IDiscardOperation (Symbol: System.Int32 _) (OperationKind.Discard, Type: System.Int32) (Syntax: '_')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<IdentifierNameSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[Fact]
public void DiscardExpression_AsAssignment_EntireStatement()
{
string source = @"
class C
{
int P { get; }
void M()
{
/*<bind>*/_ = P;/*</bind>*/
}
}
";
string expectedOperationTree = @"
IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (Syntax: '_ = P;')
Expression:
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32) (Syntax: '_ = P')
Left:
IDiscardOperation (Symbol: System.Int32 _) (OperationKind.Discard, Type: System.Int32) (Syntax: '_')
Right:
IPropertyReferenceOperation: System.Int32 C.P { get; } (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'P')
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: C, IsImplicit) (Syntax: 'P')
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<ExpressionStatementSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
}
}
......@@ -6204,8 +6204,8 @@ void M()
ITupleOperation (OperationKind.Tuple, Type: (System.Int32, System.Int32)) (Syntax: '(_, _)')
NaturalType: (System.Int32, System.Int32)
Elements(2):
IOperation: (OperationKind.None, Type: null) (Syntax: '_')
IOperation: (OperationKind.None, Type: null) (Syntax: '_')
IDiscardOperation (Symbol: System.Int32 _) (OperationKind.Discard, Type: System.Int32) (Syntax: '_')
IDiscardOperation (Symbol: System.Int32 _) (OperationKind.Discard, Type: System.Int32) (Syntax: '_')
Right:
ITupleOperation (OperationKind.Tuple, Type: (System.Int32, System.Int32)) (Syntax: '(0, 0)')
NaturalType: (System.Int32, System.Int32)
......@@ -6239,7 +6239,7 @@ void M()
NaturalType: (System.Int32 x, System.Int32)
Elements(2):
ILocalReferenceOperation: x (OperationKind.LocalReference, Type: System.Int32) (Syntax: 'x')
IOperation: (OperationKind.None, Type: null) (Syntax: '_')
IDiscardOperation (Symbol: System.Int32 _) (OperationKind.Discard, Type: System.Int32) (Syntax: '_')
Right:
ITupleOperation (OperationKind.Tuple, Type: (System.Int32, System.Int32)) (Syntax: '(0, 0)')
NaturalType: (System.Int32, System.Int32)
......@@ -6271,7 +6271,7 @@ void M2(out int x)
}
";
string expectedOperationTree = @"
IOperation: (OperationKind.None, Type: null) (Syntax: 'var _')
IDiscardOperation (Symbol: System.Int32 _) (OperationKind.Discard, Type: System.Int32) (Syntax: 'var _')
";
var expectedDiagnostics = DiagnosticDescription.None;
......
......@@ -6730,4 +6730,27 @@ internal sealed class LazyConstructorBodyOperation : BaseConstructorBodyOperatio
public override IBlockOperation BlockBody => SetParentOperation(_lazyBlockBody.Value, this);
public override IBlockOperation ExpressionBody => SetParentOperation(_lazyExpressionBody.Value, this);
}
internal sealed class DiscardOperation : Operation, IDiscardOperation
{
public DiscardOperation(IDiscardSymbol discardSymbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(OperationKind.Discard, semanticModel, syntax, type, constantValue, isImplicit)
{
DiscardSymbol = discardSymbol;
}
public IDiscardSymbol DiscardSymbol { get; }
public override IEnumerable<IOperation> Children => Array.Empty<IOperation>();
public override void Accept(OperationVisitor visitor)
{
visitor.VisitDiscardOperation(this);
}
public override TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, TResult> visitor, TArgument argument)
{
return visitor.VisitDiscardOperation(this, argument);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.CodeAnalysis.Operations
{
/// <summary>
/// Represents a discard operation.
/// <para>
/// Current Usage:
/// (1) C# discard expressions
/// </para>
/// </summary>
/// <remarks>
/// This interface is reserved for implementation by its associated APIs. We reserve the right to
/// change it in the future.
/// </remarks>
public interface IDiscardOperation : IOperation
{
/// <summary>
/// The symbol of the discard operation.
/// </summary>
IDiscardSymbol DiscardSymbol { get; }
}
}
......@@ -500,5 +500,10 @@ public override IOperation VisitMethodBodyOperation(IMethodBodyOperation operati
{
return new MethodBodyOperation(((Operation)operation).SemanticModel, operation.Syntax, Visit(operation.BlockBody), Visit(operation.ExpressionBody));
}
public override IOperation VisitDiscardOperation(IDiscardOperation operation, object argument)
{
return new DiscardOperation(operation.DiscardSymbol, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
}
}
}
......@@ -187,6 +187,8 @@ public enum OperationKind
MethodBodyOperation = 0x58,
/// <summary>Indicates an <see cref="IConstructorBodyOperation"/>.</summary>
ConstructorBodyOperation = 0x59,
/// <summary>Indicates an <see cref="IDiscardOperation"/>.</summary>
Discard = 0x5A,
// /// <summary>Indicates an <see cref="IFixedOperation"/>.</summary>
// https://github.com/dotnet/roslyn/issues/21281
......
......@@ -509,6 +509,11 @@ public virtual void VisitConstructorBodyOperation(IConstructorBodyOperation oper
{
DefaultVisit(operation);
}
public virtual void VisitDiscardOperation(IDiscardOperation operation)
{
DefaultVisit(operation);
}
}
/// <summary>
......@@ -1024,5 +1029,10 @@ public virtual TResult VisitConstructorBodyOperation(IConstructorBodyOperation o
{
return DefaultVisit(operation, argument);
}
public virtual TResult VisitDiscardOperation(IDiscardOperation operation, TArgument argument)
{
return DefaultVisit(operation, argument);
}
}
}
......@@ -11,11 +11,14 @@ Microsoft.CodeAnalysis.MetadataImportOptions.All = 2 -> Microsoft.CodeAnalysis.M
Microsoft.CodeAnalysis.MetadataImportOptions.Internal = 1 -> Microsoft.CodeAnalysis.MetadataImportOptions
Microsoft.CodeAnalysis.MetadataImportOptions.Public = 0 -> Microsoft.CodeAnalysis.MetadataImportOptions
Microsoft.CodeAnalysis.OperationKind.ConstructorBodyOperation = 89 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.Discard = 90 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.MethodBodyOperation = 88 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.TupleBinaryOperator = 87 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.Operations.IConstructorBodyOperation
Microsoft.CodeAnalysis.Operations.IConstructorBodyOperation.Initializer.get -> Microsoft.CodeAnalysis.IOperation
Microsoft.CodeAnalysis.Operations.IConstructorBodyOperation.Locals.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ILocalSymbol>
Microsoft.CodeAnalysis.Operations.IDiscardOperation
Microsoft.CodeAnalysis.Operations.IDiscardOperation.DiscardSymbol.get -> Microsoft.CodeAnalysis.IDiscardSymbol
Microsoft.CodeAnalysis.Operations.ILocalFunctionOperation.IgnoredBody.get -> Microsoft.CodeAnalysis.Operations.IBlockOperation
Microsoft.CodeAnalysis.Operations.IMethodBodyBaseOperation
Microsoft.CodeAnalysis.Operations.IMethodBodyBaseOperation.BlockBody.get -> Microsoft.CodeAnalysis.Operations.IBlockOperation
......@@ -33,8 +36,10 @@ abstract Microsoft.CodeAnalysis.DataFlowAnalysis.CapturedOutside.get -> System.C
const Microsoft.CodeAnalysis.WellKnownMemberNames.DeconstructMethodName = "Deconstruct" -> string
static Microsoft.CodeAnalysis.Diagnostic.Create(Microsoft.CodeAnalysis.DiagnosticDescriptor descriptor, Microsoft.CodeAnalysis.Location location, Microsoft.CodeAnalysis.DiagnosticSeverity effectiveSeverity, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.Location> additionalLocations, System.Collections.Immutable.ImmutableDictionary<string, string> properties, params object[] messageArgs) -> Microsoft.CodeAnalysis.Diagnostic
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitConstructorBodyOperation(Microsoft.CodeAnalysis.Operations.IConstructorBodyOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitDiscardOperation(Microsoft.CodeAnalysis.Operations.IDiscardOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitMethodBodyOperation(Microsoft.CodeAnalysis.Operations.IMethodBodyOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitTupleBinaryOperator(Microsoft.CodeAnalysis.Operations.ITupleBinaryOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitConstructorBodyOperation(Microsoft.CodeAnalysis.Operations.IConstructorBodyOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitDiscardOperation(Microsoft.CodeAnalysis.Operations.IDiscardOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitMethodBodyOperation(Microsoft.CodeAnalysis.Operations.IMethodBodyOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitTupleBinaryOperator(Microsoft.CodeAnalysis.Operations.ITupleBinaryOperation operation, TArgument argument) -> TResult
\ No newline at end of file
......@@ -1592,6 +1592,15 @@ public override void VisitMethodBodyOperation(IMethodBodyOperation operation)
Visit(operation.ExpressionBody, "ExpressionBody");
}
public override void VisitDiscardOperation(IDiscardOperation operation)
{
LogString(nameof(IDiscardOperation));
LogString(" (");
LogSymbol(operation.DiscardSymbol, "Symbol");
LogString(")");
LogCommonPropertiesAndNewLine(operation);
}
#endregion
}
}
......@@ -1181,5 +1181,14 @@ public override void VisitMethodBodyOperation(IMethodBodyOperation operation)
Assert.Empty(operation.Children);
}
}
public override void VisitDiscardOperation(IDiscardOperation operation)
{
Assert.Equal(OperationKind.Discard, operation.Kind);
Assert.Empty(operation.Children);
var discardSymbol = operation.DiscardSymbol;
Assert.Equal(operation.Type, discardSymbol.Type);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册