2014-11-02 54 views
10

我前幾天在TechEd,我看到this talk by Kevin Pilch-Bisson (relevent part starts at about 18 minutes) ......我覺得這很酷,所以我決定和Roslyn一起玩。將訪問修飾符添加到使用Roslyn CodeFixProvider的方法?

我想有一條規定, 「訪問修飾符必須聲明」(了StyleCop SA1400) - 這意味着,

這違反了規則:

static void Main(string[] args) 
    { 
    } 

這是確定的:

public static void Main(string[] args) 
    { 
    } 

它必須有一個明確的內部關鍵字,關鍵字public,private關鍵字,或親檢測關鍵字。

檢測違規是相當容易的,但現在我試圖提供一個修復程序。我一直在嘗試和搜索各處,但我無法找到如何添加訪問修飾符。

這是我到目前爲止有:

public async Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, TextSpan span, IEnumerable<Diagnostic> diagnostics, CancellationToken cancellationToken) 
{ 
    var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); 
    var token = root.FindToken(span.Start); 

    var methodDeclaration = token.Parent as MethodDeclarationSyntax; 

    //var newModifiers = methodDeclaration.Modifiers.Add(SyntaxFactory.AccessorDeclaration(SyntaxKind.PublicKeyword));   
    //var newModifiers = new SyntaxTokenList() { new SyntaxToken() }; 

    MethodDeclarationSyntax newMethodDeclaration = methodDeclaration.WithModifiers(methodDeclaration.Modifiers); 
    var newRoot = root.ReplaceNode(methodDeclaration, newMethodDeclaration); 
    var newDocument = document.WithSyntaxRoot(newRoot); 

    return new[] { CodeAction.Create("Add Public Keyword", newDocument) }; 
} 

WithModifiers需要SyntaxTokenList,我可以新建(),但我不知道如何使它的SyntaxKind.PublicKeyword。我也不確定我是否想要新的它,或者使用SyntaxFactory。然而,在使用時SyntaxFactory,我也想不通,我需要創建的SyntaxKind.PublicKeyword

一個SyntaxToken我可以張貼整個事情,包括DiagnosticAnalyzer如果有興趣哪一種方法......

回答

3

其實我需要的是這樣的:

var newModifiers = SyntaxFactory.TokenList(SyntaxFactory.Token(accessModifierToken)) 
.AddRange(methodDeclaration.Modifiers); 

它幾乎什麼克里斯Eelmaa建議,但與此建議我結束了static public void Main這是有效的,但醜陋。

追加公共將它添加到列表的末尾,據我所知,訪問修飾符應始終是第一個。

+1

看起來不錯,除了你有一個未使用的本地「公共令牌列表」。你的Func將被調用來創建預覽以及點擊時,但是應該沒問題。 – 2014-11-02 21:23:23

+0

好的,謝謝:)。 publicTokenList,通常resharper告訴我有關這些,但因爲我在vs14工作,它沒有.. – 2014-11-02 21:48:27

1

好,創建一個修飾符表示public static,您可以使用此:

var modifiers = SyntaxFactory.TokenList(
    new SyntaxToken[] { 
     SyntaxFactory.Token(SyntaxKind.PublicKeyword), 
     SyntaxFactory.Token(SyntaxKind.StaticKeyword) 
    }), 

但在你的情況,我不明白爲什麼

var updatedModifiers = methodDeclaration 
       .Modifiers 
       .Add(SyntaxFactory.Token(SyntaxKind.PublicKeyword)); 

methodDeclaration.WithModifiers(updatedModifiers); 

不起作用。

+0

第一個建議不起作用,因爲你明顯並不總是需要靜態的,但我只是想解釋它的語法......儘管如此,第二個建議也並不真正起作用,它導致了'static public void Main '或靜態publicvoid Main – 2014-11-02 20:43:19

+0

@RonSijm,+1。如果你清理你的答案並且只輸入相關的東西(例如,擺脫'GetFixesAsync'和'CreateAction')並接受它,我就沒有問題。這是一個很好的問題。 – 2014-11-03 14:39:59

6

很高興你喜歡這個話題!實際上,我們在語法模型的一些助手,使其更容易將項目添加到列表,所以你應該能夠做這樣的事情:

var newMethodDeclaration = methodDeclaration.AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword)); 

要獲得新的方法聲明。

的這種擴展形式會是這樣的:

var newModifiers = SyntaxFactory.TokenList(modifiers.Concat(new[] { SyntaxFactory.Token(SyntaxKind.PublicKeyword)})); 
var newMethodDeclaration = methodDeclaration.WithModifiers(newModifiers); 

希望這有助於

+0

我很喜歡這個話題!關於我在教室裏看到的最好的演講,以及Async之一:) - 無論如何,你的建議有些作品,但我最終得到了'static public void Main'。我已經添加了我自己的解決方案,似乎工作。如果可以審查,如果我做了一些奇怪的事情,那會很棒。它是我爲Roslyn做的第一件事,所以可能有一些東西需要改進 – 2014-11-02 20:48:00

+0

哦,順便說一句,爲什麼AnalyzeNode的語法是這樣的:'public void AnalyzeNode(SyntaxNode node,SemanticModel semanticModel,Action addDiagnostic' and not this :'public Action AnalyzeNode(SyntaxNode node,SemanticModel semanticModel'?看起來有點奇怪 – 2014-11-02 21:11:33

+1

因爲你可以報告多個診斷,並且讓它們成爲回調讓我們避免了一些分配,並且在你報告結果異步 – 2014-11-02 21:25:01