Получите SyntaxNode, учитывая номер строки в SyntaxTree - программирование

Получите SyntaxNode, учитывая номер строки в SyntaxTree

Я хочу получить SyntaxNode строки с указанием местоположения (lineNumber). Код ниже должен быть понятным, но дайте мне знать о любых вопросах.

static void Main()
        {
            string codeSnippet = @"using System;
                                        class Program
                                        {
                                            static void Main(string[] args)
                                            {
                                                Console.WriteLine(""Hello, World!"");
                                            }
                                        }";

            SyntaxTree tree = SyntaxTree.ParseCompilationUnit(codeSnippet);
            string[] lines = codeSnippet.Split('\n');
            SyntaxNode node = GetNode(tree, 6); //How??
        }

        static SyntaxNode GetNode(SyntaxTree tree,int lineNumber)
        {
            throw new NotImplementedException();
            // *** What I did ***
            //Calculted length from using System... to Main(string[] args) and named it (totalSpan)
            //Calculated length of the line(lineNumber) Console.Writeline("Helllo...."); and named it (lineSpan)
            //Created a textspan : TextSpan span = new TextSpan(totalSpan, lineSpan);
            //Was able to get back the text of the line : tree.GetLocation(span);
            //But how to get the SyntaxNode corresponding to that line??
        }
4b9b3361

Ответ 1

Во-первых, чтобы получить TextSpan на основе номера строки, вы можете использовать индекс Lines SourceText, возвращаемый GetText() (но осторожно, он подсчитывает строки из 0).

Затем, чтобы получить все узлы, которые пересекают этот диапазон, вы можете использовать перегрузку DescendantNodes().

Наконец, вы фильтруете этот список, чтобы получить первый node, который содержится полностью в этой строке.

В коде:

static SyntaxNode GetNode(SyntaxTree tree, int lineNumber)
{
    var lineSpan = tree.GetText().Lines[lineNumber - 1].Span;
    return tree.GetRoot().DescendantNodes(lineSpan)
        .First(n => lineSpan.Contains(n.Span));
}

Если в этой строке нет node, это вызовет исключение. Если их больше одного, он вернет первый.