提交 ee706b92 编写于 作者: M Manish Vasani

Add IOperation support for VB ReDim statement

Also fix the IDE helper to get value usage info, which fixes the MakeFieldReadOnlyAnalyzer

Fixes #29373
Fixes #30175
上级 d681f7f5
......@@ -7053,4 +7053,126 @@ internal sealed partial class LazyNoPiaObjectCreationOperation : BaseNoPiaObject
}
public override IObjectOrCollectionInitializerOperation Initializer => SetParentOperation(_lazyInitializer.Value, this);
}
internal abstract class BaseReDimOperation : Operation, IReDimOperation
{
protected BaseReDimOperation(bool preserve, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(OperationKind.ReDim, semanticModel, syntax, type, constantValue, isImplicit)
{
Preserve = preserve;
}
public abstract ImmutableArray<IReDimClauseOperation> Clauses { get; }
public bool Preserve { get; }
public sealed override IEnumerable<IOperation> Children
{
get
{
foreach (var clause in Clauses)
{
yield return clause;
}
}
}
public sealed override void Accept(OperationVisitor visitor)
{
visitor.VisitReDim(this);
}
public sealed override TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, TResult> visitor, TArgument argument)
{
return visitor.VisitReDim(this, argument);
}
}
internal sealed class ReDimOperation : BaseReDimOperation
{
public ReDimOperation(ImmutableArray<IReDimClauseOperation> clauses, bool preserve, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(preserve, semanticModel, syntax, type, constantValue, isImplicit)
{
Clauses = SetParentOperation(clauses, this);
}
public override ImmutableArray<IReDimClauseOperation> Clauses { get; }
}
internal sealed class LazyReDimOperation : BaseReDimOperation
{
private readonly Lazy<ImmutableArray<IReDimClauseOperation>> _lazyClauses;
public LazyReDimOperation(Lazy<ImmutableArray<IReDimClauseOperation>> clauses, bool preserve, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(preserve, semanticModel, syntax, type, constantValue, isImplicit)
{
_lazyClauses = clauses;
}
public override ImmutableArray<IReDimClauseOperation> Clauses => SetParentOperation(_lazyClauses.Value, this);
}
internal abstract class BaseReDimClauseOperation : Operation, IReDimClauseOperation
{
protected BaseReDimClauseOperation(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(OperationKind.ReDimClause, semanticModel, syntax, type, constantValue, isImplicit)
{
}
public abstract IOperation Operand { get; }
public abstract ImmutableArray<IOperation> Indices { get; }
public sealed override IEnumerable<IOperation> Children
{
get
{
Debug.Assert(Operand != null);
yield return Operand;
foreach (var index in Indices)
{
Debug.Assert(index != null);
yield return index;
}
}
}
public sealed override void Accept(OperationVisitor visitor)
{
visitor.VisitReDimClause(this);
}
public sealed override TResult Accept<TArgument, TResult>(OperationVisitor<TArgument, TResult> visitor, TArgument argument)
{
return visitor.VisitReDimClause(this, argument);
}
}
internal sealed class ReDimClauseOperation : BaseReDimClauseOperation
{
public ReDimClauseOperation(IOperation operand, ImmutableArray<IOperation> indices, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(semanticModel, syntax, type, constantValue, isImplicit)
{
Operand = SetParentOperation(operand, this);
Indices = SetParentOperation(indices, this);
}
public override IOperation Operand { get; }
public override ImmutableArray<IOperation> Indices { get; }
}
internal sealed class LazyReDimClauseOperation : BaseReDimClauseOperation
{
private readonly Lazy<IOperation> _lazyOperand;
private readonly Lazy<ImmutableArray<IOperation>> _lazyIndices;
public LazyReDimClauseOperation(Lazy<IOperation> lazyOperand, Lazy<ImmutableArray<IOperation>> lazyIndices, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional<object> constantValue, bool isImplicit) :
base(semanticModel, syntax, type, constantValue, isImplicit)
{
_lazyOperand = lazyOperand;
_lazyIndices = lazyIndices;
}
public override IOperation Operand => SetParentOperation(_lazyOperand.Value, this);
public override ImmutableArray<IOperation> Indices => SetParentOperation(_lazyIndices.Value, this);
}
}
......@@ -6500,6 +6500,41 @@ IOperation visitInvalidOperationExpression(IInvalidOperation invalidOperation)
}
}
public override IOperation VisitReDim(IReDimOperation operation, int? argument)
{
// We visit and rewrite the ReDim clauses in two phases:
// 1. Visit all the clause operands and indices and push them onto the eval stack.
// 2. Traverse the parts in reverse order, popping the indices and the operands from the eval stack for producing visited clauses.
EvalStackFrame frame = PushStackFrame();
foreach (var clause in operation.Clauses)
{
PushOperand(Visit(clause.Operand));
VisitAndPushArray(clause.Indices);
}
var clausesBuilder = ArrayBuilder<IReDimClauseOperation>.GetInstance(operation.Clauses.Length);
for (int i = operation.Clauses.Length - 1; i >= 0; i--)
{
IReDimClauseOperation clause = operation.Clauses[i];
var visitedIndices = PopArray(clause.Indices);
var visitedOperand = PopOperand();
var rewrittenClause = new ReDimClauseOperation(visitedOperand, visitedIndices, semanticModel: null,
clause.Syntax, clause.Type, clause.ConstantValue, IsImplicit(clause));
clausesBuilder.Add(rewrittenClause);
}
clausesBuilder.ReverseContents();
PopStackFrame(frame);
return new ReDimOperation(clausesBuilder.ToImmutableAndFree(), operation.Preserve,
semanticModel: null, operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation));
}
public override IOperation VisitReDimClause(IReDimClauseOperation operation, int? argument)
{
throw ExceptionUtilities.Unreachable;
}
public override IOperation VisitTranslatedQuery(ITranslatedQueryOperation operation, int? captureIdForResult)
{
return new TranslatedQueryExpression(Visit(operation.Operation), semanticModel: null, operation.Syntax, operation.Type, operation.ConstantValue, IsImplicit(operation));
......
// 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.Operations
{
/// <summary>
/// Represents an individual clause of an <see cref="IReDimOperation"/> to re-allocate storage space for a single array variable.
/// <para>
/// Current usage:
/// (1) VB ReDim clause.
/// </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 IReDimClauseOperation : IOperation
{
/// <summary>
/// Operand whose storage space needs to be re-allocated.
/// </summary>
IOperation Operand { get; }
/// <summary>
/// Bounds of each dimension of the re-allocated array.
/// </summary>
ImmutableArray<IOperation> Indices { 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.
using System.Collections.Immutable;
namespace Microsoft.CodeAnalysis.Operations
{
/// <summary>
/// Represents the ReDim operation to re-allocate storage space for array variables.
/// <para>
/// Current usage:
/// (1) VB ReDim statement.
/// </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 IReDimOperation : IOperation
{
/// <summary>
/// Individual clauses of the ReDim operation.
/// </summary>
ImmutableArray<IReDimClauseOperation> Clauses { get; }
/// <summary>
/// Modifier used to preserve the data in the existing array when you change the size of only the last dimension.
/// </summary>
bool Preserve { get; }
}
}
......@@ -586,5 +586,15 @@ public override IOperation VisitStaticLocalInitializationSemaphore(IStaticLocalI
{
throw ExceptionUtilities.Unreachable;
}
public override IOperation VisitReDim(IReDimOperation operation, object argument)
{
return new ReDimOperation(VisitArray(operation.Clauses), operation.Preserve, ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
}
public override IOperation VisitReDimClause(IReDimClauseOperation operation, object argument)
{
return new ReDimClauseOperation(Visit(operation.Operand), VisitArray(operation.Indices), ((Operation)operation).OwningSemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit);
}
}
}
......@@ -209,6 +209,11 @@ public enum OperationKind
/// <summary>Indicates an <see cref="ICoalesceAssignmentOperation"/>.</summary>
CoalesceAssignment = 0x61,
/// <summary>Indicates an <see cref="IReDimOperation"/>.</summary>
ReDim = 0x62,
/// <summary>Indicates an <see cref="IReDimClauseOperation"/>.</summary>
ReDimClause = 0x63,
// /// <summary>Indicates an <see cref="IFixedOperation"/>.</summary>
// https://github.com/dotnet/roslyn/issues/21281
//Fixed = <TBD>,
......
......@@ -564,6 +564,16 @@ public virtual void VisitStaticLocalInitializationSemaphore(IStaticLocalInitiali
{
DefaultVisit(operation);
}
public virtual void VisitReDim(IReDimOperation operation)
{
DefaultVisit(operation);
}
public virtual void VisitReDimClause(IReDimClauseOperation operation)
{
DefaultVisit(operation);
}
}
/// <summary>
......@@ -1132,5 +1142,15 @@ public virtual TResult VisitStaticLocalInitializationSemaphore(IStaticLocalIniti
{
return DefaultVisit(operation, argument);
}
public virtual TResult VisitReDim(IReDimOperation operation, TArgument argument)
{
return DefaultVisit(operation, argument);
}
public virtual TResult VisitReDimClause(IReDimClauseOperation operation, TArgument argument)
{
return DefaultVisit(operation, argument);
}
}
}
......@@ -29,8 +29,16 @@ Microsoft.CodeAnalysis.FlowAnalysis.IStaticLocalInitializationSemaphoreOperation
Microsoft.CodeAnalysis.FlowAnalysis.IStaticLocalInitializationSemaphoreOperation.Local.get -> Microsoft.CodeAnalysis.ILocalSymbol
Microsoft.CodeAnalysis.IOperation.SemanticModel.get -> Microsoft.CodeAnalysis.SemanticModel
Microsoft.CodeAnalysis.OperationKind.CoalesceAssignment = 97 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.ReDim = 98 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.ReDimClause = 99 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.Operations.CommonConversion.IsImplicit.get -> bool
Microsoft.CodeAnalysis.Operations.ICoalesceAssignmentOperation
Microsoft.CodeAnalysis.Operations.IReDimClauseOperation
Microsoft.CodeAnalysis.Operations.IReDimClauseOperation.Indices.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.IOperation>
Microsoft.CodeAnalysis.Operations.IReDimClauseOperation.Operand.get -> Microsoft.CodeAnalysis.IOperation
Microsoft.CodeAnalysis.Operations.IReDimOperation
Microsoft.CodeAnalysis.Operations.IReDimOperation.Clauses.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Operations.IReDimClauseOperation>
Microsoft.CodeAnalysis.Operations.IReDimOperation.Preserve.get -> bool
abstract Microsoft.CodeAnalysis.Compilation.ClassifyCommonConversion(Microsoft.CodeAnalysis.ITypeSymbol source, Microsoft.CodeAnalysis.ITypeSymbol destination) -> Microsoft.CodeAnalysis.Operations.CommonConversion
abstract Microsoft.CodeAnalysis.Compilation.ContainsSymbolsWithName(string name, Microsoft.CodeAnalysis.SymbolFilter filter = Microsoft.CodeAnalysis.SymbolFilter.TypeAndMember, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> bool
abstract Microsoft.CodeAnalysis.Compilation.GetSymbolsWithName(string name, Microsoft.CodeAnalysis.SymbolFilter filter = Microsoft.CodeAnalysis.SymbolFilter.TypeAndMember, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.ISymbol>
......@@ -149,12 +157,16 @@ virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitCoalesceAssignme
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitFlowCapture(Microsoft.CodeAnalysis.FlowAnalysis.IFlowCaptureOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitFlowCaptureReference(Microsoft.CodeAnalysis.FlowAnalysis.IFlowCaptureReferenceOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitIsNull(Microsoft.CodeAnalysis.FlowAnalysis.IIsNullOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitReDim(Microsoft.CodeAnalysis.Operations.IReDimOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitReDimClause(Microsoft.CodeAnalysis.Operations.IReDimClauseOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitStaticLocalInitializationSemaphore(Microsoft.CodeAnalysis.FlowAnalysis.IStaticLocalInitializationSemaphoreOperation operation) -> void
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitCaughtException(Microsoft.CodeAnalysis.FlowAnalysis.ICaughtExceptionOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitCoalesceAssignment(Microsoft.CodeAnalysis.Operations.ICoalesceAssignmentOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitFlowCapture(Microsoft.CodeAnalysis.FlowAnalysis.IFlowCaptureOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitFlowCaptureReference(Microsoft.CodeAnalysis.FlowAnalysis.IFlowCaptureReferenceOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitIsNull(Microsoft.CodeAnalysis.FlowAnalysis.IIsNullOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitReDim(Microsoft.CodeAnalysis.Operations.IReDimOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitReDimClause(Microsoft.CodeAnalysis.Operations.IReDimClauseOperation operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Operations.OperationVisitor<TArgument, TResult>.VisitStaticLocalInitializationSemaphore(Microsoft.CodeAnalysis.FlowAnalysis.IStaticLocalInitializationSemaphoreOperation operation, TArgument argument) -> TResult
Microsoft.CodeAnalysis.FlowAnalysis.IFlowAnonymousFunctionOperation
Microsoft.CodeAnalysis.FlowAnalysis.IFlowAnonymousFunctionOperation.Symbol.get -> Microsoft.CodeAnalysis.IMethodSymbol
......
......@@ -53,22 +53,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Property
End Class
Partial Friend Class BoundRedimStatement
Protected Overrides ReadOnly Property Children As ImmutableArray(Of BoundNode)
Get
Return StaticCast(Of BoundNode).From(Me.Clauses)
End Get
End Property
End Class
Partial Friend Class BoundRedimClause
Protected Overrides ReadOnly Property Children As ImmutableArray(Of BoundNode)
Get
Return StaticCast(Of BoundNode).From(Me.Indices.Insert(0, Me.Operand))
End Get
End Property
End Class
Partial Friend Class BoundEraseStatement
Protected Overrides ReadOnly Property Children As ImmutableArray(Of BoundNode)
Get
......
......@@ -294,6 +294,8 @@ Namespace Microsoft.CodeAnalysis.Operations
Return Create(DirectCast(boundNode, BoundBadVariable).Expression)
Case BoundKind.NullableIsTrueOperator
Return CreateBoundNullableIsTrueOperator(DirectCast(boundNode, BoundNullableIsTrueOperator))
Case BoundKind.RedimStatement
Return CreateBoundReDimOperation(DirectCast(boundNode, BoundRedimStatement))
Case BoundKind.AddressOfOperator,
BoundKind.ArrayLiteral,
......@@ -309,8 +311,6 @@ Namespace Microsoft.CodeAnalysis.Operations
BoundKind.OnErrorStatement,
BoundKind.PropertyGroup,
BoundKind.RangeVariable,
BoundKind.RedimClause,
BoundKind.RedimStatement,
BoundKind.ResumeStatement,
BoundKind.TypeAsValueExpression,
BoundKind.TypeExpression,
......@@ -1765,6 +1765,32 @@ Namespace Microsoft.CodeAnalysis.Operations
Return New LazyInvalidOperation(children, _semanticModel, syntax, type, constantValue, isImplicit)
End If
End Function
Private Function CreateBoundReDimOperation(boundRedimStatement As BoundRedimStatement) As IReDimOperation
Dim preserve As Boolean = boundRedimStatement.Syntax.Kind = SyntaxKind.ReDimPreserveStatement
Dim clauses As Lazy(Of ImmutableArray(Of IReDimClauseOperation)) = New Lazy(Of ImmutableArray(Of IReDimClauseOperation))(
Function()
Return boundRedimStatement.Clauses.SelectAsArray(Function(n)
Debug.Assert(preserve = n.Preserve)
Return CreateBoundReDimClauseOperation(n)
End Function)
End Function)
Dim syntax As SyntaxNode = boundRedimStatement.Syntax
Dim type As ITypeSymbol = Nothing
Dim constantValue As [Optional](Of Object) = Nothing
Dim isImplicit As Boolean = boundRedimStatement.WasCompilerGenerated
Return New LazyReDimOperation(clauses, preserve, _semanticModel, syntax, type, constantValue, isImplicit)
End Function
Private Function CreateBoundReDimClauseOperation(boundRedimClause As BoundRedimClause) As IReDimClauseOperation
Dim operand As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundRedimClause.Operand))
Dim indices As Lazy(Of ImmutableArray(Of IOperation)) = New Lazy(Of ImmutableArray(Of IOperation))(Function() boundRedimClause.Indices.SelectAsArray(Function(n) Create(n)))
Dim syntax As SyntaxNode = boundRedimClause.Syntax
Dim type As ITypeSymbol = Nothing
Dim constantValue As [Optional](Of Object) = Nothing
Dim isImplicit As Boolean = boundRedimClause.WasCompilerGenerated
Return New LazyReDimClauseOperation(operand, indices, _semanticModel, syntax, type, constantValue, isImplicit)
End Function
End Class
End Namespace
......
......@@ -770,11 +770,12 @@ Friend Class [Class]
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None, Type: null) (Syntax: 'ReDim intArray(x, x, x)')
Children(1):
IOperation: (OperationKind.None, Type: null) (Syntax: 'intArray(x, x, x)')
Children(4):
ILocalReferenceOperation: intArray (OperationKind.LocalReference, Type: System.Int32(,,)) (Syntax: 'intArray')
IReDimOperation (OperationKind.ReDim, Type: null) (Syntax: 'ReDim intArray(x, x, x)')
Clauses(1):
IReDimClauseOperation (OperationKind.ReDimClause, Type: null) (Syntax: 'intArray(x, x, x)')
Operand:
ILocalReferenceOperation: intArray (OperationKind.LocalReference, Type: System.Int32(,,)) (Syntax: 'intArray')
Indices(3):
IBinaryOperation (BinaryOperatorKind.Add, Checked) (OperationKind.BinaryOperator, Type: System.Int32, IsImplicit) (Syntax: 'x')
Left:
IParameterReferenceOperation: x (OperationKind.ParameterReference, Type: System.Int32) (Syntax: 'x')
......
......@@ -892,6 +892,34 @@ End Class",
Sub Goo()
_goo = 0
End Sub
End Class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeFieldReadonly)>
Public Async Function FieldIsRedimOperand() As Task
Await TestMissingInRegularAndScriptAsync(
"Class C
Private [|_goo()|] As Integer
Private Sub M()
Redim _goo(5)
End Sub
End Class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsMakeFieldReadonly)>
Public Async Function FieldIsRedimIndex() As Task
Await TestInRegularAndScriptAsync(
"Class C
Private [|_goo()|] As Integer
Private Sub M(a() As Integer)
Redim a(_goo)
End Sub
End Class",
"Class C
Private ReadOnly _goo() As Integer
Private Sub M(a() As Integer)
Redim a(_goo)
End Sub
End Class")
End Function
End Class
......
......@@ -1764,6 +1764,8 @@ private static bool CanBeInControlFlowGraph(IOperation n)
case OperationKind.CaughtException:
case OperationKind.StaticLocalInitializationSemaphore:
case OperationKind.Discard:
case OperationKind.ReDim:
case OperationKind.ReDimClause:
return true;
}
......
......@@ -109,7 +109,7 @@ private static string GetSnippetFromSyntax(SyntaxNode syntax)
return "null";
}
var text = syntax.ToString();
var text = syntax.ToString().Trim(Environment.NewLine.ToCharArray());
var lines = text.Split(new[] { Environment.NewLine, "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries).Select(l => l.Trim()).ToArray();
if (lines.Length <= 1 && text.Length < 25)
{
......@@ -1794,6 +1794,25 @@ public override void VisitStaticLocalInitializationSemaphore(IStaticLocalInitial
LogCommonPropertiesAndNewLine(operation);
}
public override void VisitReDim(IReDimOperation operation)
{
LogString(nameof(IReDimOperation));
if (operation.Preserve)
{
LogString(" (Preserve)");
}
LogCommonPropertiesAndNewLine(operation);
VisitArray(operation.Clauses, "Clauses", logElementCount: true);
}
public override void VisitReDimClause(IReDimClauseOperation operation)
{
LogString(nameof(IReDimClauseOperation));
LogCommonPropertiesAndNewLine(operation);
Visit(operation.Operand, "Operand");
VisitArray(operation.Indices, "Indices", logElementCount: true);
}
#endregion
}
}
......@@ -11,6 +11,7 @@
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.VisualBasic;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Test.Utilities
......@@ -1295,5 +1296,24 @@ public override void VisitStaticLocalInitializationSemaphore(IStaticLocalInitial
Assert.NotNull(operation.Local);
Assert.True(operation.Local.IsStatic);
}
public override void VisitReDim(IReDimOperation operation)
{
Assert.Equal(OperationKind.ReDim, operation.Kind);
AssertEx.Equal(operation.Clauses, operation.Children);
var preserve = operation.Preserve;
}
public override void VisitReDimClause(IReDimClauseOperation operation)
{
Assert.Equal(OperationKind.ReDimClause, operation.Kind);
Assert.NotNull(operation.Operand);
foreach (var index in operation.Indices)
{
Assert.NotNull(index);
}
AssertEx.Equal(SpecializedCollections.SingletonEnumerable(operation.Operand).Concat(operation.Indices), operation.Children);
}
}
}
......@@ -85,6 +85,11 @@ public static ValueUsageInfo GetValueUsageInfo(this IOperation operation)
return ValueUsageInfo.Read;
}
}
else if (operation.Parent is IReDimClauseOperation reDimClauseOperation &&
reDimClauseOperation.Operand == operation)
{
return ValueUsageInfo.Write;
}
else if (IsInLeftOfDeconstructionAssignment(operation))
{
return ValueUsageInfo.Write;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册