使用 Roslyn 拆分表达式语句
Splitting the Expression statements with Roslyn
我正在开发一个重述 CSharp
代码的应用程序。我用 Roslyn
来做这个。我遇到了 splitting expressions
.
的问题
示例类
class Program
{
static void Main(string[] args)
{
float floatVariable = 20;
Int16 intVariable = 10;
string str = "School";
Console.Write(str + floatVariable.ToString() + intVariable.ToString()); // Facing problem with this statement
}
}
我正在使用的示例代码
string code = new StreamReader(classPath).ReadToEnd();
var syntaxTree = CSharpSyntaxTree.ParseText(code);
var syntaxRoot = syntaxTree.GetRoot();
//This will get the method and local variables declared inside the method
var MyMethods = syntaxRoot.DescendantNodes().OfType<MethodDeclarationSyntax>();
foreach (MethodDeclarationSyntax mds in MyMethods)
{
syntaxTree = CSharpSyntaxTree.ParseText(mds.ToFullString());
IEnumerable<SyntaxNode> nodes = syntaxTree.GetRoot().DescendantNodes();
IEnumerable<VariableDeclarationSyntax> variableDeclarations = nodes.OfType<VariableDeclarationSyntax>();
foreach (VariableDeclarationSyntax variable in variableDeclarations)
{
// I will collect the variable details like Datatype, variable names and initialized values here
}
foreach (StatementSyntax statement in mds.Body.Statements)
{
if (statement.CSharpKind() == SyntaxKind.ExpressionStatement)
{
//I want to split the expressions "Console.Write(str + floatVariable.ToString() + intVariable.ToString());" as below
//1. intVariable.ToString()
//2. floatVariable.ToString()
//3. str
//Then I have to find the whole data type from the resolved result of above 3 => string here
}
}
}
我们将不胜感激。
编辑:
我在拆分参数化表达式语句时遇到问题。我正在尝试通过
来做到这一点
if (statement.CSharpKind() == SyntaxKind.ExpressionStatement)
{
ExpressionStatementSyntax expression = statement as ExpressionStatementSyntax;
var expressions = expression.Expression.DescendantNodes();
}
但这会将每个标记拆分为单独的元素。我只想将 Console.Write(str + floatVariable.ToString() + intVariable.ToString())
拆分为
- Console.Write()
- 海峡
- intVariable.ToString()
- floatVariable.ToString()
很难说出你到底想做什么,因为你只指定了代码在一种特定情况下应该做什么,而不是在一般情况下。
我的理解是:
- 对于调用表达式,return 被调用的表达式,如果有的话,也会下降到它的参数中。
- 对于二元运算符,下降到 children。
- 对于所有其他表达式,return 直接表达式。
使用此规范并使用 CSharpSyntaxVisitor
,代码可能如下所示:
public static IEnumerable<ExpressionSyntax> Split(ExpressionSyntax expression)
{
return new SplitVisitor().Visit(expression);
}
class SplitVisitor : CSharpSyntaxVisitor<IEnumerable<ExpressionSyntax>>
{
public override IEnumerable<ExpressionSyntax> VisitInvocationExpression(
InvocationExpressionSyntax node)
{
yield return node.Expression;
var argumentExpressions = node.ArgumentList.Arguments
.SelectMany(a => Visit(a.Expression));
foreach (var expression in argumentExpressions)
yield return expression;
}
public override IEnumerable<ExpressionSyntax> VisitBinaryExpression(
BinaryExpressionSyntax node)
{
foreach (var expression in Visit(node.Left))
yield return expression;
foreach (var expression in Visit(node.Right))
yield return expression;
}
public override IEnumerable<ExpressionSyntax> DefaultVisit(SyntaxNode node)
{
var expression = node as ExpressionSyntax;
if (expression != null)
yield return expression;
}
}
我正在开发一个重述 CSharp
代码的应用程序。我用 Roslyn
来做这个。我遇到了 splitting expressions
.
示例类
class Program
{
static void Main(string[] args)
{
float floatVariable = 20;
Int16 intVariable = 10;
string str = "School";
Console.Write(str + floatVariable.ToString() + intVariable.ToString()); // Facing problem with this statement
}
}
我正在使用的示例代码
string code = new StreamReader(classPath).ReadToEnd();
var syntaxTree = CSharpSyntaxTree.ParseText(code);
var syntaxRoot = syntaxTree.GetRoot();
//This will get the method and local variables declared inside the method
var MyMethods = syntaxRoot.DescendantNodes().OfType<MethodDeclarationSyntax>();
foreach (MethodDeclarationSyntax mds in MyMethods)
{
syntaxTree = CSharpSyntaxTree.ParseText(mds.ToFullString());
IEnumerable<SyntaxNode> nodes = syntaxTree.GetRoot().DescendantNodes();
IEnumerable<VariableDeclarationSyntax> variableDeclarations = nodes.OfType<VariableDeclarationSyntax>();
foreach (VariableDeclarationSyntax variable in variableDeclarations)
{
// I will collect the variable details like Datatype, variable names and initialized values here
}
foreach (StatementSyntax statement in mds.Body.Statements)
{
if (statement.CSharpKind() == SyntaxKind.ExpressionStatement)
{
//I want to split the expressions "Console.Write(str + floatVariable.ToString() + intVariable.ToString());" as below
//1. intVariable.ToString()
//2. floatVariable.ToString()
//3. str
//Then I have to find the whole data type from the resolved result of above 3 => string here
}
}
}
我们将不胜感激。
编辑: 我在拆分参数化表达式语句时遇到问题。我正在尝试通过
来做到这一点if (statement.CSharpKind() == SyntaxKind.ExpressionStatement)
{
ExpressionStatementSyntax expression = statement as ExpressionStatementSyntax;
var expressions = expression.Expression.DescendantNodes();
}
但这会将每个标记拆分为单独的元素。我只想将 Console.Write(str + floatVariable.ToString() + intVariable.ToString())
拆分为
- Console.Write()
- 海峡
- intVariable.ToString()
- floatVariable.ToString()
很难说出你到底想做什么,因为你只指定了代码在一种特定情况下应该做什么,而不是在一般情况下。
我的理解是:
- 对于调用表达式,return 被调用的表达式,如果有的话,也会下降到它的参数中。
- 对于二元运算符,下降到 children。
- 对于所有其他表达式,return 直接表达式。
使用此规范并使用 CSharpSyntaxVisitor
,代码可能如下所示:
public static IEnumerable<ExpressionSyntax> Split(ExpressionSyntax expression)
{
return new SplitVisitor().Visit(expression);
}
class SplitVisitor : CSharpSyntaxVisitor<IEnumerable<ExpressionSyntax>>
{
public override IEnumerable<ExpressionSyntax> VisitInvocationExpression(
InvocationExpressionSyntax node)
{
yield return node.Expression;
var argumentExpressions = node.ArgumentList.Arguments
.SelectMany(a => Visit(a.Expression));
foreach (var expression in argumentExpressions)
yield return expression;
}
public override IEnumerable<ExpressionSyntax> VisitBinaryExpression(
BinaryExpressionSyntax node)
{
foreach (var expression in Visit(node.Left))
yield return expression;
foreach (var expression in Visit(node.Right))
yield return expression;
}
public override IEnumerable<ExpressionSyntax> DefaultVisit(SyntaxNode node)
{
var expression = node as ExpressionSyntax;
if (expression != null)
yield return expression;
}
}