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,是語法樹的根節點。

關鍵字

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
    • [] 這種用於創建數組類型的語法。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章