語言服務剖析及掃描程式 (受管理的封裝架構)
剖析器是語言服務的核心。 管理套件架構 (MPF) 的語言類別需要的語言剖析器,以選取要顯示的程式碼的相關資訊。 剖析器會將文字分隔成語彙基元,並再找出這些語彙基元型別和功能。
討論
下面是 C# 方法。
namespace MyNamespace
{
class MyClass
{
public void MyFunction(int arg1)
{
int var1 = arg1;
}
}
}
在這個範例中,語彙基元會是中的單字和標點符號。 語彙基元的類型如下所示。
語彙基元名稱 |
語彙基元型別 |
---|---|
命名空間中,類別中,公用,void int |
keyword |
= |
運算子 |
{ } ( ) ; |
分隔符號 |
MyNamespace,MyClass,MyFunction,arg1 var1 |
identifier |
MyNamespace |
namespace |
MyClass |
class |
MyFunction |
方法 |
arg1 |
parameter |
var1 |
區域變數 |
剖析器的角色是要識別語彙基元。 某些語彙基元只能有一個以上的類型。 剖析器已識別之語彙基元之後,以提供有用的功能,例如語法反白顯示,大括號比對的資訊,並 IntelliSense 作業,可以使用語言服務。
剖析器的型別
語言服務剖析器並不相同,可做為編譯器的一部分的剖析器。 然而,這種類型的剖析器需要同時使用掃描器和剖析器,編譯器剖析器方式相同。
掃瞄器用來識別語彙基元的型別。 這項資訊用語法反白顯示,對於快速識別語彙基元型別會觸發其他作業,例如,括號對稱。 此程式由IScanner介面。
剖析器用來描述函式和語彙基元的範圍。 IntelliSense 作業中使用這項資訊,以識別語言項目,例如方法、 變數、 參數和宣告,並提供成員,以及依內容的方法簽名碼的清單。 這個剖析器也會用來找出相符的語言項目組,例如括號和括號中。 這個剖析器便會透過ParseSource中的方法LanguageService類別。
如何為您的語言服務實作掃描器和剖析器會給您。 數個資源可供使用,描述剖析器的運作方式,以及如何撰寫自己的剖析器。 此外,有數個空閒 / 商業產品,協助建立剖析器。
ParseSource 剖析器
與編譯器 (語彙基元會轉換成某種形式的可執行程式碼) 的一部分時,會剖析器,不同的是語言服務剖析器可以呼叫許多不同的原因,並在許多不同的內容。 在這種方法的實作方式ParseSource中的方法LanguageService類別是由您。 請務必要牢記在心, ParseSource可能會在背景執行緒上呼叫方法。
警告
ParseRequest結構包含參考IVsTextView物件。這IVsTextView物件不能用在背景執行緒。事實上,許多基底的 MPF 類別不能用在背景執行緒。其中包括Source, ViewFilter, CodeWindowManager類別和任何其他類別會直接或間接與通訊的檢視。
這個剖析器通常會剖析整個來源檔案的第一個時間呼叫它,或當剖析原因的值Check都可以。 後續呼叫ParseSource方法處理剖析程式碼的一小部分,並可以藉由使用先前的完整的剖析作業的結果更快速地執行。 ParseSource方法會透過在剖析作業的結果進行通訊, AuthoringSink和AuthoringScope物件。 AuthoringSink物件用來收集特定的剖析原因,比方說,span 的資訊比對大括號或具有參數清單的方法簽名碼的資訊。 AuthoringScope提供的宣告和方法簽名碼,也支援集合,移至進階編輯] 選項 (移至定義, 移至宣告, 移至參考)。
IScanner 掃瞄器
您也必須實作掃描器實作IScanner。 不過,因為這個掃瞄器的運作方式透過琵式為基礎,所以Colorizer類別,它是通常比較容易實作。 每一行的開頭時,讓 MPF Colorizer類別來當作傳遞到掃瞄器的狀態變數的值。 在每一行的結尾,掃瞄器會傳回更新的狀態變數。 MPF 會快取每一行這個狀態的資訊,這樣可以從任何列剖析,而不必從頭開始的原始程式檔 」 來啟動 「 掃瞄器。 單行這個快速掃描可讓編輯器] 提供快速的回應給使用者。
剖析相符的大括號
這個範例會顯示符合的使用者輸入右括號的控制流程。 進行這項工作,適用於顏色標示掃描器也用於判斷語彙基元和語彙基元會引動的比對大括號作業的型別。 如果找不到觸發程序, ParseSource會呼叫方法來尋找成對的括弧。 最後,在兩個大括號會反白顯示。
即使大括號用在觸發程序的名稱,並剖析原因,這項程序不是實際的大括號。 支援任何的字元,指定為相對應的配對組。 例如,< 和 >,以及 [和]。
假設語言服務支援對稱的括號。
使用者輸入右大括號 (})。
大括號會插入游標所在的原始程式檔的位置,而且游標會前移一個。
OnCommand方法呼叫GetTokenInfo中的方法Source以取得目前的游標位置之前的位置的語彙基元的類別。 這個語彙基元對應至具型別的右括號)。
GetTokenInfo方法呼叫GetLineInfo上的方法Colorizer以取得目前這一行上的所有語彙基元的物件。
GetLineInfo方法呼叫SetSource上的方法IScanner與目前這一行文字的物件。
GetLineInfo方法會重複呼叫ScanTokenAndProvideInfoAboutIt上的方法IScanner物件從目前這一行蒐集所有的語彙基元。
GetTokenInfo方法會呼叫私用的方法, Source類別以取得語彙基元,其中包含想要的位置,並傳入的語彙基元清單取自GetLineInfo方法。
OnCommand方法的語彙基元的觸發程序旗標會尋找MatchBraces會從傳回的權杖GetTokenInfo方法。 大括也就是語彙基元,表示結束號)。
如果觸發程序的旗標的MatchBraces發現, MatchBraces中的方法Source會呼叫類別。
MatchBraces方法會剖析作業開始剖析原因的值為HighlightBraces。 這項作業最後呼叫ParseSource上的方法LanguageService類別。 如果非同步剖析已啟用,此呼叫,就會ParseSource方法,就會發生在背景執行緒上。
當剖析作業完成時,名為內部完成處理常式 (也就是回呼方法) HandleMatchBracesResponse中呼叫Source類別。 這個呼叫後會自動地LanguageService基底類別,不是由剖析器。
HandleMatchBracesResponse方法會取得一份從 span AuthoringSink物件,儲存在ParseRequest物件。 (範圍是TextSpan原始程式檔中指定一系列的線條或字元的結構。) 這份 span 通常會包含兩個的 span,分別給開頭和結尾大括號。
HandleBracesResponse方法呼叫HighlightMatchingBrace上的方法IVsTextView物件,儲存在ParseRequest物件。 這會指定的 span 反白顯示。
如果LanguagePreferences屬性EnableShowMatchingBrace啟用時, HandleBracesResponse方法會取得已被對應的範圍,並在狀態列中顯示該範圍的第一次 80 個字元的文字。 這適合用ParseSource方法包含隨附於組相符的語言項目。 如需詳細資訊,請參閱 EnableShowMatchingBrace 屬性 (Property)。
完成。
摘要
相符的大括號作業是通常都限於簡單配對的語言項目。 更複雜的項目,例如,相符的 triples ("if(…)","{"和"}",或"else","{"和"}"),可反白顯示文字自動完成作業的一部分。 比方說,"else"word 完成時,比對"if"陳述式會被標示出來。 如果有一系列的if/else if陳述式,全部都可以使用相同的機制為相符的大括號來反白顯示。 Source基底類別已經支援,以下列方式: 掃描器必須傳回語彙基元的觸發程序值MatchBraces加上引動程序值MemberSelect的游標位置之前的語彙基元。
如需詳細資訊,請參閱 大括號對稱 (受管理的封裝架構)。
正在剖析的顏色標示
Colorizing 來源的程式碼相當簡單,只需找出有關該型別語彙基元,並傳回的色彩資訊的型別。 Colorizer類別是編輯器,並掃瞄器提供每個語彙基元的色彩資訊之間的媒介。 Colorizer類別使用IScanner物件中 colorizing 一條線的 [說明及收集原始程式檔中的所有行的狀態資訊。 在 MPF 語言服務中, Colorizer類別並沒有加以覆寫,因為它會與掃描器通訊只能透過IScanner介面。 您提供實作的物件IScanner介面,藉由覆寫GetScanner上的方法LanguageService類別。
IScanner掃瞄器提供一系列的原始程式碼,透過SetSource方法。 要呼叫的方法ScanTokenAndProvideInfoAboutIt方法會取得行中的下一個語彙基元,直到行已用完語彙基元的重複。 顏色標示,MPF 會將所有的原始程式碼視為一系列的行。 因此,掃描器必須能應付成線條即將在它的來源。 此外,任何一行可以在任何時候,傳遞到掃描器,而且唯一保證會掃瞄器接收狀態變數,大概會想要掃描行前寄。
Colorizer類別也可用於識別語彙基元的觸發程序。 這些引動程序告訴 MPF 特定的語彙基元可以啟始更複雜的作業,例如文字自動完成或比對大括號。 用來識別這類引動程序必須快速,而且必須發生在任何位置,因為掃描器最適合這項工作。
如需詳細資訊,請參閱 Colorizing (受管理的封裝架構) 的語法。
剖析功能和範圍
剖析功能和範圍的要求不能只用來識別的型別時所發生的語彙基元。 剖析器,就必須找出而不是只一種語彙基元,語彙基元適用的功能。 比方說,識別項是只是名稱,但您的語言識別項可能是名稱的類別、 命名空間、 方法或變數,內容而定。 一般型別語彙基元可能識別項,但是識別項也可以用其他的意義,取決於它是什麼,以及定義的位置。 這個識別需要具備更多關於剖析時所使用的語言剖析器。 這是要在哪裡AuthoringSink類別進來。 AuthoringSink類別收集的資訊識別項、 方法、 對稱的語言括號 (例如大括號和括號),以及語言 triples (類似於語言組只會有三個部分,比方說,"foreach()""{"和"}")。 此外,您可以覆寫AuthoringSink類別來支援程式碼識別,使用中斷點的早期的驗證,因此偵錯工具並沒有載入,以及自動變數偵錯] 視窗,其中顯示區域變數和參數自動時程式是否正在偵錯,而且需要剖析器,以識別適當的區域變數和除了偵錯工具所提供的參數。
AuthoringSink物件的一部分,會傳遞給剖析器ParseRequest物件和新的AuthoringSink物件是建立每次新的ParseRequest在建立物件。 此外, ParseSource方法必須傳回AuthoringScope物件,它用來處理各種 IntelliSense 作業。 AuthoringScope物件維持 「 宣告 」 清單及清單的方法,或是其中已填入,取決於剖析的原因。 AuthoringScope必須實作的類別。