Roslyn 语法树中的各种语法节点及每个节点的含义
使用 Roslyn 进行源码分析时,我们会对很多不同种类的语法节点进行分析。如果能够一次性了解到各种不同种类的语法节点,并明白其含义和结构,那么在源码分析的过程中将会更加得心应手。
本文将介绍 Roslyn 中各种不同的语法节点、每个节点的含义,以及这些节点之间的关系和语法树结构。
基本概念
using System;
namespace Walterlv.Demo
{
class Program { static void Main(string[] args) { Console.WriteLine("Hello Walterlv!"); } }
}
1
2
3
4
5
6
7
8
9
10
11
12
以上是一个非常简单但完整的 .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(string a) 中的 部分。
TypeParameter
泛型形参,即以上例子中的 T1 和 T2 部分。
TypeArgumentList
泛型实参列表,出现在使用泛型参数的地方,例如 this.Foo() 中的 部分。
TypeArgument
泛型实参,即以上例子中的 T1 和 T2 部分。
语句块
Block
即用 { 和 } 包裹的语句代码。
当然并不是所有 { 和 } 包裹的都是语句(例如类型声明就不是),里面真正有代码时才是语句。
EqualsValueClause
等号子句,例如 = null。我们经常称之为“赋值”语句。
语句
一个语句是指包含分号在内的实际执行的句子。
LocalDeclarationStatement
本地变量声明语句,即 var a = 0; 这样的句子;其中,去掉分号的部分即前面我们提到的变量声明 VariableDeclaration。
一个本地变量声明的语句也可以不包含赋值。
ExpressionStatement
表达式语句,即 this.Foo(); 这样的一次方法调用。如果去掉分号,剩下的部分是表达式(Expression)。
IfStatement
if 语句,即一个完整的 if-else if-else。
ForStatement
for 语句。
ForEachStatement
for 语句。
WhileStatement
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。
如果是获取属性(没有参数列表),那么也是这个节点。
AwaitExpression
await 表达式,即 await this.Foo() 这样的调用。
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 的语法。
TupleType
即 (bool, string) 这种用于创建 ValueTuple 的语法。
ArrayType
即 [] 这种用于创建数组类型的语法。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
cefsharp 与webbrowser简单对比概述
原文: cefsharp 与webbrowser简单对比概述 有个项目需要做个简单浏览器,从网上了解到几个相关的组件有winform自带的IE内核的WebBrowser,有第三方组件谷歌内核的webkit、cefsharp、chromiumfx等。 一开始是用的webbrowser 后来发现有些css样式是不兼容的于是又开始研究webkit这个有些css样式同样不能用,然后才开始研究cefsharp,从网上下载了57版本的但总是运行不起来后来发现装上vs中C++公共工具才行(注意即使装上vcredist_x86这个运行库也是不行),这个你不能要求人家客户装vs啊,后来也没找到到底是哪个动态库的问题。之后就下载了47版本。 按键事件 不同于webbrowser通过事件PreviewKeyDown捕获键盘按键,cefsharp是通过实现接口IKeyboardHandler赋值委托KeyboardHandler来实现的 web.KeyboardHandler = new CefKeyboardHandler(m_cell as CellControl); public class CefK...
- 下一篇
Django 搭建CMDB系统完整[12](软件资产、厂商)
search_software.html {% extends 'base.html' %} {% block title %} <script type="text/javascript" src="/static/scripts/jquery/jquery-1.7.1.js"></script> <link href="/static/style/authority/basic_layout.css" rel="stylesheet" type="text/css"> <link href="/static/style/authority/common_style.css" rel="stylesheet" type="text/css"> <script type="text/javascript" src="/static/scripts/authority/commonAll.js"></script> <script type="text/javascript" src="/static/scri...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker快速安装Oracle11G,搭建oracle11g学习环境