3

免责声明

我很确定我遗漏了一些明显的东西,但是即使在阅读了官方文档之后,我也不清楚 Roslyn 如何创建语法树。

例子

考虑以下简单的代码:

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 子语法节点的集合?

我错过了什么?

4

3 回答 3

11

在聊天讨论之后,我们确定问题在于要解析的代码是用以下方式构造的:

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

它将所有代码放在一行中。因此之后的所有内容都//成为评论。解决方案只是Environment.NewLine用作连接字符,或使用ReadAllText代替ReadAllLines.

于 2011-12-30T22:24:31.210 回答
3

由于注释可以出现在源代码中的任何地方,它们没有被建模为 a ChildNode,它是为真正的句法元素保留的。相反,它们被认为是SyntaxTrivia. 在您的示例中,您应该能够查看LeadingTrivia方法并查看注释。

此外,由于这是一个 XML 文档注释,它可能具有它自己的有趣结构,它将被建模为它自己的小树,您可以GetStructure()使用SyntaxTrivia.

于 2011-12-30T21:32:48.917 回答
1

对于这种情况,UsingCSharpSyntaxWalker可以提供很大的帮助。

以下是从Josh Varty 的博客中提取的示例,有助于在控制台上打印语法树:

 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

于 2017-12-15T11:34:19.713 回答