大括號對稱 (受管理的封裝架構)
括號對稱會幫助開發人員追蹤需要如括號和大括號放在一起,就會發生的語言項目。 當開發人員輸入右括號時,左括號會反白顯示。
您可以比對兩個或三個 co-occurring 的項目,稱為成對及 triples。 Triples 是 co-occurring 的三個項目集。 例如,在 C# foreach陳述式形成三:"foreach()","{",和"}"。 輸入右括號時,會反白顯示三個項目。
AuthoringSink類別支援配對,並使用 triples MatchPair和MatchTriple方法。
實作
語言服務,就必須找出所有相符的項目在語言中,並接著找出所有配對成功。 這通常透過實作IScanner偵測到相符的語言,然後將ParseSource方法,以符合的項目。
OnCommand方法會呼叫 token 化的列,並傳回前面插入號的語彙基元掃描器。 掃瞄器表示的語言項目組藉由將值設定為語彙基元的觸發程序找到MatchBraces上目前的語彙基元。 OnCommand方法呼叫MatchBraces方法,依序呼叫BeginParse方法,以剖析原因值MatchBraces找不到相符的語言項目。 當找到相符的語言項目時,會反白顯示這兩個項目。
輸入在括號觸發方式大括號反白顯示的完整說明,請參閱主題的 「 範例剖析作業 」 一節語言服務剖析及掃描程式 (受管理的封裝架構)。
啟用支援括號對稱
ProvideLanguageServiceAttribute屬性可以設定MatchBraces, MatchBracesAtCaret,以及ShowMatchingBrace具名參數設定相對應的屬性, LanguagePreferences類別。 使用者也可以設定語言喜好設定的屬性。
登錄項目 |
屬性 |
描述 |
---|---|---|
MatchBraces |
啟用括號對稱 |
|
MatchBracesAtCaret |
啟用插入號所在的括號對稱會移動。 |
|
ShowMatchingBrace |
會反白顯示對稱的括號。 |
符合的條件陳述式
您也可以符合條件陳述式,例如if, else if,和else,或#if, #elif, #else, #endif,相同的方式,以符合分隔字元。 您可以子類別化AuthoringSink類別,並提供一種方法,可將文字新增跨越以及內部的相符項目陣列的分隔符號。
設定觸發程序
下列範例會示範如何偵測到相符的括號、 大括號和方括號包住,以及設定觸發程序為它掃描器。 OnCommand上的方法Source類別會偵測觸發程序,並會呼叫剖析器找到相符的配對 (請參閱本主題中的 「 尋找匹配 」 一節)。 這個範例是僅供說明。 它會假設您的掃描器包含方法GetNextToken的識別,並傳回從文字行的語彙基元。
using Microsoft.VisualStudio.Package;
using Microsoft.VisualStudio.TextManager.Interop;
namespace TestLanguagePackage
{
public class TestScanner : IScanner
{
private const string braces = "()[]{}";
private Lexer lex;
public bool ScanTokenAndProvideInfoAboutIt(TokenInfo tokenInfo,
ref int state)
{
bool foundToken = false;
string token = lex.GetNextToken();
if (token != null)
{
foundToken = true;
char firstChar = token[0];
if (Char.IsPunctuation(firstChar) && token.Length == 0)
{
if (braces.IndexOf(c) != -1)
{
tokenInfo.Trigger = TokenTriggers.MatchBraces;
}
}
}
return foundToken;
}
比對大括號
下面是一個簡單的例子如對應語言項目 {} (),[]] 及 [新增至其 span AuthoringSink物件。 此方法不是建議的方法,以剖析原始程式碼 ; 它是僅供說明。
using Microsoft.VisualStudio.Package;
using Microsoft.VisualStudio.TextManager.Interop;
namespace TestLanguagePackage
{
public class Parser
{
private IList<TextSpan[]> m_braces;
public IList<TextSpan[]> Braces
{
get { return m_braces; }
}
private void AddMatchingBraces(TextSpan braceSpan1, TextSpan braceSpan2)
{
if IsMatch(braceSpan1, braceSpan2)
m_braces.Add(new TextSpan[] { braceSpan1, braceSpan2 });
}
private bool IsMatch(TextSpan braceSpan1, TextSpan braceSpan2)
{
//definition for matching here
}
}
public class TestLanguageService : LanguageService
{
Parser parser = new Parser();
Source source = (Source) this.GetSource(req.FileName);
private AuthoringScope ParseSource(ParseRequest req)
{
if (req.Sink.BraceMatching)
{
if (req.Reason==ParseReason.MatchBraces)
{
foreach (TextSpan[] brace in parser.Braces)
{
req.Sink.MatchPair(brace[0], brace[1], 1);
}
}
}
return new TestAuthoringScope();
}
}
}