|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable disable
using System.Collections.Generic;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Debugging;
internal sealed partial class CSharpProximityExpressionsService
{
private sealed class RelevantExpressionsCollector(bool includeDeclarations, IList<string> expressions) : CSharpSyntaxVisitor
{
private readonly bool _includeDeclarations = includeDeclarations;
private readonly IList<string> _expressions = expressions;
public override void VisitLabeledStatement(LabeledStatementSyntax node)
=> AddRelevantExpressions(node.Statement, _expressions, _includeDeclarations);
public override void VisitExpressionStatement(ExpressionStatementSyntax node)
=> AddExpressionTerms(node.Expression, _expressions);
public override void VisitReturnStatement(ReturnStatementSyntax node)
=> AddExpressionTerms(node.Expression, _expressions);
public override void VisitThrowStatement(ThrowStatementSyntax node)
=> AddExpressionTerms(node.Expression, _expressions);
public override void VisitLocalDeclarationStatement(LocalDeclarationStatementSyntax node)
{
// Here, we collect expression expressions from any/all initialization expressions
AddVariableExpressions(node.Declaration.Variables, _expressions);
}
public override void VisitDoStatement(DoStatementSyntax node)
=> AddExpressionTerms(node.Condition, _expressions);
public override void VisitLockStatement(LockStatementSyntax node)
=> AddExpressionTerms(node.Expression, _expressions);
public override void VisitWhileStatement(WhileStatementSyntax node)
=> AddExpressionTerms(node.Condition, _expressions);
public override void VisitIfStatement(IfStatementSyntax node)
=> AddExpressionTerms(node.Condition, _expressions);
public override void VisitForStatement(ForStatementSyntax node)
{
if (node.Declaration != null)
{
AddVariableExpressions(node.Declaration.Variables, _expressions);
}
node.Initializers.Do(i => AddExpressionTerms(i, _expressions));
AddExpressionTerms(node.Condition, _expressions);
node.Incrementors.Do(i => AddExpressionTerms(i, _expressions));
}
public override void VisitForEachStatement(ForEachStatementSyntax node)
{
_expressions.Add(node.Identifier.ValueText);
AddExpressionTerms(node.Expression, _expressions);
}
public override void VisitForEachVariableStatement(ForEachVariableStatementSyntax node)
{
AddVariableExpressions(node.Variable, _expressions);
AddExpressionTerms(node.Expression, _expressions);
}
public override void VisitUsingStatement(UsingStatementSyntax node)
{
if (node.Declaration != null)
{
AddVariableExpressions(node.Declaration.Variables, _expressions);
}
AddExpressionTerms(node.Expression, _expressions);
}
public override void VisitSwitchStatement(SwitchStatementSyntax node)
=> AddExpressionTerms(node.Expression, _expressions);
private void AddVariableExpressions(
SeparatedSyntaxList<VariableDeclaratorSyntax> declarators,
IList<string> expressions)
{
foreach (var declarator in declarators)
{
if (_includeDeclarations)
{
expressions.Add(declarator.Identifier.ValueText);
}
if (declarator.Initializer != null)
{
AddExpressionTerms(declarator.Initializer.Value, expressions);
}
}
}
private void AddVariableExpressions(
ExpressionSyntax component,
IList<string> expressions)
{
if (!_includeDeclarations)
return;
switch (component.Kind())
{
case SyntaxKind.TupleExpression:
{
var t = (TupleExpressionSyntax)component;
foreach (var a in t.Arguments)
{
AddVariableExpressions(a.Expression, expressions);
}
break;
}
case SyntaxKind.DeclarationExpression:
{
var t = (DeclarationExpressionSyntax)component;
AddVariableExpressions(t.Designation, expressions);
break;
}
}
}
private void AddVariableExpressions(
VariableDesignationSyntax component,
IList<string> expressions)
{
if (!_includeDeclarations)
return;
switch (component.Kind())
{
case SyntaxKind.ParenthesizedVariableDesignation:
{
var t = (ParenthesizedVariableDesignationSyntax)component;
foreach (var v in t.Variables)
AddVariableExpressions(v, expressions);
break;
}
case SyntaxKind.SingleVariableDesignation:
{
var t = (SingleVariableDesignationSyntax)component;
expressions.Add(t.Identifier.ValueText);
break;
}
}
}
}
}
|