从循环条件获取Microsoft Roslyn的迭代次数

时间:2013-11-22 15:38:12

标签: c# roslyn

我有这个代码要解析:

int[] tab1 = { 0, 1, 2, 3, 4 };
for (var i = 0; i < tab1.Length - 1; i++) { };

如何使用Microsoft Roslyn获取tab1.Length - 1(本例中为4)的确切值?

我可以使用以下代码找到表达式tab1.Length - 1:

var collector = new ForCollector();
foreach (var statement in collector.ForStatements)
{
    Console.WriteLine(statement.Condition.ChildNodes().ElementAt(1));
}

其中ForCollector是一个继承SyntaxWalker的类,具有覆盖函数VisitForStatement但我不知道如何获取tab1.Length的值。我想我必须为此目的使用SemanticModel。

罗斯林版本 - 2012年9月

1 个答案:

答案 0 :(得分:1)

此解决方案遍历语法树以查找您要查找的内容。注意:

  1. 走遍整棵树。如果你输入更多的类或方法,它只会找到第一个。您可以修改代码以找到任意数量的for循环,然后检查每个循环。
  2. 我已将代码段包装在一个方法中,以便于解析。
  3. 为了便于阅读,我已经打破了每一步,你可以将它们折叠起来。
  4. 这是源代码,您可以将其转储到控制台应用程序中以运行它。

    using System.Linq;
    using Roslyn.Compilers.CSharp;
    
    // Snip some console app wrapping
    
    var code = @"
        public void FindI()
        {
            int[] tab1 = { 0, 1, 2, 3, 4 };
            for (var i = 0; i < tab1.Length - 1; i++) { };
        }";
    
            var syntaxTree = SyntaxTree.ParseText(code);
    
            var forStatement = syntaxTree
                .GetRoot()
                .DescendantNodes()
                .OfType<ForStatementSyntax>()
                .First();
    
            // Gets the name 'tab1' from the for statement condition
            var conditionMemberName = forStatement
                .DescendantNodes()
                .OfType<MemberAccessExpressionSyntax>()
                .First()
                .GetFirstToken()
                .Value;
    
            // Finds the first variable: int[] tab1 = { 0, 1, 2, 3, 4 };
            var member = syntaxTree
                .GetRoot()
                .DescendantNodes()
                .OfType<VariableDeclarationSyntax>()
                .First()
    
            // Finds the variable with the correct name 'tab1'
            var variable = member.Variables.Where(x => x.Identifier.Value == conditionMemberName).Single();
    
            // Find the initializer: { 0, 1, 2, 3, 4 };
            var initializer = variable.Initializer.Value as InitializerExpressionSyntax;
    
            // Counds the number of items in the initializer
            var lengthOfInitializers = initializer.Expressions.Count;