Skip to content

Commit d31a8c2

Browse files
committed
Access settings once per compilation instead of once per file
1 parent 3938c68 commit d31a8c2

1 file changed

Lines changed: 163 additions & 152 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers/DocumentationRules/FileHeaderAnalyzers.cs

Lines changed: 163 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)