我很确定我遗漏了一些明显的东西,但即使在阅读官方文档后,我也不清楚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子句的集合语法节点?
我错过了什么?
答案 0 :(得分:10)
在聊天讨论之后,我们确定问题是要解析的代码正在构建:
string[]lines = System.IO.File.ReadAllLines(filename);
string tocompile = string.Join(string.Empty, lines);
将所有代码放在一行上。因此//
之后的所有内容都会成为评论。解决方案只是使用Environment.NewLine
作为连接字符,或使用ReadAllText
代替ReadAllLines
。
答案 1 :(得分:3)
由于注释可以出现在源代码中的任何位置,因此它们不会被建模为ChildNode
,它们是为真正的语法元素保留的。相反,它们被视为SyntaxTrivia
。在您的示例中,您应该能够查看方法的LeadingTrivia
并查看注释。
此外,由于这是一个XML文档注释,它可能具有自己的有趣结构,因此它将被建模为它自己的小树,您可以使用GetStructure()
的{{1}}方法获得该树。
答案 2 :(得分:1)
对于这种情况,使用CSharpSyntaxWalker
可能会有很大帮助。
以下是从Josh Varty's博客here中提取的示例,该示例有助于在控制台上打印语法树:
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
方法来打印trivias。