2017-03-01 28 views
2

我是Roslyn的新手。我正在編寫一個代碼修復提供程序,它將foreach塊轉換爲遍歷Select的結果,例如,如何使用Roslyn將語句插入具有規格化空白的塊中?

foreach (var item in new int[0].Select(i => i.ToString())) 
{ 
    ... 
} 

foreach (int i in new int[0]) 
{ 
    var item = i.ToString(); 
    ... 
} 

要做到這一點,我需要在BlockSyntax的表示foreachForEachStatementSyntax內開始插入語句。這裏是我的代碼爲:

var blockStatement = forEach.Statement as BlockSyntax; 
if (blockStatement == null) 
{ 
    return document; 
} 
forEach = forEach.WithStatement(
    blockStatment.WithStatements(
     blockStatement.Statements.Insert(0, selectorStatement)); 

不幸的是,這樣做導致的空白被關閉:

  foreach (int i in new int[0]) 
      { 
var item = i.ToString(); 
       ... 
      } 

我Google了這個解決方案。我遇到了this answer,推薦使用Formatter.FormatSyntaxNode.NormalizeWhitespace

  • 我不能使用Formatter.Format,因爲這需要一個Workspace參數,它看起來我沒有訪問WorkspaceRoslyn: Current Workspace in Diagnostic with code fix project

  • 我試着在文檔的語法根目錄上使用NormalizeWhitespace(),但它侵入性地格式化了與修正無關的其他代碼。我試圖用它在與foreach塊關聯的ForEachStatementSyntax上,然後調用syntaxRoot = syntaxRoot.ReplaceNode(oldForEach, newForEach),但導致整個foreach而不是正確縮進。

    namespace ConsoleApp1 
    { 
        class Program 
        { 
         static void Main(string[] args) 
         { 
          var array = new int[0]; 
          int length = array.Length; 
    
    foreach (int i in array) 
    { 
        string item = i.ToString(); 
    }  } 
        } 
    } 
    

那麼,是否可以簡單地插入在首位的正確縮進的聲明,而無需格式化其他的代碼?

感謝。

回答

2

您可以將Formatter Annotation添加到您想要的格式上使用WithAdditionalAnnotations

blockStatement.Statements.Insert(0, selectorStatement.WithAdditionalAnnotations(Formatter.Annotation))

+0

感謝這麼多運行的節點!像魅力一樣工作。出於好奇,你知道*爲什麼*添加註釋會導致語句格式化?當我看[Roslyn源代碼](http://source.roslyn.io/#Microsoft.CodeAnalysis.Workspaces/Formatting/Formatter.cs,24)時,我發現它初始化爲一個普通的'new SyntaxAnnotation()' 。 –

+0

SyntaxAnnotation在創建時會增加一個全局ID,因此如果'someAnnotation'實際上是對同一個實例的引用,'Formatter.Annotation == someAnnotation'將僅爲真。 –