2016-04-21 16 views
0

メソッドにxmlに<createddate>タグが含まれていないかどうかを検出するアナライザを作成しました。それは正常に動作し、タグを挿入しますが、ルールが修正されていてもビルドエラーが返されます。おそらく意味モデルを使う必要があると思いますか?Roslynはコードフィックスの後にソリューションを更新できません

これは私が持っているものです:タグがxmlの中に存在する場合、ビルドが通るようにする方法として CodeFixProvider.cs

using System; 
using System.Collections.Immutable; 
using System.Composition; 
using System.Linq; 
using System.Threading; 
using System.Threading.Tasks; 
using Microsoft.CodeAnalysis; 
using Microsoft.CodeAnalysis.CodeFixes; 
using Microsoft.CodeAnalysis.CodeActions; 
using Microsoft.CodeAnalysis.CSharp; 
using Microsoft.CodeAnalysis.CSharp.Syntax; 
using Microsoft.CodeAnalysis.Formatting; 
using Microsoft.CodeAnalysis.Simplification; 
using Microsoft.CodeAnalysis.Rename; 

namespace NewAnalyzer 
{ 
    [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(NewAnalyzerCodeFixProvider)), Shared] 
    public class NewAnalyzerCodeFixProvider : CodeFixProvider 
    { 
     private const string title = "Add Createddate"; 

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

     public sealed override FixAllProvider GetFixAllProvider() 
     { 
      // See https://github.com/dotnet/roslyn/blob/master/docs/analyzers/FixAllProvider.md for more information on Fix All Providers 
      return WellKnownFixAllProviders.BatchFixer; 
     } 

     public sealed override Task RegisterCodeFixesAsync(CodeFixContext context) 
     { 
      var diagnostic = context.Diagnostics.First(); 
      var diagnosticSpan = diagnostic.Location.SourceSpan; 
      SyntaxNode root; 
      context.Document.TryGetSyntaxRoot(out root); 

      var syntax = root.FindNode(diagnostic.Location.SourceSpan); 

      var methodDeclarationSyntax = syntax.FirstAncestorOrSelf<MethodDeclarationSyntax>(); 

      var description = "Add created datetime for API endpoint."; 
      var equivalenceKey = "empty string"; 
      context.RegisterCodeFix(CodeAction.Create(description, cancellationToken => CreateChangedDocument(context, methodDeclarationSyntax, cancellationToken), equivalenceKey), diagnostic); 
      return Task.FromResult(0); 
     } 


     /// <summary> 
     /// Create a new method that will contain the changes required to insert a createddate tag into the comments. 
     /// </summary> 
     /// <param name="context">context</param> 
     /// <param name="methodDeclarationSyntax">method declaration syntax</param> 
     /// <param name="cancellationToken">cancellation token</param> 
     /// <returns>new method that contains createddate in the comments</returns> 
     private static async Task<Document> CreateChangedDocument(CodeFixContext context, MethodDeclarationSyntax methodDeclarationSyntax, CancellationToken cancellationToken) 
     { 
      var originalTree = await context.Document.GetSyntaxTreeAsync(cancellationToken); 
      var newTree = await context.Document.GetSyntaxTreeAsync(cancellationToken); 
      var root = await newTree.GetRootAsync(cancellationToken); 

      var documentationComment = methodDeclarationSyntax.GetLeadingTrivia().Select(i => i.GetStructure()).OfType<DocumentationCommentTriviaSyntax>().FirstOrDefault(); 
      var summaryElement = (XmlElementSyntax)documentationComment.Content.FirstOrDefault(x => x is XmlElementSyntax); // works 


      if (documentationComment == null) 
       return context.Document; 

      var newLineText = SyntaxFactory.XmlTextNewLine(SyntaxFactory.TriviaList(), Environment.NewLine, Environment.NewLine, SyntaxFactory.TriviaList()); 

      var createdDateText = 
      SyntaxFactory.XmlText(SyntaxFactory.TokenList(
       SyntaxFactory.XmlTextLiteral(
        SyntaxFactory.TriviaList(), 
        DateTime.UtcNow.ToString("d"), 
        DateTime.UtcNow.ToString("d"), 
        SyntaxFactory.TriviaList()) 
        )); 

      var textList = SyntaxFactory.List<XmlNodeSyntax>(new[] { createdDateText }); 
      var createdDateNode = new XmlNodeSyntax[] 
      { 
       SyntaxFactory.XmlText().AddTextTokens(SyntaxFactory.XmlTextNewLine(SyntaxFactory.TriviaList(), Environment.NewLine, Environment.NewLine, SyntaxFactory.TriviaList())), 
        SyntaxFactory.XmlElement(SyntaxFactory.XmlElementStartTag(SyntaxFactory.XmlName("createddate")).WithLeadingTrivia(SyntaxFactory.DocumentationCommentExterior("/// ")), 
            textList, 
            SyntaxFactory.XmlElementEndTag(SyntaxFactory.XmlName("createddate"))).WithAdditionalAnnotations(Formatter.Annotation, Simplifier.Annotation) 
      }; 

      var list = SyntaxFactory.List<XmlNodeSyntax>(createdDateNode); 
      SyntaxNode tempNode = documentationComment.InsertNodesAfter(summaryElement, list); 

      var newRoot = root.ReplaceNode(documentationComment, tempNode); 
      var semanticModel = await context.Document.GetSemanticModelAsync(cancellationToken); 
      var typeSymbol = semanticModel.GetDeclaredSymbol(methodDeclarationSyntax, cancellationToken); 

      var semModel = await context.Document.GetSemanticModelAsync(); 
      var compilation = semModel.Compilation.ReplaceSyntaxTree(originalTree, newTree); 

      var oldSemModel = await context.Document.GetSemanticModelAsync(); 
      oldSemModel = semanticModel; 
      return context.Document; 
     } 
    } 
} 

そしてDiagnosticAnalyzer.cs

using System; 
using System.Collections.Generic; 
using System.Collections.Immutable; 
using System.Linq; 
using System.Threading; 
using Microsoft.CodeAnalysis; 
using Microsoft.CodeAnalysis.CSharp; 
using Microsoft.CodeAnalysis.CSharp.Syntax; 
using Microsoft.CodeAnalysis.Diagnostics; 

namespace NewAnalyzer 
{ 
    [DiagnosticAnalyzer(LanguageNames.CSharp)] 
    public class NewAnalyzerAnalyzer : DiagnosticAnalyzer 
    { 
     public const string DiagnosticId = "NA001"; 

     // You can change these strings in the Resources.resx file. If you do not want your analyzer to be localize-able, you can use regular strings for Title and MessageFormat. 
     // See https://github.com/dotnet/roslyn/blob/master/docs/analyzers/Localizing%20Analyzers.md for more on localization 
     private static readonly LocalizableString Title = "Title: createddate is missing"; 
     private static readonly LocalizableString MessageFormat = "Format: createddate is missing"; 
     private static readonly LocalizableString Description = "Desc: createddate is missing"; 
     private const string Category = "Naming"; 

     private static DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Error, isEnabledByDefault: true, description: Description); 

     public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } } 

     public override void Initialize(AnalysisContext context) 
     { 
      // TODO: Consider registering other actions that act on syntax instead of or in addition to symbols 
      // See https://github.com/dotnet/roslyn/blob/master/docs/analyzers/Analyzer%20Actions%20Semantics.md for more information 
      //context.RegisterSymbolAction(AnalyzeSymbol, SymbolKind.NamedType); 
      context.RegisterSymbolAction(AnalyzeMethod, SymbolKind.Method); 
     } 

     /// <summary> 
     /// Analyze method to see if it's a REST endpoint method 
     /// </summary> 
     /// <param name="context">context</param> 
     private static void AnalyzeMethod(SymbolAnalysisContext context) 
     { 
      var methodDeclarationNode = context.Symbol.GetDocumentationCommentXml(); 

      if (methodDeclarationNode != null) 
      { 
       if (!methodDeclarationNode.Contains("createddate")) 
       { 
        var diagnostic = Diagnostic.Create(Rule, context.Symbol.Locations[0], methodDeclarationNode); 
        context.ReportDiagnostic(diagnostic); 
       } 
      } 
     } 
    } 
} 

任意のアイデア?実際にはソリューションを更新していないようですね。

答えて

0

context.RegisterSymbolAction(AnalyzeMethod, SymbolKind.Method)は、プロパティゲッターとセッターのコールバックも実行します。報告された場所のMethodDeclarationSyntaxが見つからないため、コードフィックスのプロパティに失敗しています。

なぜこの機能をシンボルベースのアナライザとして実装しましたか?これは、構文ノードベースのもので、MethodDeclarationに登録することができます。

また、コード番号documentationCommentnullとなりますが、その場合はContentとなり、失敗する可能性もあります。

これらのコード以外は、現在の時刻を追加します。

これらはすべて、拡張機能のデバッグを開始するときに表示されます。おそらく、CLR例外をすべて破るためにException Settingsウィンドウを見てください。

+0

これは機能しません。それをメソッド宣言として持つと、ビルドエラーではなくIDEエラーとして返されます。これはsemanticModelAnalysisコンテキストですか? –

+0

申し訳ありませんが、何が動作しないのか分かりません。あなたはもう少し問題を説明できますか? – Tamas

+0

私はあなたにコードを送るべきです、methoddeclarationsyntaxを使用してビルドエラーをスローしません。コードを共有できる方法はありますか? –

関連する問題