173 lines
4.9 KiB
C#
173 lines
4.9 KiB
C#
using System.Collections.Generic;
|
|
using System.Collections.Immutable;
|
|
using System.Linq;
|
|
using Microsoft.CodeAnalysis.CSharp.Symbols;
|
|
using Roslyn.Utilities;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp;
|
|
|
|
internal class VariablesDeclaredWalker : AbstractRegionControlFlowPass
|
|
{
|
|
private HashSet<Symbol> _variablesDeclared = new HashSet<Symbol>();
|
|
|
|
internal static IEnumerable<Symbol> Analyze(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion)
|
|
{
|
|
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
|
VariablesDeclaredWalker variablesDeclaredWalker = new VariablesDeclaredWalker(compilation, member, node, firstInRegion, lastInRegion);
|
|
try
|
|
{
|
|
bool badRegion = false;
|
|
variablesDeclaredWalker.Analyze(ref badRegion);
|
|
IEnumerable<Symbol> result;
|
|
if (!badRegion)
|
|
{
|
|
IEnumerable<Symbol> variablesDeclared = variablesDeclaredWalker._variablesDeclared;
|
|
result = variablesDeclared;
|
|
}
|
|
else
|
|
{
|
|
result = SpecializedCollections.EmptyEnumerable<Symbol>();
|
|
}
|
|
return result;
|
|
}
|
|
finally
|
|
{
|
|
variablesDeclaredWalker.Free();
|
|
}
|
|
}
|
|
|
|
internal VariablesDeclaredWalker(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion)
|
|
: base(compilation, member, node, firstInRegion, lastInRegion)
|
|
{
|
|
}
|
|
|
|
protected override void Free()
|
|
{
|
|
base.Free();
|
|
_variablesDeclared = null;
|
|
}
|
|
|
|
public override void VisitPattern(BoundPattern pattern)
|
|
{
|
|
base.VisitPattern(pattern);
|
|
NoteDeclaredPatternVariables(pattern);
|
|
}
|
|
|
|
protected override void VisitSwitchSection(BoundSwitchSection node, bool isLastSection)
|
|
{
|
|
ImmutableArray<BoundSwitchLabel>.Enumerator enumerator = node.SwitchLabels.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
BoundSwitchLabel current = enumerator.Current;
|
|
NoteDeclaredPatternVariables(current.Pattern);
|
|
}
|
|
base.VisitSwitchSection(node, isLastSection);
|
|
}
|
|
|
|
private void NoteDeclaredPatternVariables(BoundPattern pattern)
|
|
{
|
|
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0025: Invalid comparison between Unknown and I4
|
|
if (base.IsInside && pattern is BoundObjectPattern boundObjectPattern)
|
|
{
|
|
Symbol? variable = boundObjectPattern.Variable;
|
|
if ((object)variable != null && (int)variable.Kind == 8)
|
|
{
|
|
_variablesDeclared.Add(boundObjectPattern.Variable);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override BoundNode VisitLocalDeclaration(BoundLocalDeclaration node)
|
|
{
|
|
if (base.IsInside)
|
|
{
|
|
_variablesDeclared.Add(node.LocalSymbol);
|
|
}
|
|
return base.VisitLocalDeclaration(node);
|
|
}
|
|
|
|
public override BoundNode VisitLambda(BoundLambda node)
|
|
{
|
|
if (base.IsInside && !node.WasCompilerGenerated)
|
|
{
|
|
ImmutableArray<ParameterSymbol>.Enumerator enumerator = node.Symbol.Parameters.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
ParameterSymbol current = enumerator.Current;
|
|
_variablesDeclared.Add(current);
|
|
}
|
|
}
|
|
return base.VisitLambda(node);
|
|
}
|
|
|
|
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
|
|
{
|
|
if (base.IsInside && !node.WasCompilerGenerated)
|
|
{
|
|
ImmutableArray<ParameterSymbol>.Enumerator enumerator = node.Symbol.Parameters.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
ParameterSymbol current = enumerator.Current;
|
|
_variablesDeclared.Add(current);
|
|
}
|
|
}
|
|
return base.VisitLocalFunctionStatement(node);
|
|
}
|
|
|
|
public override void VisitForEachIterationVariables(BoundForEachStatement node)
|
|
{
|
|
if (!base.IsInside)
|
|
{
|
|
return;
|
|
}
|
|
BoundDeconstructionAssignmentOperator boundDeconstructionAssignmentOperator = node.DeconstructionOpt?.DeconstructionAssignment;
|
|
if (boundDeconstructionAssignmentOperator == null)
|
|
{
|
|
ISetExtensions.AddAll<Symbol>((ISet<Symbol>)_variablesDeclared, (IEnumerable<Symbol>)node.IterationVariables);
|
|
return;
|
|
}
|
|
boundDeconstructionAssignmentOperator.Left.VisitAllElements(delegate(BoundExpression x, VariablesDeclaredWalker self)
|
|
{
|
|
self.Visit(x);
|
|
}, this);
|
|
}
|
|
|
|
protected override void VisitCatchBlock(BoundCatchBlock catchBlock, ref LocalState finallyState)
|
|
{
|
|
if (base.IsInside)
|
|
{
|
|
LocalSymbol localSymbol = catchBlock.Locals.FirstOrDefault();
|
|
if ((object)localSymbol != null && localSymbol.DeclarationKind == LocalDeclarationKind.CatchVariable)
|
|
{
|
|
_variablesDeclared.Add(localSymbol);
|
|
}
|
|
}
|
|
base.VisitCatchBlock(catchBlock, ref finallyState);
|
|
}
|
|
|
|
public override BoundNode VisitQueryClause(BoundQueryClause node)
|
|
{
|
|
if (base.IsInside && (object)node.DefinedSymbol != null)
|
|
{
|
|
_variablesDeclared.Add(node.DefinedSymbol);
|
|
}
|
|
return base.VisitQueryClause(node);
|
|
}
|
|
|
|
protected override void VisitLvalue(BoundLocal node)
|
|
{
|
|
VisitLocal(node);
|
|
}
|
|
|
|
public override BoundNode VisitLocal(BoundLocal node)
|
|
{
|
|
if (base.IsInside && node.DeclarationKind != BoundLocalDeclarationKind.None)
|
|
{
|
|
_variablesDeclared.Add(node.LocalSymbol);
|
|
}
|
|
return null;
|
|
}
|
|
}
|