44namespace StyleCop . Analyzers . DocumentationRules
55{
66 using System ;
7+ using System . Collections . Generic ;
78 using System . Collections . Immutable ;
9+ using System . Linq ;
10+ using System . Xml . Linq ;
811 using Microsoft . CodeAnalysis ;
9- using Microsoft . CodeAnalysis . CSharp ;
1012 using Microsoft . CodeAnalysis . CSharp . Syntax ;
1113 using Microsoft . CodeAnalysis . Diagnostics ;
1214 using StyleCop . Analyzers . Helpers ;
@@ -26,7 +28,7 @@ namespace StyleCop.Analyzers.DocumentationRules
2628 /// </remarks>
2729 [ DiagnosticAnalyzer ( LanguageNames . CSharp ) ]
2830 [ NoCodeFix ( "Cannot generate documentation" ) ]
29- internal class SA1614ElementParameterDocumentationMustHaveText : DiagnosticAnalyzer
31+ internal class SA1614ElementParameterDocumentationMustHaveText : ElementDocumentationParameterBase
3032 {
3133 /// <summary>
3234 /// The ID for diagnostics produced by the <see cref="SA1614ElementParameterDocumentationMustHaveText"/>
@@ -41,47 +43,68 @@ internal class SA1614ElementParameterDocumentationMustHaveText : DiagnosticAnaly
4143 private static readonly DiagnosticDescriptor Descriptor =
4244 new DiagnosticDescriptor ( DiagnosticId , Title , MessageFormat , AnalyzerCategory . DocumentationRules , DiagnosticSeverity . Warning , AnalyzerConstants . EnabledByDefault , Description , HelpLink ) ;
4345
44- private static readonly Action < CompilationStartAnalysisContext > CompilationStartAction = HandleCompilationStart ;
45- private static readonly Action < SyntaxNodeAnalysisContext > XmlElementAction = HandleXmlElement ;
46- private static readonly Action < SyntaxNodeAnalysisContext > XmlEmptyElementAction = HandleXmlEmptyElement ;
46+ public SA1614ElementParameterDocumentationMustHaveText ( )
47+ : base ( inheritDocSuppressesWarnings : true )
48+ {
49+ }
4750
4851 /// <inheritdoc/>
4952 public override ImmutableArray < DiagnosticDescriptor > SupportedDiagnostics { get ; } =
5053 ImmutableArray . Create ( Descriptor ) ;
5154
5255 /// <inheritdoc/>
53- public override void Initialize ( AnalysisContext context )
54- {
55- context . RegisterCompilationStartAction ( CompilationStartAction ) ;
56- }
57-
58- private static void HandleCompilationStart ( CompilationStartAnalysisContext context )
56+ protected override void HandleXmlElement ( SyntaxNodeAnalysisContext context , IEnumerable < XmlNodeSyntax > syntaxList , XElement completeDocumentation , params Location [ ] diagnosticLocations )
5957 {
60- context . RegisterSyntaxNodeActionHonorExclusions ( XmlElementAction , SyntaxKind . XmlElement ) ;
61- context . RegisterSyntaxNodeActionHonorExclusions ( XmlEmptyElementAction , SyntaxKind . XmlEmptyElement ) ;
62- }
58+ bool includeElementPresent = completeDocumentation != null ;
59+ if ( includeElementPresent )
60+ {
61+ var xmlParameterNames = completeDocumentation . Nodes ( )
62+ . OfType < XElement > ( )
63+ . Where ( e => e . Name == XmlCommentHelper . ParamXmlTag )
64+ . Select ( x =>
65+ {
66+ return new Tuple < bool , Location > ( XmlCommentHelper . IsConsideredEmpty ( x ) , null ) ;
67+ } )
68+ . ToImmutableArray ( ) ;
6369
64- private static void HandleXmlElement ( SyntaxNodeAnalysisContext context )
65- {
66- XmlElementSyntax emptyElement = context . Node as XmlElementSyntax ;
70+ VerifyParameters ( context , xmlParameterNames , diagnosticLocations . First ( ) ) ;
71+ }
72+ else if ( syntaxList != null )
73+ {
74+ var xmlParameterNames = syntaxList
75+ . Where ( x => string . Equals ( GetName ( x ) ? . ToString ( ) , XmlCommentHelper . ParamXmlTag ) )
76+ . Select ( x =>
77+ {
78+ bool isEmpty = x is XmlEmptyElementSyntax || XmlCommentHelper . IsConsideredEmpty ( x ) ;
79+ var location = x . GetLocation ( ) ;
6780
68- var name = emptyElement ? . StartTag ? . Name ;
81+ return new Tuple < bool , Location > ( isEmpty , location ) ;
82+ } )
83+ . ToImmutableArray ( ) ;
6984
70- if ( string . Equals ( name . ToString ( ) , XmlCommentHelper . ParamXmlTag ) && XmlCommentHelper . IsConsideredEmpty ( emptyElement ) )
71- {
72- context . ReportDiagnostic ( Diagnostic . Create ( Descriptor , emptyElement . GetLocation ( ) ) ) ;
85+ VerifyParameters ( context , xmlParameterNames , diagnosticLocations . First ( ) ) ;
7386 }
7487 }
7588
76- private static void HandleXmlEmptyElement ( SyntaxNodeAnalysisContext context )
89+ private static void VerifyParameters ( SyntaxNodeAnalysisContext context , ImmutableArray < Tuple < bool , Location > > documentationParameters , Location identifierLocation )
7790 {
78- XmlEmptyElementSyntax emptyElement = context . Node as XmlEmptyElementSyntax ;
91+ var index = 0 ;
7992
80- if ( string . Equals ( emptyElement ? . Name . ToString ( ) , XmlCommentHelper . ParamXmlTag ) )
93+ foreach ( var documentedParameter in documentationParameters )
8194 {
82- // <param .../> is empty.
83- context . ReportDiagnostic ( Diagnostic . Create ( Descriptor , emptyElement . GetLocation ( ) ) ) ;
95+ if ( documentedParameter . Item1 )
96+ {
97+ context . ReportDiagnostic ( Diagnostic . Create ( Descriptor , documentedParameter . Item2 ?? identifierLocation ) ) ;
98+ }
99+
100+ index ++ ;
84101 }
85102 }
103+
104+ private static XmlNameSyntax GetName ( XmlNodeSyntax element )
105+ {
106+ return ( element as XmlElementSyntax ) ? . StartTag ? . Name
107+ ?? ( element as XmlEmptyElementSyntax ) ? . Name ;
108+ }
86109 }
87110}
0 commit comments