Рослин сомневается в конструкции SyntaxTree - PullRequest
3 голосов
/ 30 декабря 2011

Отказ от ответственности

Я почти уверен, что упускаю что-то очевидное, но даже после прочтения официальной документации я не совсем понимаю, как Рослин создает синтаксическое дерево.

Пример

Рассмотрим следующий простой код:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace aopsample
{

    class UsbReadWriter
    {

        public bool ReadFromUsb()
        {
            return true;
        }

        public virtual bool WriteToUsb()
        {
            return true;
        }
    }
}

Я получаю SyntaxTree для этого кода и делаю что-то вроде этого, очень грубое и простое, ноМне просто нужно понять.

  string[]lines =  System.IO.File.ReadAllLines(filename);      
  string tocompile = string.Join(string.Empty, lines);  

  SyntaxNode root = tree.GetRoot(new CancellationToken());
  foreach (SyntaxNode sn in root.ChildNodes())
  {
      if (sn.Kind == SyntaxKind.NamespaceDeclaration)
      {
         //I get a namespace, so it's Child node just will be class
         foreach (SyntaxNode sname in sn.ChildNodes())
         {
             if (sname.Kind == SyntaxKind.ClassDeclaration)
             {
                 //I get class, so it's  Children will be methods of the class        
                 foreach (SyntaxNode sclass in sname.ChildNodes()) // **{1}** 
                 {
                     if (sclass.Kind == SyntaxKind.MethodDeclaration) 
                     {

                     }
                 }
             }
        }

И это работает довольно хорошо.

Проблема

Но достаточно добавить комментарий к методу ReadFromUsb(), что-то вроде этого

/// <summary>
/// Reads a data from Usb
/// </summary>
/// <returns></returns>
public bool ReadFromUsb()
{
    return true;
}

И ChildNodes() вызов {1} отмеченстрока, для CLASS (???) возвращает 0.

Вопрос

Зачем добавлять комментарий к функции-члену, сбрасывает коллекцию родительских дочерних узлов синтаксиса CLASS?

Чего мне не хватает?

Ответы [ 3 ]

10 голосов
/ 31 декабря 2011

После обсуждения в чате мы определили, что проблема заключалась в том, что код для разбора создавался с помощью:

string[]lines = System.IO.File.ReadAllLines(filename); 
string tocompile = string.Join(string.Empty, lines);

, который помещает весь код в одну строку.Поэтому все после // становится комментарием.Решение состоит в том, чтобы просто использовать Environment.NewLine в качестве символа объединения или использовать ReadAllText вместо ReadAllLines.

3 голосов
/ 31 декабря 2011

Поскольку комментарии могут появляться где угодно в исходном коде, они не моделируются как ChildNode, которые зарезервированы для истинных синтаксических элементов. Вместо этого они считаются SyntaxTrivia. В вашем примере вы сможете посмотреть LeadingTrivia метода и увидеть комментарий.

Кроме того, поскольку это XML-комментарий к документу, который может иметь интересную собственную структуру, он будет смоделирован как собственное небольшое дерево, которое вы можете получить с помощью метода GetStructure() SyntaxTrivia.

1 голос
/ 15 декабря 2017

В таких ситуациях использование CSharpSyntaxWalker может быть очень полезным.

Ниже приведен пример, извлеченный из блога Джоша Варти здесь , который помогает распечатать дерево синтаксиса на консоли:

 public class CustomWalker : CSharpSyntaxWalker
{
    static int Tabs = 0;
    public override void Visit(SyntaxNode node)
    {
        Tabs++;
        var indents = new String('\t', Tabs);
        Console.WriteLine(indents + node.Kind());
        base.Visit(node);
        Tabs--;
    }
}

static void Main(string[] args)
{
    var tree = CSharpSyntaxTree.ParseText(@"
        public class MyClass
        {
            public void MyMethod()
            {
            }
            public void MyMethod(int n)
            {
            }
       ");

    var walker = new CustomWalker();
    walker.Visit(tree.GetRoot());
}

Вы также можете распечатать пустяки, вызвав методы GetLeadingTrivia и GetTrailingTrivia на узлах синтаксиса.

...