标签:ret nod null dir ima sim 避免 了解 数列
使用 Roslyn 进行源码分析时,我们会对很多不同种类的语法节点进行分析。如果能够一次性了解到各种不同种类的语法节点,并明白其含义和结构,那么在源码分析的过程中将会更加得心应手。
本文将介绍 Roslyn 中各种不同的语法节点、每个节点的含义,以及这些节点之间的关系和语法树结构。
using System;
namespace Walterlv.Demo
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello Walterlv!");
}
}
}
以上是一个非常简单但完整的 .cs 文件。
在 Roslyn 的解析中,这就是一个“编译单元”(Compilation Unit)。编译单元是 Roslyn 语法树的根节点。紧接着的 using System
是 using 指令(Using Directives);随后是命名空间声明(Namespace Declaration),包含子节点类型声明(Class Declaration);类型声明包含子节点方法声明(Method Declaration)。
接下来,我们会介绍 Roslyn 语法树中各种不同种类的节点,以及其含义。
CompilationUnit,是语法树的根节点。
UsingKeyword、NamespaceKeyword、PublicKeyword、InternalKeyword、PrivateKeyword、ProtectedKeyword、StaticKeyword、ClassKeyword、InterfaceKeyword、StructKeyword。
分别是 C# 的各种关键字:using
, namespace
, public
, internal
, private
, protected
, static
, class
, interface
, struct
。
InKeyword、OutKeyword、RefKeyword、ReturnKeyword、ConstKeyword、DefaultKeyword。
分别是 C# 的另一波关键字 in
、out
、ref
、return
、const
、default
。
ByteKeyword、CharKeyword、IntKeyword、LongKeyword、BoolKeyword、FloatKeyword、DoubleKeyword、DecimalKeyword。
分别是 C# 中的基元类型关键字byte
、char
、int
、long
、bool
、float
、double
、decimal
。需要注意的是,var
和 dynamic
并不是基元类型关键字,在语法节点中,它是 IdentifierName。
AsyncKeyword、AwaitKeyword。
分别是 async
、await
关键字。
TrueKeyword、FalseKeyword。
分别是 true
和 false
关键字。
LockKeyword、CheckedKeyword、UncheckedKeyword、UnsafeKeyword、FixedKeyword。
分别是 lock
、checked
、unchecked
、unsafe
、fixed
关键字。
DotToken、SemicolonToken、OpenBraceToken、CloseBraceToken、LessThanToken、GreaterThanToken、OpenParenToken、CloseParenToken。
分别是 C# 中的各种符号:.
, ;
, {
, }
, <
, >
, (
, )
。
EndOfLineTrivia 表示换行,WhitespaceTrivia 表示空格,EndOfFileToken 表示文件的末尾。
通常,这两个语法节点会在另一个节点的里面,作为另一个节点的最后一部分。比如 using Walterlv.Demo;
是一个 UsingDirective,它的最后一个节点 Semicolon 中就会包含换行符 EndOfLineTrivia。
UsingDirective 是 using
指令。一个 using
指令包含一个 UsingKeyword,一个 QualifiedName 和一个 Semicolon(;
)。
NamespaceDeclaration、ClassDeclaration、MethodDeclaration、PropertyDeclaration、FieldDeclaration、VariableDeclaration。
分别是命名空间、类型、方法、属性、。
其中,属性声明包含一个 AccessorList,即属性访问器列表,访问期列表可以包含 GetAccessorDeclaration(属性 get)、SetAccessorDeclaration(属性 set)的声明。
这些声明通常是嵌套存在的。例如一个常规的文件的第 0、1 级语法节点通常是这样的:
类型声明是命名空间声明的子节点,类型成员的声明是类型声明的子节点。
AttributeList、Attribute。
一个允许添加特性的地方,如果添加了特性,那么可以得到 AttributeList 节点,内部包含了多个 Attribute 子节点。
形参是 parameter,实参是 argument。前者是定义的参数,后者是实际传入的参数。
语法节点中有两种不同的形参和实参,一个是泛型,一个是普通参数。
void Foo(string a, bool b)
中的 (string a, bool b)
部分。string a
和 bool b
部分。this.Foo(a, b)
中的 (a, b)
部分。a
和 b
部分。void Foo<T1, T2>(string a)
中的 <T1, T2>
部分。T1
和 T2
部分。this.Foo<T1, T2>()
中的 <T1, T2>
部分。T1
和 T2
部分。{
和 }
包裹的语句代码。{
和 }
包裹的都是语句(例如类型声明就不是),里面真正有代码时才是语句。= null
。我们经常称之为“赋值”语句。一个语句是指包含分号在内的实际执行的句子。
var a = 0;
这样的句子;其中,去掉分号的部分即前面我们提到的变量声明 VariableDeclaration。this.Foo();
这样的一次方法调用。如果去掉分号,剩下的部分是表达式(Expression)。if
-else if
-else
。while
。default();
语句。a == b
。Class.Method(xxx)
或 instance.Method(xxx)
这种完整的调用。Class.Method
或 instance.Method
。await this.Foo()
这样的调用。default()
表达式。true
表达式。false
表达式。() => xxx
、(a) => xxx
、(a, b) => xxx
、(int a, string b) => xxx
() => { }
、(a) => { }
、(a, b) => { }
、(int a, string b) => { }
a => xxx
、a => { }
PredefinedType 是所有基元类型的节点。它的子节点可能是 BoolKeyword、StringKeyword 或其它基元类型的关键字。
NullableType、TupleType、ArrayType。
这三个分别是 C# 中语法级别支持的类型,分别是可空类型、元组类型和数组类型。
bool?
这种用于创建 Nullable<bool>
的语法。(bool, string)
这种用于创建 ValueTuple<bool, string>
的语法。[]
这种用于创建数组类型的语法。本文会经常更新,请阅读原文: https://blog.walterlv.com/post/roslyn-syntax-tree-nodes.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://blog.walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 (walter.lv@qq.com) 。
标签:ret nod null dir ima sim 避免 了解 数列
原文地址:https://www.cnblogs.com/bigmango/p/11407268.html