CGC_Codes

XmlDocumentationAnalyzer

Feb 21st, 2017
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.64 KB | None | 0 0
  1. using Microsoft.CodeAnalysis;
  2. using Microsoft.CodeAnalysis.CSharp;
  3. using Microsoft.CodeAnalysis.CSharp.Syntax;
  4. using Microsoft.CodeAnalysis.Diagnostics;
  5. using System.Collections.Generic;
  6. using System.Collections.Immutable;
  7. using System.Linq;
  8. using CodeCracker.Properties;
  9.  
  10. namespace CodeCracker.CSharp.Maintainability
  11. {
  12.     [DiagnosticAnalyzer(LanguageNames.CSharp)]
  13.     public sealed class XmlDocumentationAnalyzer : DiagnosticAnalyzer
  14.     {
  15.         internal static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.XmlDocumentationAnalyzer_Title), Resources.ResourceManager, typeof(Resources));
  16.  
  17.         internal static readonly DiagnosticDescriptor RuleMissingInCSharp = new DiagnosticDescriptor(
  18.             DiagnosticId.XmlDocumentation_MissingInCSharp.ToDiagnosticId(),
  19.             Title,
  20.             Title,
  21.             SupportedCategories.Maintainability,
  22.             DiagnosticSeverity.Info,
  23.             isEnabledByDefault: true,
  24.             helpLinkUri: HelpLink.ForDiagnostic(DiagnosticId.XmlDocumentation_MissingInCSharp));
  25.  
  26.         internal static readonly DiagnosticDescriptor RuleMissingInXml = new DiagnosticDescriptor(
  27.             DiagnosticId.XmlDocumentation_MissingInXml.ToDiagnosticId(),
  28.             Title,
  29.             Title,
  30.             SupportedCategories.Maintainability,
  31.             DiagnosticSeverity.Warning,
  32.             isEnabledByDefault: true,
  33.             helpLinkUri: HelpLink.ForDiagnostic(DiagnosticId.XmlDocumentation_MissingInXml));
  34.  
  35.         public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(RuleMissingInCSharp, RuleMissingInXml);
  36.  
  37.         public override void Initialize(AnalysisContext context) => context.RegisterSyntaxNodeAction(Analyzer, SyntaxKind.SingleLineDocumentationCommentTrivia);
  38.  
  39.         private static void Analyzer(SyntaxNodeAnalysisContext context)
  40.         {
  41.             if (context.IsGenerated()) return;
  42.             var documentationNode = (DocumentationCommentTriviaSyntax)context.Node;
  43.             var method = GetMethodFromXmlDocumentation(documentationNode);
  44.             if (method == null) return;
  45.             var elementNames = documentationNode.Content
  46.                                 .OfType<XmlEmptyElementSyntax>()
  47.                                 .Select(element => element.Name?.LocalName.ValueText);
  48.             if (elementNames.Contains("inheritdoc")) return;
  49.             var methodParameters = method.ParameterList.Parameters;
  50.             var xElementsWitAttrs = documentationNode.Content.OfType<XmlElementSyntax>()
  51.                                     .Where(xEle => xEle.StartTag?.Name?.LocalName.ValueText == "param")
  52.                                     .SelectMany(xEle => xEle.StartTag.Attributes, (xEle, attr) => attr as XmlNameAttributeSyntax)
  53.                                     .Where(attr => attr != null);
  54.  
  55.             var keys = methodParameters.Select(parameter => parameter.Identifier.ValueText)
  56.                 .Union(xElementsWitAttrs.Select(x => x.Identifier?.Identifier.ValueText))
  57.                 .ToImmutableHashSet();
  58.  
  59.             var parameterWithDocParameter = (from key in keys
  60.                                              where key != null
  61.                                              let Parameter = methodParameters.FirstOrDefault(p => p.Identifier.ValueText == key)
  62.                                              let DocParameter = xElementsWitAttrs.FirstOrDefault(p => p.Identifier?.Identifier.ValueText== key)
  63.                                              select new { Parameter, DocParameter });
  64.  
  65.             if (parameterWithDocParameter.Any(p => p.Parameter == null))
  66.             {
  67.                 var diagnostic = Diagnostic.Create(RuleMissingInCSharp, documentationNode.GetLocation());
  68.                 context.ReportDiagnostic(diagnostic);
  69.             }
  70.  
  71.             if (parameterWithDocParameter.Any(p => p.DocParameter == null))
  72.             {
  73.                 var diagnostic = Diagnostic.Create(RuleMissingInXml, documentationNode.GetLocation());
  74.                 context.ReportDiagnostic(diagnostic);
  75.             }
  76.         }
  77.  
  78.         private static MethodDeclarationSyntax GetMethodFromXmlDocumentation(DocumentationCommentTriviaSyntax doc)
  79.         {
  80.             var tokenParent = doc.ParentTrivia.Token.Parent;
  81.             var method = tokenParent as MethodDeclarationSyntax;
  82.             if (method == null)
  83.             {
  84.                 var attributeList = tokenParent as AttributeListSyntax;
  85.                 if (attributeList == null) return null;
  86.                 method = attributeList.Parent as MethodDeclarationSyntax;
  87.             }
  88.             return method;
  89.         }
  90.     }
  91. }
Add Comment
Please, Sign In to add comment