重新格式化程式碼 (受管理的封裝架構)
在Visual Studio可以重新格式化來源程式碼,藉由使用縮排和泛空白字元的正常化。 這可包括插入或移除空格或 tab 字元,每一行的開頭,加入新行行間的情況下,或以定位點或空格與 tab 字元取代空格。
![]() |
---|
附註插入或刪除新行字元也可能會影響資料標記,例如中斷點和書籤,但新增或移除空格或 tab 字元並不會影響資料標記。 |
使用者可以選取啟動 reformatting 作業格式化選取範圍 或 格式化文件 的 進階 上的功能表 編輯功能表。 當您插入程式碼片段] 或 [特殊字元時,也會觸發 reformatting 的作業。 比方說,您可以鍵入右邊大括號在 C# 中,開啟對稱的大括號和右大括弧之間的所有項目時自動縮排至適當的層級。
當Visual Studio傳送格式化選取範圍或格式的文件命令到 「 語言 」 服務, ViewFilter類別呼叫ReformatSpan中的方法Source類別。 若要支援的格式設定,您必須覆寫ReformatSpan方法,並提供您自己的格式化程式碼。
啟用支援重新格式化
若要支援的格式設定, EnableFormatSelection參數的ProvideLanguageServiceAttribute必須設定成true當您註冊您的 VSPackage。 這會將EnableFormatSelection屬性,以true。 CanReformat方法會傳回這個屬性的值。 如果為 true,則會傳回ViewFilter類別呼叫ReformatSpan。
實作重新格式化
若要實作重新格式化,您必須衍生類別,以從Source類別並覆寫ReformatSpan方法。 TextSpan物件將告訴您要設定格式的範圍和EditArray物件會保留在範圍上所進行的編輯。 請注意這個範圍可以是整份文件。 不過,因為有可能是多個範圍所做的變更,所有的變更應該以單一動作可還原。 若要這樣做,換行中的所有變更CompoundAction物件 (請參閱本主題中的 〈 使用 CompoundAction 類別 〉 一節)。
範例
下面範例確保單一空格之後每個逗點中沒有選取範圍,除非逗號後按下 tab 鍵,或位於行尾。 後端空格之後也會刪除行中的最後一個逗號。 若要從會呼叫這個方法,請參閱本主題中的 「 使用 CompoundAction 類別 」 一節,請參閱ReformatSpan方法。
using Microsoft.VisualStudio.Package;
using Microsoft VisualStudio.TextManager.Interop;
namespace MyLanguagePackage
{
class MySource : Source
{
private void DoFormatting(EditArray mgr, TextSpan span)
{
// Make sure there is one space after every comma unless followed
// by a tab or comma is at end of line.
IVsTextLines pBuffer = GetTextLines();
if (pBuffer != null)
{
int startIndex = span.iStartIndex;
int endIndex = 0;
string line = "";
// Loop over all lines in span
for (int i = span.iStartLine; i <= span.iEndLine; i++)
{
if (i < span.iEndLine)
{
pBuffer.GetLengthOfLine(i, out endIndex);
}
else
{
endIndex = span.iEndIndex;
}
pBuffer.GetLineText(i, startIndex, i, endIndex, out line);
if (line.Length > 0)
{
int index = 0;
// Loop over all commas in line
while ((index = line.IndexOf(',', index)) != -1)
{
int spaceIndex = index + 1;
// Determine how many spaces after comma
while (spaceIndex < line.Length && line[spaceIndex] == ' ')
{
++spaceIndex;
}
int spaceCount = spaceIndex - (index + 1);
string replacementText = " ";
bool fDoEdit = true;
TextSpan editTextSpan = new TextSpan();
editTextSpan.iStartLine = i;
editTextSpan.iEndLine = i;
editTextSpan.iStartIndex = index + 1;
if (spaceIndex == line.Length)
{
if (spaceCount > 0)
{
// Delete spaces after a comma at end of line
editTextSpan.iEndIndex = spaceIndex;
replacementText = "";
}
else
{
// Otherwise, do not add spaces if comma is
// at end of line.
fDoEdit = false;
}
}
else if (spaceCount == 0)
{
if (spaceIndex < line.Length && line[spaceIndex] == '\t')
{
// Do not insert space if a tab follows
// a comma.
fDoEdit = false;
}
else
{
// No space after comma so add a space.
editTextSpan.iEndIndex = index + 1;
}
}
else if (spaceCount > 1)
{
// More than one space after comma, replace
// with a single space.
editTextSpan.iEndIndex = spaceIndex;
}
else
{
// Single space after a comma and not at end
// of the line, leave it alone.
fDoEdit = false;
}
if (fDoEdit)
{
// Add edit operation
mgr.Add(new EditSpan(editTextSpan, replacementText));
}
index = spaceIndex;
}
}
startIndex = 0; // All subsequent lines start at 0
}
// Apply all edits
mgr.ApplyEdits();
}
}
}
}
使用 CompoundAction 類別
所有在一段程式碼上進行格式化應該以單一動作可還原。 這可以透過CompoundAction類別。 這個類別會包裝一段文字緩衝區成一個單一的編輯作業的編輯作業。
範例
以下是如何使用範例CompoundAction類別。 請參閱本主題的範例,「 實作支援的格式 」 一節中的範例DoFormatting方法。
using Microsoft.VisualStudio.Package;
using Microsoft VisualStudio.TextManager.Interop;
namespace MyLanguagePackage
{
class MySource : Source
{
public override void ReformatSpan(EditArray mgr, TextSpan span)
{
string description = "Reformat code";
CompoundAction ca = new CompoundAction(this, description);
using (ca)
{
ca.FlushEditActions(); // Flush any pending edits
DoFormatting(mgr, span); // Format the span
}
}
}
}