使用 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,是语法树的根节点。

关键字

UsingKeywordNamespaceKeywordPublicKeywordInternalKeywordPrivateKeywordProtectedKeywordStaticKeywordClassKeywordInterfaceKeywordStructKeyword

分别是 C# 的各种关键字:using, namespace, public, internal, private, protected, static, class, interface, struct

InKeywordOutKeywordRefKeywordReturnKeywordConstKeywordDefaultKeyword

分别是 C# 的另一波关键字 inoutrefreturnconstdefault

ByteKeywordCharKeywordIntKeywordLongKeywordBoolKeywordFloatKeywordDoubleKeywordDecimalKeyword

分别是 C# 中的基元类型关键字bytecharintlongboolfloatdoubledecimal。需要注意的是,vardynamic 并不是基元类型关键字,在语法节点中,它是 IdentifierName。

AsyncKeywordAwaitKeyword

分别是 asyncawait 关键字。

TrueKeywordFalseKeyword

分别是 truefalse 关键字。

LockKeywordCheckedKeywordUncheckedKeywordUnsafeKeywordFixedKeyword

分别是 lockcheckeduncheckedunsafefixed 关键字。

符号

DotTokenSemicolonTokenOpenBraceTokenCloseBraceTokenLessThanTokenGreaterThanTokenOpenParenTokenCloseParenToken

分别是 C# 中的各种符号:., ;, {, }, <, >, (, )

空白

EndOfLineTrivia 表示换行,WhitespaceTrivia 表示空格,EndOfFileToken 表示文件的末尾。

通常,这两个语法节点会在另一个节点的里面,作为另一个节点的最后一部分。比如 using Walterlv.Demo; 是一个 UsingDirective,它的最后一个节点 Semicolon 中就会包含换行符 EndOfLineTrivia。

指令

UsingDirectiveusing 指令。一个 using 指令包含一个 UsingKeyword,一个 QualifiedName 和一个 Semicolon(;)。

声明

NamespaceDeclarationClassDeclarationMethodDeclarationPropertyDeclarationFieldDeclarationVariableDeclaration

分别是命名空间、类型、方法、属性、。

其中,属性声明包含一个 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 这种。

特性

AttributeListAttribute

一个允许添加特性的地方,如果添加了特性,那么可以得到 AttributeList 节点,内部包含了多个 Attribute 子节点。

形参和实参

形参是 parameter,实参是 argument。前者是定义的参数,后者是实际传入的参数。

语法节点中有两种不同的形参和实参,一个是泛型,一个是普通参数。

  • ParameterList

    • 形参列表,出现在方法声明中,即 void Foo(string a, bool b) 中的 (string a, bool b) 部分。
  • Parameter
    • 形参,即以上例子中的 string abool b 部分。
  • ArgumentList
    • 实参列表,出现在方法调用中,即 this.Foo(a, b) 中的 (a, b) 部分。
  • Argument
    • 实参,即以上例子中的 ab 部分。
  • TypeParameterList
    • 泛型形参列表,出现在类型声明或者方法声明中,即 void Foo<T1, T2>(string a) 中的 <T1, T2> 部分。
  • TypeParameter
    • 泛型形参,即以上例子中的 T1T2 部分。
  • TypeArgumentList
    • 泛型实参列表,出现在使用泛型参数的地方,例如 this.Foo<T1, T2>() 中的 <T1, T2> 部分。
  • TypeArgument
    • 泛型实参,即以上例子中的 T1T2 部分。

语句块

  • 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.Methodinstance.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 => xxxa => { }

基元类型

PredefinedType 是所有基元类型的节点。它的子节点可能是 BoolKeyword、StringKeyword 或其它基元类型的关键字。

C# 内建类型

NullableTypeTupleTypeArrayType

这三个分别是 C# 中语法级别支持的类型,分别是可空类型、元组类型和数组类型。

  • NullableType

    • bool? 这种用于创建 Nullable<bool> 的语法。
  • TupleType
    • (bool, string) 这种用于创建 ValueTuple<bool, string> 的语法。
  • ArrayType
    • [] 这种用于创建数组类型的语法。

Roslyn 语法树中的各种语法节点及每个节点的含义相关推荐

  1. 【Groovy】编译时元编程 ( 方法拦截时用到的 AST 语法树节点 MethodNode 节点 | MethodNode 节点分析 | MethodNode 节点中的BlockStatement)

    文章目录 一.方法拦截时用到的 AST 语法树节点 MethodNode 节点 二.MethodNode 节点分析 三.MethodNode 节点中的 BlockStatement 集合 一.方法拦截 ...

  2. 【Groovy】编译时元编程 ( AST 语法树分析 | ClassNode 根节点 | 方法 Methods 节点 | 字段 Fields 节点 | 属性 Properties 节点 )

    文章目录 一.AST 语法树分析 一.AST 语法树分析 在上一篇博客 [Groovy]编译时元编程 ( 编译时元编程引入 | 声明需要编译时处理的类 | 分析 Groovy 类的 AST 语法树 ) ...

  3. 【编译原理笔记08】语法制导翻译:语法制导定义,SSD的求值顺序,S属性定义与L属性定义

    本次笔记内容: 5-1 语法制导翻译概述 5-2 语法制导定义 5-3 SSD的求值顺序 5-4 S属性定义与L属性定义 本节课幻灯片,见于我的 GitHub 仓库:第8讲 语法制导翻译_1 文章目录 ...

  4. 【编译原理笔记09】语法制导翻译:语法制导翻译方案,在非递归的预测分析过程中进行翻译

    本次笔记内容: 5-5 语法制导翻译方案 5-6 在非递归的预测分析过程中进行翻译 本节课幻灯片,见于我的 GitHub 仓库:第9讲 语法制导翻译_2 文章目录 语法制导翻译方案 语法制导翻译方案 ...

  5. python selenium语法_selenium之xpath语法总结

    xpath语法 1. 什么是XPath? XPath是一种XML路径,用于浏览页面的HTML结构.他是一种语法或者语言用来查找使用XML路径表达的网页中的任意元素. XPath的基本形式如下: Xpa ...

  6. python语法错误概述_python语法错误

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 我是python中的新手,当我想在模块中编译代码时,我遇到语法错误:invail ...

  7. 【Groovy】Groovy 代码创建 ( 使用 Java 语法实现 Groovy 类和主函数并运行 | 按照 Groovy 语法改造上述 Java 语法规则代码 )

    文章目录 一.创建 Groovy 代码文件 二.使用 Java 语法实现 Groovy 类和主函数并运行 三.按照 Groovy 语法改造上述 Java 语法规则代码 一.创建 Groovy 代码文件 ...

  8. LINQ语法类似于SQL的语法

    LINQ语法类似于SQL的语法如下, Models.BookStoreEntities 是从添加新建项中的数据--->ADO.NET实体数据模型--->从数据库生成--->使用5.0 ...

  9. HTML语言的语法结构,语言的语法结构类型

    人类语言的语法结构类型有几种分类法 人类语言的语法结构类型有四种分类法:孤立语.粘着语.曲折语和复综语. 请喜欢. 语言的语法结构类型有哪些 论述题 语法范畴有广义和狭义之分.广义语法范畴是各种语法形 ...

最新文章

  1. jquery 获取一组元素的选中项 - 函数、jquery获取复选框值、jquery获取单选按钮值...
  2. LBS将使品牌口碑更真实
  3. 我的第一个python web开发框架(5)——开发前准备工作(了解编码前需要知道的一些常识)...
  4. 网站地图能给网站的优化带来什么好处
  5. 经济学与计算机科学结合,理论计算机在物理学和经济学领域的重要作用
  6. Java对象容器——Hash表/散列表
  7. NPM酷库:dateformat 时间字符串格式化
  8. 串口接收中断配置过程---STM32F4--HAL
  9. monkey自动化测试移动app 操作指南——真机 安卓(Android)app测试
  10. Linux磁盘管理之磁盘结构、概念、原理01
  11. 安卓系统为何这么容易被黑客入侵
  12. Java 1.1.3 修改字符串、不可变字符串
  13. Oracle In子句
  14. 【数据结构与算法】动态规划
  15. 登出/退出java_Servlet代码
  16. (2)VBA 关键字
  17. 298day(点触验证)
  18. jenkins pipeline slave部署nacos负载均衡平滑升级
  19. (application)javaweb中application的用法
  20. 一缕黑暗中的火光-----------活动图--------------优雅的建模语言

热门文章

  1. 创建df的副本df2,其中df2为除了df最后一列之外的所有列;
  2. PEST分析模型(转载)
  3. Matlab实现基于二维伽马函数的光照不均匀图像自适应校正算法
  4. matlab中 spm,使用SPM批处理在MATLAB中运行预处理
  5. Linux pidstat命令实战
  6. java abc排序_Java实现按照大小写字母顺序排序的方法
  7. 快手短视频没有才艺可以做主播吗
  8. LoadRunner 11压测时碰到错误Error: missing newline in E:\xx\RCV.dat
  9. 【C++】关于回调函数
  10. 整理不易的软件测试学习线路