@@ -179,220 +179,231 @@ private static void HandleCompilationStart(CompilationStartAnalysisContext conte
179179 // Disabling SA1633 will disable all other header related diagnostics.
180180 if ( ! compilation . IsAnalyzerSuppressed ( SA1633Identifier ) )
181181 {
182- context . RegisterSyntaxTreeActionHonorExclusions ( ctx => HandleSyntaxTreeAction ( ctx , compilation ) ) ;
182+ Analyzer analyzer = new Analyzer ( context . Options ) ;
183+ context . RegisterSyntaxTreeActionHonorExclusions ( ctx => analyzer . HandleSyntaxTreeAction ( ctx , compilation ) ) ;
183184 }
184185 }
185186
186- private static void HandleSyntaxTreeAction ( SyntaxTreeAnalysisContext context , Compilation compilation )
187+ private sealed class Analyzer
187188 {
188- var root = context . Tree . GetRoot ( context . CancellationToken ) ;
189- var settings = context . GetStyleCopSettings ( ) ;
189+ private readonly DocumentationSettings documentationSettings ;
190190
191- // don't process empty files
192- if ( root . FullSpan . IsEmpty )
191+ public Analyzer ( AnalyzerOptions options )
193192 {
194- return ;
193+ StyleCopSettings settings = options . GetStyleCopSettings ( ) ;
194+ this . documentationSettings = settings . DocumentationRules ;
195195 }
196196
197- if ( settings . DocumentationRules . XmlHeader )
197+ public void HandleSyntaxTreeAction ( SyntaxTreeAnalysisContext context , Compilation compilation )
198198 {
199- var fileHeader = FileHeaderHelpers . ParseXmlFileHeader ( root ) ;
200- if ( fileHeader . IsMissing )
201- {
202- context . ReportDiagnostic ( Diagnostic . Create ( SA1633DescriptorMissing , fileHeader . GetLocation ( context . Tree ) ) ) ;
203- return ;
204- }
199+ var root = context . Tree . GetRoot ( context . CancellationToken ) ;
205200
206- if ( fileHeader . IsMalformed )
201+ // don't process empty files
202+ if ( root . FullSpan . IsEmpty )
207203 {
208- context . ReportDiagnostic ( Diagnostic . Create ( SA1633DescriptorMalformed , fileHeader . GetLocation ( context . Tree ) ) ) ;
209204 return ;
210205 }
211206
212- if ( ! compilation . IsAnalyzerSuppressed ( SA1634Identifier ) )
213- {
214- CheckCopyrightHeader ( context , compilation , settings , fileHeader ) ;
215- }
216-
217- if ( ! compilation . IsAnalyzerSuppressed ( SA1639Identifier ) )
218- {
219- CheckSummaryHeader ( context , compilation , fileHeader ) ;
220- }
221- }
222- else
223- {
224- var fileHeader = FileHeaderHelpers . ParseFileHeader ( root ) ;
225- if ( fileHeader . IsMissing )
226- {
227- context . ReportDiagnostic ( Diagnostic . Create ( SA1633DescriptorMissing , fileHeader . GetLocation ( context . Tree ) ) ) ;
228- return ;
229- }
230-
231- if ( ! compilation . IsAnalyzerSuppressed ( SA1635Identifier ) )
207+ if ( this . documentationSettings . XmlHeader )
232208 {
233- if ( string . IsNullOrWhiteSpace ( fileHeader . CopyrightText ) )
209+ var fileHeader = FileHeaderHelpers . ParseXmlFileHeader ( root ) ;
210+ if ( fileHeader . IsMissing )
234211 {
235- context . ReportDiagnostic ( Diagnostic . Create ( SA1635Descriptor , fileHeader . GetLocation ( context . Tree ) ) ) ;
212+ context . ReportDiagnostic ( Diagnostic . Create ( SA1633DescriptorMissing , fileHeader . GetLocation ( context . Tree ) ) ) ;
236213 return ;
237214 }
238215
239- if ( compilation . IsAnalyzerSuppressed ( SA1636Identifier ) )
216+ if ( fileHeader . IsMalformed )
240217 {
218+ context . ReportDiagnostic ( Diagnostic . Create ( SA1633DescriptorMalformed , fileHeader . GetLocation ( context . Tree ) ) ) ;
241219 return ;
242220 }
243221
244- if ( ! CompareCopyrightText ( fileHeader . CopyrightText , settings ) )
222+ if ( ! compilation . IsAnalyzerSuppressed ( SA1634Identifier ) )
245223 {
246- context . ReportDiagnostic ( Diagnostic . Create ( SA1636Descriptor , fileHeader . GetLocation ( context . Tree ) ) ) ;
224+ this . CheckCopyrightHeader ( context , compilation , fileHeader ) ;
225+ }
226+
227+ if ( ! compilation . IsAnalyzerSuppressed ( SA1639Identifier ) )
228+ {
229+ this . CheckSummaryHeader ( context , compilation , fileHeader ) ;
230+ }
231+ }
232+ else
233+ {
234+ var fileHeader = FileHeaderHelpers . ParseFileHeader ( root ) ;
235+ if ( fileHeader . IsMissing )
236+ {
237+ context . ReportDiagnostic ( Diagnostic . Create ( SA1633DescriptorMissing , fileHeader . GetLocation ( context . Tree ) ) ) ;
247238 return ;
248239 }
240+
241+ if ( ! compilation . IsAnalyzerSuppressed ( SA1635Identifier ) )
242+ {
243+ if ( string . IsNullOrWhiteSpace ( fileHeader . CopyrightText ) )
244+ {
245+ context . ReportDiagnostic ( Diagnostic . Create ( SA1635Descriptor , fileHeader . GetLocation ( context . Tree ) ) ) ;
246+ return ;
247+ }
248+
249+ if ( compilation . IsAnalyzerSuppressed ( SA1636Identifier ) )
250+ {
251+ return ;
252+ }
253+
254+ if ( ! this . CompareCopyrightText ( fileHeader . CopyrightText ) )
255+ {
256+ context . ReportDiagnostic ( Diagnostic . Create ( SA1636Descriptor , fileHeader . GetLocation ( context . Tree ) ) ) ;
257+ return ;
258+ }
259+ }
249260 }
250261 }
251- }
252262
253- private static void CheckCopyrightHeader ( SyntaxTreeAnalysisContext context , Compilation compilation , StyleCopSettings settings , XmlFileHeader fileHeader )
254- {
255- var copyrightElement = fileHeader . GetElement ( "copyright" ) ;
256- if ( copyrightElement == null )
263+ private void CheckCopyrightHeader ( SyntaxTreeAnalysisContext context , Compilation compilation , XmlFileHeader fileHeader )
257264 {
258- context . ReportDiagnostic ( Diagnostic . Create ( SA1634Descriptor , fileHeader . GetLocation ( context . Tree ) ) ) ;
259- return ;
260- }
265+ var copyrightElement = fileHeader . GetElement ( "copyright" ) ;
266+ if ( copyrightElement == null )
267+ {
268+ context . ReportDiagnostic ( Diagnostic . Create ( SA1634Descriptor , fileHeader . GetLocation ( context . Tree ) ) ) ;
269+ return ;
270+ }
261271
262- if ( ! compilation . IsAnalyzerSuppressed ( SA1637Identifier ) )
263- {
264- CheckFile ( context , compilation , fileHeader , copyrightElement , settings ) ;
265- }
272+ if ( ! compilation . IsAnalyzerSuppressed ( SA1637Identifier ) )
273+ {
274+ this . CheckFile ( context , compilation , fileHeader , copyrightElement ) ;
275+ }
266276
267- if ( ! compilation . IsAnalyzerSuppressed ( SA1640Identifier ) )
268- {
269- CheckCompanyName ( context , compilation , fileHeader , copyrightElement , settings ) ;
270- }
277+ if ( ! compilation . IsAnalyzerSuppressed ( SA1640Identifier ) )
278+ {
279+ this . CheckCompanyName ( context , compilation , fileHeader , copyrightElement ) ;
280+ }
271281
272- if ( ! compilation . IsAnalyzerSuppressed ( SA1635Identifier ) )
273- {
274- CheckCopyrightText ( context , compilation , fileHeader , copyrightElement , settings ) ;
282+ if ( ! compilation . IsAnalyzerSuppressed ( SA1635Identifier ) )
283+ {
284+ this . CheckCopyrightText ( context , compilation , fileHeader , copyrightElement ) ;
285+ }
275286 }
276- }
277287
278- private static void CheckFile ( SyntaxTreeAnalysisContext context , Compilation compilation , XmlFileHeader fileHeader , XElement copyrightElement , StyleCopSettings settings )
279- {
280- var fileAttribute = copyrightElement . Attribute ( "file" ) ;
281- if ( fileAttribute == null )
288+ private void CheckFile ( SyntaxTreeAnalysisContext context , Compilation compilation , XmlFileHeader fileHeader , XElement copyrightElement )
282289 {
283- var location = fileHeader . GetElementLocation ( context . Tree , copyrightElement ) ;
284- context . ReportDiagnostic ( Diagnostic . Create ( SA1637Descriptor , location ) ) ;
285- return ;
286- }
290+ var fileAttribute = copyrightElement . Attribute ( "file" ) ;
291+ if ( fileAttribute == null )
292+ {
293+ var location = fileHeader . GetElementLocation ( context . Tree , copyrightElement ) ;
294+ context . ReportDiagnostic ( Diagnostic . Create ( SA1637Descriptor , location ) ) ;
295+ return ;
296+ }
287297
288- if ( compilation . IsAnalyzerSuppressed ( SA1638Identifier ) )
289- {
290- return ;
291- }
298+ if ( compilation . IsAnalyzerSuppressed ( SA1638Identifier ) )
299+ {
300+ return ;
301+ }
292302
293- var fileName = Path . GetFileName ( context . Tree . FilePath ) ;
294- if ( string . CompareOrdinal ( fileAttribute . Value , fileName ) != 0 )
295- {
296- var location = fileHeader . GetElementLocation ( context . Tree , copyrightElement ) ;
297- context . ReportDiagnostic ( Diagnostic . Create ( SA1638Descriptor , location ) ) ;
303+ var fileName = Path . GetFileName ( context . Tree . FilePath ) ;
304+ if ( string . CompareOrdinal ( fileAttribute . Value , fileName ) != 0 )
305+ {
306+ var location = fileHeader . GetElementLocation ( context . Tree , copyrightElement ) ;
307+ context . ReportDiagnostic ( Diagnostic . Create ( SA1638Descriptor , location ) ) ;
308+ }
298309 }
299- }
300310
301- private static void CheckCopyrightText ( SyntaxTreeAnalysisContext context , Compilation compilation , XmlFileHeader fileHeader , XElement copyrightElement , StyleCopSettings settings )
302- {
303- var copyrightText = copyrightElement . Value ;
304- if ( string . IsNullOrWhiteSpace ( copyrightText ) )
311+ private void CheckCopyrightText ( SyntaxTreeAnalysisContext context , Compilation compilation , XmlFileHeader fileHeader , XElement copyrightElement )
305312 {
306- var location = fileHeader . GetElementLocation ( context . Tree , copyrightElement ) ;
307- context . ReportDiagnostic ( Diagnostic . Create ( SA1635Descriptor , location ) ) ;
308- return ;
309- }
313+ var copyrightText = copyrightElement . Value ;
314+ if ( string . IsNullOrWhiteSpace ( copyrightText ) )
315+ {
316+ var location = fileHeader . GetElementLocation ( context . Tree , copyrightElement ) ;
317+ context . ReportDiagnostic ( Diagnostic . Create ( SA1635Descriptor , location ) ) ;
318+ return ;
319+ }
310320
311- if ( compilation . IsAnalyzerSuppressed ( SA1636Identifier ) )
312- {
313- return ;
314- }
321+ if ( compilation . IsAnalyzerSuppressed ( SA1636Identifier ) )
322+ {
323+ return ;
324+ }
315325
316- var settingsCopyrightText = settings . DocumentationRules . CopyrightText ;
317- if ( string . Equals ( settingsCopyrightText , DocumentationSettings . DefaultCopyrightText , StringComparison . OrdinalIgnoreCase ) )
318- {
319- // The copyright text is meaningless until the company name is configured by the user.
320- return ;
321- }
326+ var settingsCopyrightText = this . documentationSettings . CopyrightText ;
327+ if ( string . Equals ( settingsCopyrightText , DocumentationSettings . DefaultCopyrightText , StringComparison . OrdinalIgnoreCase ) )
328+ {
329+ // The copyright text is meaningless until the company name is configured by the user.
330+ return ;
331+ }
322332
323- // trim any leading / trailing new line or whitespace characters (those are a result of the XML formatting)
324- if ( ! CompareCopyrightText ( copyrightText . Trim ( '\r ' , '\n ' , ' ' , '\t ' ) , settings ) )
325- {
326- var location = fileHeader . GetElementLocation ( context . Tree , copyrightElement ) ;
327- context . ReportDiagnostic ( Diagnostic . Create ( SA1636Descriptor , location ) ) ;
333+ // trim any leading / trailing new line or whitespace characters (those are a result of the XML formatting)
334+ if ( ! this . CompareCopyrightText ( copyrightText . Trim ( '\r ' , '\n ' , ' ' , '\t ' ) ) )
335+ {
336+ var location = fileHeader . GetElementLocation ( context . Tree , copyrightElement ) ;
337+ context . ReportDiagnostic ( Diagnostic . Create ( SA1636Descriptor , location ) ) ;
338+ }
328339 }
329- }
330340
331- private static void CheckCompanyName ( SyntaxTreeAnalysisContext context , Compilation compilation , XmlFileHeader fileHeader , XElement copyrightElement , StyleCopSettings settings )
332- {
333- var companyName = copyrightElement . Attribute ( "company" ) ? . Value ;
334- if ( string . IsNullOrWhiteSpace ( companyName ) )
341+ private void CheckCompanyName ( SyntaxTreeAnalysisContext context , Compilation compilation , XmlFileHeader fileHeader , XElement copyrightElement )
335342 {
336- var location = fileHeader . GetElementLocation ( context . Tree , copyrightElement ) ;
337- context . ReportDiagnostic ( Diagnostic . Create ( SA1640Descriptor , location ) ) ;
338- return ;
339- }
343+ var companyName = copyrightElement . Attribute ( "company" ) ? . Value ;
344+ if ( string . IsNullOrWhiteSpace ( companyName ) )
345+ {
346+ var location = fileHeader . GetElementLocation ( context . Tree , copyrightElement ) ;
347+ context . ReportDiagnostic ( Diagnostic . Create ( SA1640Descriptor , location ) ) ;
348+ return ;
349+ }
340350
341- if ( compilation . IsAnalyzerSuppressed ( SA1641Identifier ) )
342- {
343- return ;
344- }
351+ if ( compilation . IsAnalyzerSuppressed ( SA1641Identifier ) )
352+ {
353+ return ;
354+ }
345355
346- if ( string . Equals ( settings . DocumentationRules . CompanyName , DocumentationSettings . DefaultCompanyName , StringComparison . OrdinalIgnoreCase ) )
347- {
348- // The company name is meaningless until configured by the user.
349- return ;
350- }
356+ if ( string . Equals ( this . documentationSettings . CompanyName , DocumentationSettings . DefaultCompanyName , StringComparison . OrdinalIgnoreCase ) )
357+ {
358+ // The company name is meaningless until configured by the user.
359+ return ;
360+ }
351361
352- if ( string . CompareOrdinal ( companyName , settings . DocumentationRules . CompanyName ) != 0 )
353- {
354- var location = fileHeader . GetElementLocation ( context . Tree , copyrightElement ) ;
355- context . ReportDiagnostic ( Diagnostic . Create ( SA1641Descriptor , location ) ) ;
362+ if ( string . CompareOrdinal ( companyName , this . documentationSettings . CompanyName ) != 0 )
363+ {
364+ var location = fileHeader . GetElementLocation ( context . Tree , copyrightElement ) ;
365+ context . ReportDiagnostic ( Diagnostic . Create ( SA1641Descriptor , location ) ) ;
366+ }
356367 }
357- }
358368
359- private static void CheckSummaryHeader ( SyntaxTreeAnalysisContext context , Compilation compilation , XmlFileHeader fileHeader )
360- {
361- var summaryElement = fileHeader . GetElement ( "summary" ) ;
362- if ( summaryElement == null )
369+ private void CheckSummaryHeader ( SyntaxTreeAnalysisContext context , Compilation compilation , XmlFileHeader fileHeader )
363370 {
364- context . ReportDiagnostic ( Diagnostic . Create ( SA1639Descriptor , fileHeader . GetLocation ( context . Tree ) ) ) ;
365- return ;
366- }
371+ var summaryElement = fileHeader . GetElement ( "summary" ) ;
372+ if ( summaryElement == null )
373+ {
374+ context . ReportDiagnostic ( Diagnostic . Create ( SA1639Descriptor , fileHeader . GetLocation ( context . Tree ) ) ) ;
375+ return ;
376+ }
367377
368- if ( string . IsNullOrWhiteSpace ( summaryElement . Value ) )
369- {
370- var location = fileHeader . GetElementLocation ( context . Tree , summaryElement ) ;
371- context . ReportDiagnostic ( Diagnostic . Create ( SA1639Descriptor , location ) ) ;
378+ if ( string . IsNullOrWhiteSpace ( summaryElement . Value ) )
379+ {
380+ var location = fileHeader . GetElementLocation ( context . Tree , summaryElement ) ;
381+ context . ReportDiagnostic ( Diagnostic . Create ( SA1639Descriptor , location ) ) ;
382+ }
372383 }
373- }
374384
375- private static bool CompareCopyrightText ( string copyrightText , StyleCopSettings settings )
376- {
377- // make sure that both \n and \r\n are accepted from the settings.
378- var reformattedCopyrightTextParts = settings . DocumentationRules . CopyrightText . Replace ( "\r \n " , "\n " ) . Split ( '\n ' ) ;
379- var fileHeaderCopyrightTextParts = copyrightText . Replace ( "\r \n " , "\n " ) . Split ( '\n ' ) ;
380-
381- if ( reformattedCopyrightTextParts . Length != fileHeaderCopyrightTextParts . Length )
385+ private bool CompareCopyrightText ( string copyrightText )
382386 {
383- return false ;
384- }
387+ // make sure that both \n and \r\n are accepted from the settings.
388+ var reformattedCopyrightTextParts = this . documentationSettings . CopyrightText . Replace ( "\r \n " , "\n " ) . Split ( '\n ' ) ;
389+ var fileHeaderCopyrightTextParts = copyrightText . Replace ( "\r \n " , "\n " ) . Split ( '\n ' ) ;
385390
386- // compare line by line, ignoring leading and trailing whitespace on each line.
387- for ( var i = 0 ; i < reformattedCopyrightTextParts . Length ; i ++ )
388- {
389- if ( string . CompareOrdinal ( reformattedCopyrightTextParts [ i ] . Trim ( ) , fileHeaderCopyrightTextParts [ i ] . Trim ( ) ) != 0 )
391+ if ( reformattedCopyrightTextParts . Length != fileHeaderCopyrightTextParts . Length )
390392 {
391393 return false ;
392394 }
393- }
394395
395- return true ;
396+ // compare line by line, ignoring leading and trailing whitespace on each line.
397+ for ( var i = 0 ; i < reformattedCopyrightTextParts . Length ; i ++ )
398+ {
399+ if ( string . CompareOrdinal ( reformattedCopyrightTextParts [ i ] . Trim ( ) , fileHeaderCopyrightTextParts [ i ] . Trim ( ) ) != 0 )
400+ {
401+ return false ;
402+ }
403+ }
404+
405+ return true ;
406+ }
396407 }
397408 }
398409}
0 commit comments