2017-11-20 12 views
0

私は最近CodeAnalyzersとCodeFixesを使い始めました。C#CodeFixes:codefixが表示される最小要件

もちろん、sdk()が付いたテンプレートが動作します。しかし、私が上に行くと、codefixはデバッグ時にもう表示されません。

診断が正常に行われたときに歩くと、 しかし、codefix(Strg +。)はもう見えません。私はDiagnostic-Id、等価鍵の世話をしました...しかし、なぜ私はコードフィックスをもう表示されないのか分かりません。だから、診断のために表示されるべきコードフィックスのための最小限の "要件"は何ですか?ここで


アナライザのコードです:

[DiagnosticAnalyzer(LanguageNames.CSharp)] 
public class VirtualMemberAnalyzer : DiagnosticAnalyzer 
{ 
    public const string PublicVirtualMethod_DiagnosticId = "PublicVirtualMethod"; 

    private const string Category = "Naming"; 

    private static readonly DiagnosticDescriptor PublicMethodVirtualRule = new DiagnosticDescriptor(
     PublicVirtualMethod_DiagnosticId, 
     "public methode not virtual", 
     "every public methode must be virtual", 
     Category, 
     DiagnosticSeverity.Error, 
     true); 

    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => 
     ImmutableArray.Create(PublicMethodVirtualRule); 

    public override void Initialize(AnalysisContext context) 
    { 
     context.RegisterSymbolAction(AnalyzeSymbol, SymbolKind.NamedType); 
    } 

    private static void AnalyzeSymbol(SymbolAnalysisContext context) 
    { 
     var namedTypeSymbol = (INamedTypeSymbol)context.Symbol; 

     foreach (var methodSymbol in namedTypeSymbol.GetMembers().OfType<IMethodSymbol>()) 
     { 
      if (methodSymbol.MethodKind == MethodKind.Ordinary && !methodSymbol.IsStatic && !methodSymbol.IsVirtual && methodSymbol.DeclaredAccessibility == Accessibility.Public) 
      { 
       var diagnostic = Diagnostic.Create(
        PublicMethodVirtualRule, 
        methodSymbol.Locations[0], 
        methodSymbol.Name); 
       context.ReportDiagnostic(diagnostic); 
      } 
     } 
    } 
} 

そしてCodefix-プロバイダの:

[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(VirtualMemberAnalyzersCodeFixProvider)), Shared] 
public class VirtualMemberAnalyzersCodeFixProvider : CodeFixProvider { 
    private const string title_property = "Make property virtual"; 
    private const string title_method = "Make method virtual"; 

    public sealed override ImmutableArray<string> FixableDiagnosticIds { 
     get { 
      return ImmutableArray.Create(VirtualMemberAnalyzer.PublicVirtualMethod_DiagnosticId); 
     } 
    } 

    public sealed override FixAllProvider GetFixAllProvider() { 
     return WellKnownFixAllProviders.BatchFixer; 
    } 

    public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { 
     var root = await context.Document.GetSyntaxRootAsync(); 

     var diagnostic = context.Diagnostics.First(); 
     var diagnosticSpan = diagnostic.Location.SourceSpan; 

     var methodDeclarations = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType<MethodDeclarationSyntax>().FirstOrDefault(); 

     if (methodDeclarations != null) { 
      CodeAction codeAction = CodeAction.Create(title_method, c => MakeVirtual(context.Document, methodDeclarations, c), equivalenceKey: title_method); 
      context.RegisterCodeFix(codeAction, diagnostic); 
     } 
    } 

    private async Task<Document> MakeVirtual(Document document, MethodDeclarationSyntax memberDeclaration, CancellationToken cancellationToken) 
    { 
     SyntaxTokenList memberDeclarationModifiers = memberDeclaration.Modifiers; 
     memberDeclarationModifiers.Add(SyntaxFactory.Token(SyntaxKind.VirtualKeyword)); 
     MethodDeclarationSyntax methodDeclarationSyntax = memberDeclaration.WithModifiers(memberDeclarationModifiers); 

     var oldRoot = await document.GetSyntaxRootAsync(cancellationToken); 
     var newRoot = oldRoot.ReplaceNode(memberDeclaration, methodDeclarationSyntax); 

     return document.WithSyntaxRoot(newRoot); 
    } 
} 

答えて

0

memberDeclarationModifiers.Add(SyntaxFactory.Token(SyntaxKind.VirtualKeyword));戻り新しいSyntaxTokenListが。あなたは新しい作成されたリストを使用していません。 SyntaxTreesはRoslynでは不変であることに注意してください。ツリー内のすべての変更は新しいツリーを作成します。あなたのローズリンコードフィックスのコードフィックスは次のとおりです。

private async Task<Document> MakeVirtual(Document document, MethodDeclarationSyntax memberDeclaration, CancellationToken cancellationToken) 
{ 
    var methodDeclarationSyntax = 
     memberDeclaration.WithModifiers(
      memberDeclaration.Modifiers.Add(SyntaxFactory.Token(SyntaxKind.VirtualKeyword))); 

    var oldRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); 
    var newRoot = oldRoot.ReplaceNode(memberDeclaration, methodDeclarationSyntax); 

    return document.WithSyntaxRoot(newRoot); 
} 
関連する問題