Roslyn 语法树中的各种语法节点及每个节点的含义
使用 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 级语法节点通常是这样的:
- CompilationUnit
- UsingDirective
- UsingDirective
- NamespaceDeclaration
- EndOfFileToken
类型声明是命名空间声明的子节点,类型成员的声明是类型声明的子节点。
名称和标识符
- QualifiedName
- 限定名称,可以理解为完整的名称。
- 例如命名空间 Walterlv.DemoTool 的限定名称就是这个全称 Walterlv.DemoTool;类型 Walterlv.DemoTool.Foo 的限定名称也是这个全程 Walterlv.DemoTool.Foo。
- IdentifierName
- 标识名称,当前上下文下的唯一名称。
- 例如 Walterlv 和 DemoTool 都是 Walterlv.DemoTool 这个命名空间的标识符。
- IdentifierToken
- 标识符,具体决定 IdentifierName 的一个字符串。
- 这其实与 IdentifierName 是一样的意思,但是在语法树上的不同节点。
- GenericName
- 泛型名称,即 Foo 这种。
特性
AttributeList、Attribute。
一个允许添加特性的地方,如果添加了特性,那么可以得到 AttributeList 节点,内部包含了多个 Attribute 子节点。
形参和实参
形参是 parameter,实参是 argument。前者是定义的参数,后者是实际传入的参数。
语法节点中有两种不同的形参和实参,一个是泛型,一个是普通参数。
- ParameterList
- 形参列表,出现在方法声明中,即
void Foo(string a, bool b)中的(string a, bool b)部分。
- 形参列表,出现在方法声明中,即
- Parameter
- 形参,即以上例子中的
string a和bool b部分。
- 形参,即以上例子中的
- ArgumentList
- 实参列表,出现在方法调用中,即
this.Foo(a, b)中的(a, b)部分。
- 实参列表,出现在方法调用中,即
- Argument
- 实参,即以上例子中的
a和b部分。
- 实参,即以上例子中的
- TypeParameterList
- 泛型形参列表,出现在类型声明或者方法声明中,即
void Foo<T1, T2>(string a)中的<T1, T2>部分。
- 泛型形参列表,出现在类型声明或者方法声明中,即
- TypeParameter
- 泛型形参,即以上例子中的
T1和T2部分。
- 泛型形参,即以上例子中的
- TypeArgumentList
- 泛型实参列表,出现在使用泛型参数的地方,例如
this.Foo<T1, T2>()中的<T1, T2>部分。
- 泛型实参列表,出现在使用泛型参数的地方,例如
- TypeArgument
- 泛型实参,即以上例子中的
T1和T2部分。
- 泛型实参,即以上例子中的
语句块
- Block
- 即用
{和}包裹的语句代码。 - 当然并不是所有
{和}包裹的都是语句(例如类型声明就不是),里面真正有代码时才是语句。
- 即用
- EqualsValueClause
- 等号子句,例如
= null。我们经常称之为“赋值”语句。
- 等号子句,例如
语句
一个语句是指包含分号在内的实际执行的句子。
- LocalDeclarationStatement
- 本地变量声明语句,即
var a = 0;这样的句子;其中,去掉分号的部分即前面我们提到的变量声明 VariableDeclaration。 - 一个本地变量声明的语句也可以不包含赋值。
- 本地变量声明语句,即
- ExpressionStatement
- 表达式语句,即
this.Foo();这样的一次方法调用。如果去掉分号,剩下的部分是表达式(Expression)。
- 表达式语句,即
- IfStatement
- if 语句,即一个完整的
if-else if-else。
- if 语句,即一个完整的
- ForStatement
- for 语句。
- ForEachStatement
- for 语句。
- WhileStatement
- while 语句,即一个完整的
while。
- while 语句,即一个完整的
- DoStatement
- do-while 语句。
- DefaultStatement
default();语句。
- ReturnStatement
- return 语句。
- CheckedStatement
- checked 语句。
- UncheckedStatement
- checked 语句。
- UnsafeStatement
- unsafe 语句。
- FixedStatement
- unsafe 语句。
表达式
- EqualsExpression
- 相等判断表达式,即
a == b。
- 相等判断表达式,即
- InvocationExpression
- 调用表达式,即
Class.Method(xxx)或instance.Method(xxx)这种完整的调用。
- 调用表达式,即
- SimpleMemberAccessExpression
- 这是 InvocationExpression 的子节点,是方法调用除去参数列表的部分,即
Class.Method或instance.Method。 - 如果是获取属性(没有参数列表),那么也是这个节点。
- 这是 InvocationExpression 的子节点,是方法调用除去参数列表的部分,即
- AwaitExpression
- await 表达式,即
await this.Foo()这样的调用。
- await 表达式,即
- DefaultExpression
default()表达式。
- TrueLiteralExpression
true表达式。
- FalseLiteralExpression
false表达式。
- ParenthesizedLambdaExpression
- 带括号的 lambda 表达式,例如:
() => xxx、(a) => xxx、(a, b) => xxx、(int a, string b) => xxx() => { }、(a) => { }、(a, b) => { }、(int a, string b) => { }
- SimpleLambdaExpression
- 不带括号的 lambda 表达式,例如:
a => xxx、a => { }
基元类型
PredefinedType 是所有基元类型的节点。它的子节点可能是 BoolKeyword、StringKeyword 或其它基元类型的关键字。
C# 内建类型
NullableType、TupleType、ArrayType。
这三个分别是 C# 中语法级别支持的类型,分别是可空类型、元组类型和数组类型。
- NullableType
- 即
bool?这种用于创建Nullable<bool>的语法。
- 即
- TupleType
- 即
(bool, string)这种用于创建ValueTuple<bool, string>的语法。
- 即
- ArrayType
- 即
[]这种用于创建数组类型的语法。
- 即
Roslyn 语法树中的各种语法节点及每个节点的含义的更多相关文章
- JSP编译成Servlet(一)语法树的生成——语法解析
一般来说,语句按一定规则进行推导后会形成一个语法树,这种树状结构有利于对语句结构层次的描述.同样Jasper对JSP语法解析后也会生成一棵树,这棵树各个节点包含了不同的信息,但对于JSP来说解析后的语 ...
- LINQ语法类似于SQL的语法
LINQ语法类似于SQL的语法如下, Models.BookStoreEntities 是从添加新建项中的数据--->ADO.NET实体数据模型--->从数据库生成--->使用5.0 ...
- dom节点及对节点的常用操作方法
dom节点及对节点的常用操作方法 在说dom节点前,先来看看页面的呈现: dom渲染流程: 1.浏览器解析html源码,然后创建一个DOM树. 在DOM树中,每一个HTML标签都有一个对应的节点(元 ...
- 【转】JavaScript获取节点类型、节点名称和节点值
DOM节点信息包括节点类型(nodeType).节点名称(nodeName)和节点值(nodeValue). 节点类型 DOM节点中,每个节点都拥有不同的类型.W3C规范中常用的 DOM节点类型有以下 ...
- SUSE Ceph 增加节点、减少节点、 删除OSD磁盘等操作 - Storage6
一.测试环境描述 之前我们已快速部署好一套Ceph集群(3节点),现要测试在现有集群中在线方式增加节点 如下表中可以看到增加节点node004具体配置 主机名 Public网络 管理网络 集群网络 说 ...
- STL---Codeforces675D Tree Construction(二叉树节点的父亲节点)
Description During the programming classes Vasya was assigned a difficult problem. However, he doesn ...
- 红黑树之 原理和算法详细介绍(阿里面试-treemap使用了红黑树) 红黑树的时间复杂度是O(lgn) 高度<=2log(n+1)1、X节点左旋-将X右边的子节点变成 父节点 2、X节点右旋-将X左边的子节点变成父节点
红黑树插入删除 具体参考:红黑树原理以及插入.删除算法 附图例说明 (阿里的高德一直追着问) 或者插入的情况参考:红黑树原理以及插入.删除算法 附图例说明 红黑树与AVL树 红黑树 的时间复杂度 ...
- Delphi Treeview 用法(概念、属性、添加编辑插入节点、定位节点、拖拽等)
今天再细研究了一下Treeview的用法,网上虽然总结了很多,但是还是有很多节点没有讲到了,也给使用中遇到很多问题.特地总结一下: 1.概念 Treeview用于显示按照树形结构进行组织的数据.Tre ...
- LeetCode-129-求根节点到叶节点数字之和
求根节点到叶节点数字之和 题目描述:给你一个二叉树的根节点 root ,树中每个节点都存放有一个 0 到 9 之间的数字. 每条从根节点到叶节点的路径都代表一个数字: 例如,从根节点到叶节点的路径 1 ...
随机推荐
- CDN专业一站式解决方案
调度,弱网加速,动态防御,无限节点(重)新技术
- cocos2d-x入门一
为什么要学cocos2d-x 首先要明白什么是cocos2d-x,能干什么.cocos2d-x是一种跨平台的2D.3D游戏开发工具,目前较为流行的大多数android.ios游戏都是用它 ...
- MVC 后台调用JS
示例控制器: public ActionResult Index() { ViewBag.js = "<script type='text/java ...
- flask学习(三):flask入门(URL)
一. flask简介 flask是一款非常流行的python web框架,出生于2010年,作者是Armin Ronacher,本来这个项目只是作者在愚人节的一个玩笑,后来由于非常受欢迎,进而成为一个 ...
- bzoj 4627 值域线段树
4627: [BeiJing2016]回转寿司 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 523 Solved: 227[Submit][Sta ...
- 【转】ext4+delalloc造成单次写延迟增加的分析
转自 http://blog.tao.ma/?p=58 这篇文章是淘宝内核组的刘峥同学在内部技术论坛上发表的一篇文章,但是由于刘峥同学目前没有blog,征得本人同意,贴在我的blog上,如果大家喜欢, ...
- Metasploit没有db_autopwn命令的解决办法
将附件db_autopwn.rp 拷贝到/opt/framework3/msf3/plugins/PS:db_autopwn.rp 下载地址:http://dl.vmall.com/c04w8czlc ...
- nyoj993——容斥
How many integers can you find 时间限制:1000 ms | 内存限制:65535 KB 难度:1 描述 给你三个数,n,m1,m2,找出所有小于n的能被m1或m ...
- 安装Linux环境
虚拟机:虚拟机(Virtual Machine),在计算机科学中的体系结构里,是指一种特殊的软件,他可以在计算机平台和终端用户之间建立一种环境,而终端用户则是基于这个软件所建立的环境来操作软件.在计算 ...
- NC 工具的使用教程
NC工具的使用说明...nc使用说明 参数介绍: nc.exe -h即可看到各参数的使用方法. 基本格式:nc [-options] hostname port[s] [ports] ... nc - ...