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

Merge pull request #39576 from 333fred/iusingdeclarationoperation

Introduce IUsingDeclarationOperation
......@@ -1734,10 +1734,10 @@ private IOperation CreateBoundLocalDeclarationOperation(BoundLocalDeclaration bo
// In the case of a for loop, varStatement and varDeclaration will be the same syntax node.
// We can only have one explicit operation, so make sure this node is implicit in that scenario.
bool isImplicit = (varStatement == varDeclaration) || boundLocalDeclaration.WasCompilerGenerated;
return new VariableDeclarationGroupOperation(ImmutableArray.Create(multiVariableDeclaration), VariableDeclarationKind.Default, _semanticModel, varStatement, type, constantValue, isImplicit);
return new VariableDeclarationGroupOperation(ImmutableArray.Create(multiVariableDeclaration), _semanticModel, varStatement, type, constantValue, isImplicit);
}
private IVariableDeclarationGroupOperation CreateBoundMultipleLocalDeclarationsBaseOperation(BoundMultipleLocalDeclarationsBase boundMultipleLocalDeclarations)
private IOperation CreateBoundMultipleLocalDeclarationsBaseOperation(BoundMultipleLocalDeclarationsBase boundMultipleLocalDeclarations)
{
// The syntax for the boundMultipleLocalDeclarations can either be a LocalDeclarationStatement or a VariableDeclaration, depending on the context
// (using/fixed statements vs variable declaration)
......@@ -1750,19 +1750,27 @@ private IVariableDeclarationGroupOperation CreateBoundMultipleLocalDeclarationsB
bool declarationIsImplicit = boundMultipleLocalDeclarations.WasCompilerGenerated;
IVariableDeclarationOperation multiVariableDeclaration = new CSharpLazyVariableDeclarationOperation(this, boundMultipleLocalDeclarations, _semanticModel, declarationSyntax, null, default, declarationIsImplicit);
// If this is a using declaration, work out the declaration kind
VariableDeclarationKind declKind = boundMultipleLocalDeclarations is BoundUsingLocalDeclarations usingDecl
? usingDecl.AwaitOpt is object
? VariableDeclarationKind.AsynchronousUsing
: VariableDeclarationKind.Using
: VariableDeclarationKind.Default;
ITypeSymbol type = null;
Optional<object> constantValue = default(Optional<object>);
// If the syntax was the same, we're in a fixed statement or using statement. We make the Group operation implicit in this scenario, as the
// syntax itself is a VariableDeclaration
bool isImplicit = declarationGroupSyntax == declarationSyntax || boundMultipleLocalDeclarations.WasCompilerGenerated;
return new VariableDeclarationGroupOperation(ImmutableArray.Create(multiVariableDeclaration), declKind, _semanticModel, declarationGroupSyntax, type, constantValue, isImplicit);
// syntax itself is a VariableDeclaration. We do this for using declarations as well, but since that doesn't have a separate parent bound
// node, we need to check the current node for that explicitly.
bool isImplicit = declarationGroupSyntax == declarationSyntax || boundMultipleLocalDeclarations.WasCompilerGenerated || boundMultipleLocalDeclarations is BoundUsingLocalDeclarations;
var variableDeclaration = new VariableDeclarationGroupOperation(ImmutableArray.Create(multiVariableDeclaration), _semanticModel, declarationGroupSyntax, type, constantValue, isImplicit);
if (boundMultipleLocalDeclarations is BoundUsingLocalDeclarations usingDecl)
{
return new UsingDeclarationOperation(
variableDeclaration,
isAsynchronous: usingDecl.AwaitOpt is object,
_semanticModel,
declarationGroupSyntax,
type: null,
constantValue: default,
isImplicit: boundMultipleLocalDeclarations.WasCompilerGenerated);
}
return variableDeclaration;
}
private ILabeledOperation CreateBoundLabelStatementOperation(BoundLabelStatement boundLabelStatement)
......
......@@ -240,5 +240,7 @@ public enum OperationKind
SwitchExpressionArm = 0x6a,
/// <summary>Indicates an <see cref="IPropertySubpatternOperation"/>.</summary>
PropertySubpattern = 0x6b,
/// <summary>Indicates an <see cref="IUsingDeclarationOperation"/>.</summary>
UsingDeclaration = 0x6c,
}
}
......@@ -72,10 +72,6 @@ public interface IVariableDeclarationGroupOperation : IOperation
/// In C#, this will always be a single declaration, with all variables in <see cref="IVariableDeclarationOperation.Declarators" />.
/// </remarks>
ImmutableArray<IVariableDeclarationOperation> Declarations { get; }
/// <summary>
/// Specifies the <see cref="VariableDeclarationKind" /> of this declaration group.
/// </summary>
VariableDeclarationKind DeclarationKind { get; }
}
/// <summary>
/// Represents a switch operation with a value to be switched upon and switch cases.
......@@ -2771,6 +2767,29 @@ internal interface IWithOperation : IOperation
/// </summary>
IOperation Value { get; }
}
/// <summary>
/// Represents using variable declaration, with scope spanning across the parent <see cref="IBlockOperation" />.
/// <para>
/// Current Usage:
/// (1) C# using declaration
/// (1) C# asynchronous using declaration
/// </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 IUsingDeclarationOperation : IOperation
{
/// <summary>
/// The variables declared by this using declaration.
/// </summary>
IVariableDeclarationGroupOperation DeclarationGroup { get; }
/// <summary>
/// True if this is an asynchronous using declaration.
/// </summary>
bool IsAsynchronous { get; }
}
#endregion
#region Implementations
......@@ -2827,13 +2846,9 @@ public override ImmutableArray<IOperation> Operations
}
internal abstract partial class BaseVariableDeclarationGroupOperation : Operation, IVariableDeclarationGroupOperation
{
internal BaseVariableDeclarationGroupOperation(VariableDeclarationKind declarationKind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit)
: base(OperationKind.VariableDeclarationGroup, semanticModel, syntax, type, constantValue, isImplicit)
{
DeclarationKind = declarationKind;
}
internal BaseVariableDeclarationGroupOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit)
: base(OperationKind.VariableDeclarationGroup, semanticModel, syntax, type, constantValue, isImplicit) { }
public abstract ImmutableArray<IVariableDeclarationOperation> Declarations { get; }
public VariableDeclarationKind DeclarationKind { get; }
public override IEnumerable<IOperation> Children
{
get
......@@ -2849,8 +2864,8 @@ public override IEnumerable<IOperation> Children
}
internal sealed partial class VariableDeclarationGroupOperation : BaseVariableDeclarationGroupOperation, IVariableDeclarationGroupOperation
{
internal VariableDeclarationGroupOperation(ImmutableArray<IVariableDeclarationOperation> declarations, VariableDeclarationKind declarationKind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit)
: base(declarationKind, semanticModel, syntax, type, constantValue, isImplicit)
internal VariableDeclarationGroupOperation(ImmutableArray<IVariableDeclarationOperation> declarations, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit)
: base(semanticModel, syntax, type, constantValue, isImplicit)
{
Declarations = SetParentOperation(declarations, this);
}
......@@ -2859,8 +2874,8 @@ internal VariableDeclarationGroupOperation(ImmutableArray<IVariableDeclarationOp
internal abstract partial class LazyVariableDeclarationGroupOperation : BaseVariableDeclarationGroupOperation, IVariableDeclarationGroupOperation
{
private ImmutableArray<IVariableDeclarationOperation> _lazyDeclarations;
internal LazyVariableDeclarationGroupOperation(VariableDeclarationKind declarationKind, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit)
: base(declarationKind, semanticModel, syntax, type, constantValue, isImplicit){ }
internal LazyVariableDeclarationGroupOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit)
: base(semanticModel, syntax, type, constantValue, isImplicit){ }
protected abstract ImmutableArray<IVariableDeclarationOperation> CreateDeclarations();
public override ImmutableArray<IVariableDeclarationOperation> Declarations
{
......@@ -8209,6 +8224,54 @@ public override IOperation Value
}
}
}
internal abstract partial class BaseUsingDeclarationOperation : Operation, IUsingDeclarationOperation
{
internal BaseUsingDeclarationOperation(bool isAsynchronous, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit)
: base(OperationKind.UsingDeclaration, semanticModel, syntax, type, constantValue, isImplicit)
{
IsAsynchronous = isAsynchronous;
}
public abstract IVariableDeclarationGroupOperation DeclarationGroup { get; }
public bool IsAsynchronous { get; }
public override IEnumerable<IOperation> Children
{
get
{
if (DeclarationGroup is object) yield return DeclarationGroup;
}
}
public override void Accept(OperationVisitor visitor) => visitor.VisitUsingDeclaration(this);
public override TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, TResult> visitor, TArgument argument) => visitor.VisitUsingDeclaration(this, argument);
}
internal sealed partial class UsingDeclarationOperation : BaseUsingDeclarationOperation, IUsingDeclarationOperation
{
internal UsingDeclarationOperation(IVariableDeclarationGroupOperation declarationGroup, bool isAsynchronous, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit)
: base(isAsynchronous, semanticModel, syntax, type, constantValue, isImplicit)
{
DeclarationGroup = SetParentOperation(declarationGroup, this);
}
public override IVariableDeclarationGroupOperation DeclarationGroup { get; }
}
internal abstract partial class LazyUsingDeclarationOperation : BaseUsingDeclarationOperation, IUsingDeclarationOperation
{
private IVariableDeclarationGroupOperation _lazyDeclarationGroup = s_unsetVariableDeclarationGroup;
internal LazyUsingDeclarationOperation(bool isAsynchronous, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit)
: base(isAsynchronous, semanticModel, syntax, type, constantValue, isImplicit){ }
protected abstract IVariableDeclarationGroupOperation CreateDeclarationGroup();
public override IVariableDeclarationGroupOperation DeclarationGroup
{
get
{
if (_lazyDeclarationGroup == s_unsetVariableDeclarationGroup)
{
IVariableDeclarationGroupOperation declarationGroup = CreateDeclarationGroup();
SetParentOperation(declarationGroup, this);
Interlocked.CompareExchange(ref _lazyDeclarationGroup, declarationGroup, s_unsetVariableDeclarationGroup);
}
return _lazyDeclarationGroup;
}
}
}
#endregion
#region Visitors
public abstract partial class OperationVisitor
......@@ -8330,6 +8393,7 @@ public abstract partial class OperationVisitor
internal virtual void VisitPlaceholder(IPlaceholderOperation operation) => DefaultVisit(operation);
internal virtual void VisitPointerIndirectionReference(IPointerIndirectionReferenceOperation operation) => DefaultVisit(operation);
internal virtual void VisitWith(IWithOperation operation) => DefaultVisit(operation);
public virtual void VisitUsingDeclaration(IUsingDeclarationOperation operation) => DefaultVisit(operation);
}
public abstract partial class OperationVisitor<TArgument, TResult>
{
......@@ -8450,6 +8514,7 @@ public abstract partial class OperationVisitor<TArgument, TResult>
internal virtual TResult VisitPlaceholder(IPlaceholderOperation operation, TArgument argument) => DefaultVisit(operation, argument);
internal virtual TResult VisitPointerIndirectionReference(IPointerIndirectionReferenceOperation operation, TArgument argument) => DefaultVisit(operation, argument);
internal virtual TResult VisitWith(IWithOperation operation, TArgument argument) => DefaultVisit(operation, argument);
public virtual TResult VisitUsingDeclaration(IUsingDeclarationOperation operation, TArgument argument) => DefaultVisit(operation, argument);
}
#endregion
}
......@@ -1368,12 +1368,11 @@ private void VisitStatements(ImmutableArray<IOperation> statements)
{
for (int i = 0; i < statements.Length; i++)
{
if (statements[i] is VariableDeclarationGroupOperation declarationGroup
&& declarationGroup.DeclarationKind != VariableDeclarationKind.Default)
if (statements[i] is IUsingDeclarationOperation usingDeclarationOperation)
{
// visit the using decl with the following statements
var followingStatements = ImmutableArray.Create(statements, i + 1, statements.Length - i - 1);
VisitUsingVariableDeclarationOperation(declarationGroup, followingStatements);
VisitUsingVariableDeclarationOperation(usingDeclarationOperation, followingStatements);
break;
}
else
......@@ -6833,30 +6832,27 @@ public override IOperation VisitSwitchExpression(ISwitchExpressionOperation oper
return GetCaptureReference(captureOutput, operation);
}
private void VisitUsingVariableDeclarationOperation(VariableDeclarationGroupOperation operation, ImmutableArray<IOperation> statements)
private void VisitUsingVariableDeclarationOperation(IUsingDeclarationOperation operation, ImmutableArray<IOperation> statements)
{
IOperation saveCurrentStatement = _currentStatement;
_currentStatement = operation;
StartVisitingStatement(operation);
var declarationKind = operation.DeclarationKind;
Debug.Assert(declarationKind == VariableDeclarationKind.Using || declarationKind == VariableDeclarationKind.AsynchronousUsing);
// a using statement introduces a 'logical' block after declaration, we synthesize one here in order to analyze it like a regular using
BlockOperation logicalBlock = new BlockOperation(
operations: statements,
locals: ImmutableArray<ILocalSymbol>.Empty,
operation.OwningSemanticModel,
((Operation)operation).OwningSemanticModel,
operation.Syntax,
operation.Type,
operation.ConstantValue,
isImplicit: true);
HandleUsingOperationParts(
resources: operation,
resources: operation.DeclarationGroup,
body: logicalBlock,
locals: ImmutableArray<ILocalSymbol>.Empty,
isAsynchronous: declarationKind == VariableDeclarationKind.AsynchronousUsing);
isAsynchronous: operation.IsAsynchronous);
FinishVisitingStatement(operation);
_currentStatement = saveCurrentStatement;
......@@ -6890,5 +6886,10 @@ public override IOperation VisitArgument(IArgumentOperation operation, int? capt
throw ExceptionUtilities.Unreachable;
}
public override IOperation VisitUsingDeclaration(IUsingDeclarationOperation operation, int? argument)
{
throw ExceptionUtilities.Unreachable;
}
}
}
......@@ -29,7 +29,7 @@ internal abstract class Operation : IOperation
protected static readonly IPatternOperation s_unsetPattern = new ConstantPatternOperation(
value: null, inputType: null, semanticModel: null, syntax: null, type: null, constantValue: default, isImplicit: true);
protected static readonly IVariableDeclarationGroupOperation s_unsetVariableDeclarationGroup = new VariableDeclarationGroupOperation(
declarations: ImmutableArray<IVariableDeclarationOperation>.Empty, declarationKind: VariableDeclarationKind.Default, semanticModel: null, syntax: null, type: null, constantValue: default, isImplicit: true);
declarations: ImmutableArray<IVariableDeclarationOperation>.Empty, semanticModel: null, syntax: null, type: null, constantValue: default, isImplicit: true);
protected static readonly IVariableInitializerOperation s_unsetVariableInitializer = new VariableInitializerOperation(
locals: ImmutableArray<ILocalSymbol>.Empty, value: null, semanticModel: null, syntax: null, type: null, constantValue: default, isImplicit: false);
private readonly SemanticModel _owningSemanticModelOpt;
......
......@@ -63,7 +63,7 @@ public override IOperation VisitBlock(IBlockOperation operation, object argument
public override IOperation VisitVariableDeclarationGroup(IVariableDeclarationGroupOperation operation, object argument)
{
return new VariableDeclarationGroupOperation(VisitArray(operation.Declarations), operation.DeclarationKind, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
return new VariableDeclarationGroupOperation(VisitArray(operation.Declarations), ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
}
public override IOperation VisitVariableDeclarator(IVariableDeclaratorOperation operation, object argument)
......@@ -655,5 +655,10 @@ public override IOperation VisitReDimClause(IReDimClauseOperation operation, obj
{
return new ReDimClauseOperation(Visit(operation.Operand), VisitArray(operation.DimensionSizes), ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
}
public override IOperation VisitUsingDeclaration(IUsingDeclarationOperation operation, object argument)
{
return new UsingDeclarationOperation(Visit(operation.DeclarationGroup), operation.IsAsynchronous, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
}
}
}
......@@ -76,13 +76,6 @@
</remarks>
</Comments>
</Property>
<Property Name="DeclarationKind" Type="VariableDeclarationKind">
<Comments>
<summary>
Specifies the <see cref="VariableDeclarationKind" /> of this declaration group.
</summary>
</Comments>
</Property>
</Node>
<Node Name="ISwitchOperation" Base="IOperation" ChildrenOrder="Value,Cases">
<Comments>
......@@ -2905,4 +2898,26 @@
</Comments>
</Property>
</Node>
<Node Name="IUsingDeclarationOperation" Base="IOperation">
<Comments>
<summary>
Represents using variable declaration, with scope spanning across the parent <see cref="IBlockOperation"/>.
<para>
Current Usage:
(1) C# using declaration
(1) C# asynchronous using declaration
</para>
</summary>
</Comments>
<Property Name="DeclarationGroup" Type="IVariableDeclarationGroupOperation">
<Comments>
<summary>The variables declared by this using declaration.</summary>
</Comments>
</Property>
<Property Name="IsAsynchronous" Type="bool">
<Comments>
<summary>True if this is an asynchronous using declaration.</summary>
</Comments>
</Property>
</Node>
</Tree>
\ 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.
namespace Microsoft.CodeAnalysis.Operations
{
public enum VariableDeclarationKind
{
/// <summary>
/// A declaration.
/// </summary>
Default = 0,
/// <summary>
/// A using declaration.
/// </summary>
Using = 1,
/// <summary>
/// An asynchronous using declaration.
/// </summary>
AsynchronousUsing = 2
}
}
......@@ -4,11 +4,10 @@ Microsoft.CodeAnalysis.ErrorLogOptions
Microsoft.CodeAnalysis.ErrorLogOptions.ErrorLogOptions(string path, Microsoft.CodeAnalysis.SarifVersion sarifVersion) -> void
Microsoft.CodeAnalysis.ErrorLogOptions.Path.get -> string
Microsoft.CodeAnalysis.ErrorLogOptions.SarifVersion.get -> Microsoft.CodeAnalysis.SarifVersion
Microsoft.CodeAnalysis.Operations.VariableDeclarationKind
Microsoft.CodeAnalysis.Operations.VariableDeclarationKind.AsynchronousUsing = 2 -> Microsoft.CodeAnalysis.Operations.VariableDeclarationKind
Microsoft.CodeAnalysis.Operations.VariableDeclarationKind.Default = 0 -> Microsoft.CodeAnalysis.Operations.VariableDeclarationKind
Microsoft.CodeAnalysis.Operations.VariableDeclarationKind.Using = 1 -> Microsoft.CodeAnalysis.Operations.VariableDeclarationKind
Microsoft.CodeAnalysis.Operations.IVariableDeclarationGroupOperation.DeclarationKind.get -> Microsoft.CodeAnalysis.Operations.VariableDeclarationKind
Microsoft.CodeAnalysis.OperationKind.UsingDeclaration = 108 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.Operations.IUsingDeclarationOperation
Microsoft.CodeAnalysis.Operations.IUsingDeclarationOperation.DeclarationGroup.get -> Microsoft.CodeAnalysis.Operations.IVariableDeclarationGroupOperation
Microsoft.CodeAnalysis.Operations.IUsingDeclarationOperation.IsAsynchronous.get -> bool
Microsoft.CodeAnalysis.SarifVersion
Microsoft.CodeAnalysis.SarifVersion.Default = 1 -> Microsoft.CodeAnalysis.SarifVersion
Microsoft.CodeAnalysis.SarifVersion.Latest = 2147483647 -> Microsoft.CodeAnalysis.SarifVersion
......@@ -23,5 +22,7 @@ abstract Microsoft.CodeAnalysis.DataFlowAnalysis.DefinitelyAssignedOnEntry.get -
abstract Microsoft.CodeAnalysis.DataFlowAnalysis.DefinitelyAssignedOnExit.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ISymbol>
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitPropertySubpattern(Microsoft.CodeAnalysis.Operations.IPropertySubpatternOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitRecursivePattern(Microsoft.CodeAnalysis.Operations.IRecursivePatternOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitUsingDeclaration(Microsoft.CodeAnalysis.Operations.IUsingDeclarationOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitPropertySubpattern(Microsoft.CodeAnalysis.Operations.IPropertySubpatternOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitRecursivePattern(Microsoft.CodeAnalysis.Operations.IRecursivePatternOperation operation, TArgument argument) -> TResult
\ No newline at end of file
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitRecursivePattern(Microsoft.CodeAnalysis.Operations.IRecursivePatternOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitUsingDeclaration(Microsoft.CodeAnalysis.Operations.IUsingDeclarationOperation operation, TArgument argument) -> TResult
\ No newline at end of file
......@@ -488,7 +488,6 @@ Namespace Microsoft.CodeAnalysis.Operations
Private Function GetUsingStatementDeclaration(resourceList As ImmutableArray(Of BoundLocalDeclarationBase), syntax As SyntaxNode) As IVariableDeclarationGroupOperation
Return New VariableDeclarationGroupOperation(
GetVariableDeclarationStatementVariables(resourceList),
VariableDeclarationKind.Default,
_semanticModel,
syntax,
type:=Nothing,
......
......@@ -1116,7 +1116,7 @@ _operationFactory.CreateFromArray(Of BoundExpression, IOperation)(_boundForToLoo
Private ReadOnly _localDeclarations As IBoundLocalDeclarations
Friend Sub New(operationFactory As VisualBasicOperationFactory, localDeclarations As IBoundLocalDeclarations, semanticModel As SemanticModel, syntax As SyntaxNode, type As ITypeSymbol, constantValue As [Optional](Of Object), isImplicit As Boolean)
MyBase.New(VariableDeclarationKind.Default, semanticModel, syntax, type, constantValue, isImplicit)
MyBase.New(semanticModel, syntax, type, constantValue, isImplicit)
_operationFactory = operationFactory
_localDeclarations = localDeclarations
End Sub
......
......@@ -451,13 +451,21 @@ public override void VisitBlock(IBlockOperation operation)
public override void VisitVariableDeclarationGroup(IVariableDeclarationGroupOperation operation)
{
var variablesCountStr = $"{operation.Declarations.Length} declarations";
var declarationKind = operation.DeclarationKind != VariableDeclarationKind.Default ? $", DeclarationKind: {operation.DeclarationKind}" : string.Empty;
LogString($"{nameof(IVariableDeclarationGroupOperation)} ({variablesCountStr}{declarationKind})");
LogString($"{nameof(IVariableDeclarationGroupOperation)} ({variablesCountStr})");
LogCommonPropertiesAndNewLine(operation);
base.VisitVariableDeclarationGroup(operation);
}
public override void VisitUsingDeclaration(IUsingDeclarationOperation operation)
{
LogString($"{nameof(IUsingDeclarationOperation)}");
LogString($"(IsAsynchronous: {operation.IsAsynchronous})");
LogCommonPropertiesAndNewLine(operation);
Visit(operation.DeclarationGroup, "DeclarationGroup");
}
public override void VisitVariableDeclarator(IVariableDeclaratorOperation operation)
{
LogString($"{nameof(IVariableDeclaratorOperation)} (");
......
......@@ -84,7 +84,6 @@ public override void VisitBlock(IBlockOperation operation)
public override void VisitVariableDeclarationGroup(IVariableDeclarationGroupOperation operation)
{
Assert.Equal(OperationKind.VariableDeclarationGroup, operation.Kind);
Assert.IsType(typeof(VariableDeclarationKind), operation.DeclarationKind);
AssertEx.Equal(operation.Declarations, operation.Children);
}
......@@ -1468,5 +1467,16 @@ public override void VisitReDimClause(IReDimClauseOperation operation)
Assert.Equal(OperationKind.ReDimClause, operation.Kind);
AssertEx.Equal(SpecializedCollections.SingletonEnumerable(operation.Operand).Concat(operation.DimensionSizes), operation.Children);
}
public override void VisitUsingDeclaration(IUsingDeclarationOperation operation)
{
Assert.NotNull(operation.DeclarationGroup);
AssertEx.Equal(SpecializedCollections.SingletonEnumerable(operation.DeclarationGroup), operation.Children);
Assert.True(operation.DeclarationGroup.IsImplicit);
Assert.Null(operation.Type);
Assert.False(operation.ConstantValue.HasValue);
_ = operation.IsAsynchronous;
_ = operation.IsImplicit;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册