Skip to content

Commit 9859cc0

Browse files
committed
Use RegisterSyntaxTreeAction for analyzers that need to check for whitespace-only documents
1 parent 490140c commit 9859cc0

9 files changed

Lines changed: 84 additions & 57 deletions

StyleCop.Analyzers/StyleCop.Analyzers.Test/Helpers/ExclusionTestAnalyzer.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace TestHelper
88
using Microsoft.CodeAnalysis;
99
using Microsoft.CodeAnalysis.Diagnostics;
1010
using Microsoft.CodeAnalysis.Text;
11-
using StyleCop.Analyzers;
11+
using StyleCop.Analyzers.Helpers;
1212

1313
/// <summary>
1414
/// A analyzer that will report a diagnostic at the start of the code file if the
@@ -26,7 +26,7 @@ internal class ExclusionTestAnalyzer : DiagnosticAnalyzer
2626
private static readonly DiagnosticDescriptor Descriptor =
2727
new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, "TestRules", DiagnosticSeverity.Warning, true, Description, HelpLink);
2828

29-
private static readonly Action<CompilationStartAnalysisContext> CompilationStartAction = HandleCompilationStart;
29+
private static readonly Action<SyntaxTreeAnalysisContext> SyntaxTreeAction = AnalyzeTree;
3030

3131
/// <inheritdoc/>
3232
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } =
@@ -35,16 +35,19 @@ internal class ExclusionTestAnalyzer : DiagnosticAnalyzer
3535
/// <inheritdoc/>
3636
public override void Initialize(AnalysisContext context)
3737
{
38-
context.RegisterCompilationStartAction(CompilationStartAction);
39-
}
38+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
4039

41-
private static void HandleCompilationStart(CompilationStartAnalysisContext context)
42-
{
43-
context.RegisterSyntaxTreeActionHonorExclusions(AnalyzeTree);
40+
context.RegisterSyntaxTreeAction(SyntaxTreeAction);
4441
}
4542

4643
private static void AnalyzeTree(SyntaxTreeAnalysisContext context)
4744
{
45+
if (context.Tree.IsWhitespaceOnly(context.CancellationToken))
46+
{
47+
// Handling of empty documents is now the responsibility of the analyzers
48+
return;
49+
}
50+
4851
// Report a diagnostic if we got called
4952
context.ReportDiagnostic(Diagnostic.Create(Descriptor, context.Tree.GetLocation(TextSpan.FromBounds(0, 0))));
5053
}

StyleCop.Analyzers/StyleCop.Analyzers/GeneratedCodeAnalysisExtensions.cs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ namespace StyleCop.Analyzers
88
using System.Linq;
99
using System.Text.RegularExpressions;
1010
using System.Threading;
11-
using Helpers;
1211
using Microsoft.CodeAnalysis;
1312
using Microsoft.CodeAnalysis.CSharp;
1413
using Microsoft.CodeAnalysis.CSharp.Syntax;
1514
using Microsoft.CodeAnalysis.Diagnostics;
15+
using StyleCop.Analyzers.Helpers;
1616

1717
internal static class GeneratedCodeAnalysisExtensions
1818
{
@@ -99,7 +99,7 @@ private static bool IsGeneratedDocumentNoCache(SyntaxTree tree, CancellationToke
9999
{
100100
return IsGeneratedFileName(tree.FilePath)
101101
|| HasAutoGeneratedComment(tree, cancellationToken)
102-
|| IsEmpty(tree, cancellationToken);
102+
|| tree.IsWhitespaceOnly(cancellationToken);
103103
}
104104

105105
/// <summary>
@@ -160,22 +160,5 @@ private static bool IsGeneratedFileName(string filePath)
160160
@"\.designer\.cs$",
161161
RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
162162
}
163-
164-
/// <summary>
165-
/// Checks if a given <see cref="SyntaxTree"/> only contains whitespaces. We don't want to analyze empty files.
166-
/// </summary>
167-
/// <param name="tree">The syntax tree to examine.</param>
168-
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that the task will observe.</param>
169-
/// <returns>
170-
/// <para><see langword="true"/> if <paramref name="tree"/> only contains whitespaces; otherwise, <see langword="false"/>.</para>
171-
/// </returns>
172-
private static bool IsEmpty(SyntaxTree tree, CancellationToken cancellationToken)
173-
{
174-
var root = tree.GetRoot(cancellationToken);
175-
var firstToken = root.GetFirstToken(includeZeroWidth: true);
176-
177-
return firstToken.IsKind(SyntaxKind.EndOfFileToken)
178-
&& TriviaHelper.IndexOfFirstNonWhitespaceTrivia(firstToken.LeadingTrivia) == -1;
179-
}
180163
}
181164
}

StyleCop.Analyzers/StyleCop.Analyzers/Helpers/SyntaxTreeHelpers.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,24 @@ public static ConcurrentDictionary<SyntaxTree, bool> GetOrCreateUsingAliasCache(
5151
return cache.Item2;
5252
}
5353

54+
/// <summary>
55+
/// Checks if a given <see cref="SyntaxTree"/> only contains whitespace. We don't want to analyze empty files.
56+
/// </summary>
57+
/// <param name="tree">The syntax tree to examine.</param>
58+
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that the task will observe.</param>
59+
/// <returns>
60+
/// <see langword="true"/> if <paramref name="tree"/> only contains whitespace; otherwise,
61+
/// <see langword="false"/>.
62+
/// </returns>
63+
public static bool IsWhitespaceOnly(this SyntaxTree tree, CancellationToken cancellationToken)
64+
{
65+
var root = tree.GetRoot(cancellationToken);
66+
var firstToken = root.GetFirstToken(includeZeroWidth: true);
67+
68+
return firstToken.IsKind(SyntaxKind.EndOfFileToken)
69+
&& TriviaHelper.IndexOfFirstNonWhitespaceTrivia(firstToken.LeadingTrivia) == -1;
70+
}
71+
5472
internal static bool ContainsUsingAlias(this SyntaxTree tree, ConcurrentDictionary<SyntaxTree, bool> cache)
5573
{
5674
if (tree == null)

StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/SA1507CodeMustNotContainMultipleBlankLinesInARow.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace StyleCop.Analyzers.LayoutRules
99
using Microsoft.CodeAnalysis.CSharp;
1010
using Microsoft.CodeAnalysis.Diagnostics;
1111
using Microsoft.CodeAnalysis.Text;
12+
using StyleCop.Analyzers.Helpers;
1213

1314
/// <summary>
1415
/// The C# code contains multiple blank lines in a row.
@@ -53,7 +54,6 @@ internal class SA1507CodeMustNotContainMultipleBlankLinesInARow : DiagnosticAnal
5354
private static readonly DiagnosticDescriptor Descriptor =
5455
new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.LayoutRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, Description, HelpLink);
5556

56-
private static readonly Action<CompilationStartAnalysisContext> CompilationStartAction = HandleCompilationStart;
5757
private static readonly Action<SyntaxTreeAnalysisContext> SyntaxTreeAction = HandleSyntaxTree;
5858

5959
/// <inheritdoc/>
@@ -63,16 +63,19 @@ internal class SA1507CodeMustNotContainMultipleBlankLinesInARow : DiagnosticAnal
6363
/// <inheritdoc/>
6464
public override void Initialize(AnalysisContext context)
6565
{
66-
context.RegisterCompilationStartAction(CompilationStartAction);
67-
}
66+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
6867

69-
private static void HandleCompilationStart(CompilationStartAnalysisContext context)
70-
{
71-
context.RegisterSyntaxTreeActionHonorExclusions(SyntaxTreeAction);
68+
context.RegisterSyntaxTreeAction(SyntaxTreeAction);
7269
}
7370

7471
private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
7572
{
73+
if (context.Tree.IsWhitespaceOnly(context.CancellationToken))
74+
{
75+
// Handling of empty documents is now the responsibility of the analyzers
76+
return;
77+
}
78+
7679
SyntaxNode root = context.Tree.GetRoot(context.CancellationToken);
7780
foreach (var token in root.DescendantTokens(descendIntoTrivia: false))
7881
{

StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/SA1517CodeMustNotContainBlankLinesAtStartOfFile.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ internal class SA1517CodeMustNotContainBlankLinesAtStartOfFile : DiagnosticAnaly
3434
private static readonly DiagnosticDescriptor Descriptor =
3535
new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.LayoutRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, Description, HelpLink);
3636

37-
private static readonly Action<CompilationStartAnalysisContext> CompilationStartAction = HandleCompilationStart;
3837
private static readonly Action<SyntaxTreeAnalysisContext> SyntaxTreeAction = HandleSyntaxTree;
3938

4039
/// <inheritdoc/>
@@ -44,16 +43,19 @@ internal class SA1517CodeMustNotContainBlankLinesAtStartOfFile : DiagnosticAnaly
4443
/// <inheritdoc/>
4544
public override void Initialize(AnalysisContext context)
4645
{
47-
context.RegisterCompilationStartAction(CompilationStartAction);
48-
}
46+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
4947

50-
private static void HandleCompilationStart(CompilationStartAnalysisContext context)
51-
{
52-
context.RegisterSyntaxTreeActionHonorExclusions(SyntaxTreeAction);
48+
context.RegisterSyntaxTreeAction(SyntaxTreeAction);
5349
}
5450

5551
private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
5652
{
53+
if (context.Tree.IsWhitespaceOnly(context.CancellationToken))
54+
{
55+
// Handling of empty documents is now the responsibility of the analyzers
56+
return;
57+
}
58+
5759
var firstToken = context.Tree.GetRoot().GetFirstToken(includeZeroWidth: true);
5860

5961
if (firstToken.HasLeadingTrivia)

StyleCop.Analyzers/StyleCop.Analyzers/MaintainabilityRules/SA1412StoreFilesAsUtf8.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace StyleCop.Analyzers.MaintainabilityRules
99
using Microsoft.CodeAnalysis;
1010
using Microsoft.CodeAnalysis.Diagnostics;
1111
using Microsoft.CodeAnalysis.Text;
12+
using StyleCop.Analyzers.Helpers;
1213

1314
/// <summary>
1415
/// Store files as UTF-8 with byte order mark.
@@ -36,7 +37,6 @@ internal class SA1412StoreFilesAsUtf8 : DiagnosticAnalyzer
3637
private static readonly DiagnosticDescriptor Descriptor =
3738
new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.MaintainabilityRules, DiagnosticSeverity.Warning, AnalyzerConstants.DisabledByDefault, Description, HelpLink);
3839

39-
private static readonly Action<CompilationStartAnalysisContext> CompilationStartAction = HandleCompilationStart;
4040
private static readonly Action<SyntaxTreeAnalysisContext> SyntaxTreeAction = HandleSyntaxTree;
4141

4242
private static byte[] utf8Preamble = Encoding.UTF8.GetPreamble();
@@ -56,16 +56,19 @@ internal class SA1412StoreFilesAsUtf8 : DiagnosticAnalyzer
5656
/// <inheritdoc/>
5757
public override void Initialize(AnalysisContext context)
5858
{
59-
context.RegisterCompilationStartAction(CompilationStartAction);
60-
}
59+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
6160

62-
private static void HandleCompilationStart(CompilationStartAnalysisContext context)
63-
{
64-
context.RegisterSyntaxTreeActionHonorExclusions(SyntaxTreeAction);
61+
context.RegisterSyntaxTreeAction(SyntaxTreeAction);
6562
}
6663

6764
private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
6865
{
66+
if (context.Tree.IsWhitespaceOnly(context.CancellationToken))
67+
{
68+
// Handling of empty documents is now the responsibility of the analyzers
69+
return;
70+
}
71+
6972
byte[] preamble = context.Tree.Encoding.GetPreamble();
7073

7174
if (!IsUtf8Preamble(preamble))

StyleCop.Analyzers/StyleCop.Analyzers/SpacingRules/SA1025CodeMustNotContainMultipleWhitespaceInARow.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace StyleCop.Analyzers.SpacingRules
88
using Microsoft.CodeAnalysis;
99
using Microsoft.CodeAnalysis.CSharp;
1010
using Microsoft.CodeAnalysis.Diagnostics;
11+
using StyleCop.Analyzers.Helpers;
1112

1213
/// <summary>
1314
/// The code contains multiple whitespace characters in a row.
@@ -33,7 +34,6 @@ internal class SA1025CodeMustNotContainMultipleWhitespaceInARow : DiagnosticAnal
3334
private static readonly DiagnosticDescriptor Descriptor =
3435
new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.SpacingRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, Description, HelpLink);
3536

36-
private static readonly Action<CompilationStartAnalysisContext> CompilationStartAction = HandleCompilationStart;
3737
private static readonly Action<SyntaxTreeAnalysisContext> SyntaxTreeAction = HandleSyntaxTree;
3838

3939
/// <inheritdoc/>
@@ -43,16 +43,19 @@ internal class SA1025CodeMustNotContainMultipleWhitespaceInARow : DiagnosticAnal
4343
/// <inheritdoc/>
4444
public override void Initialize(AnalysisContext context)
4545
{
46-
context.RegisterCompilationStartAction(CompilationStartAction);
47-
}
46+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
4847

49-
private static void HandleCompilationStart(CompilationStartAnalysisContext context)
50-
{
51-
context.RegisterSyntaxTreeActionHonorExclusions(SyntaxTreeAction);
48+
context.RegisterSyntaxTreeAction(SyntaxTreeAction);
5249
}
5350

5451
private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
5552
{
53+
if (context.Tree.IsWhitespaceOnly(context.CancellationToken))
54+
{
55+
// Handling of empty documents is now the responsibility of the analyzers
56+
return;
57+
}
58+
5659
SyntaxNode root = context.Tree.GetCompilationUnitRoot(context.CancellationToken);
5760
foreach (var trivia in root.DescendantTrivia())
5861
{

StyleCop.Analyzers/StyleCop.Analyzers/SpacingRules/SA1028CodeMustNotContainTrailingWhitespace.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace StyleCop.Analyzers.SpacingRules
99
using Microsoft.CodeAnalysis.CSharp;
1010
using Microsoft.CodeAnalysis.Diagnostics;
1111
using Microsoft.CodeAnalysis.Text;
12+
using StyleCop.Analyzers.Helpers;
1213

1314
/// <summary>
1415
/// Discovers any C# lines of code with trailing whitespace.
@@ -37,7 +38,6 @@ internal class SA1028CodeMustNotContainTrailingWhitespace : DiagnosticAnalyzer
3738
private static readonly DiagnosticDescriptor Descriptor =
3839
new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.SpacingRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, Description, HelpLink, WellKnownDiagnosticTags.Unnecessary);
3940

40-
private static readonly Action<CompilationStartAnalysisContext> CompilationStartAction = HandleCompilationStart;
4141
private static readonly Action<SyntaxTreeAnalysisContext> SyntaxTreeAction = HandleSyntaxTree;
4242

4343
/// <inheritdoc />
@@ -47,12 +47,9 @@ internal class SA1028CodeMustNotContainTrailingWhitespace : DiagnosticAnalyzer
4747
/// <inheritdoc />
4848
public override void Initialize(AnalysisContext context)
4949
{
50-
context.RegisterCompilationStartAction(CompilationStartAction);
51-
}
50+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
5251

53-
private static void HandleCompilationStart(CompilationStartAnalysisContext context)
54-
{
55-
context.RegisterSyntaxTreeActionHonorExclusions(SyntaxTreeAction);
52+
context.RegisterSyntaxTreeAction(SyntaxTreeAction);
5653
}
5754

5855
/// <summary>
@@ -61,6 +58,12 @@ private static void HandleCompilationStart(CompilationStartAnalysisContext conte
6158
/// <param name="context">The context that provides the document to scan.</param>
6259
private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
6360
{
61+
if (context.Tree.IsWhitespaceOnly(context.CancellationToken))
62+
{
63+
// Handling of empty documents is now the responsibility of the analyzers
64+
return;
65+
}
66+
6467
var root = context.Tree.GetRoot(context.CancellationToken);
6568
var text = context.Tree.GetText(context.CancellationToken);
6669

StyleCop.Analyzers/StyleCop.Analyzers/SpecialRules/SA0001XmlCommentAnalysisDisabled.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace StyleCop.Analyzers.SpecialRules
88
using System.Threading;
99
using Microsoft.CodeAnalysis;
1010
using Microsoft.CodeAnalysis.Diagnostics;
11+
using StyleCop.Analyzers.Helpers;
1112

1213
/// <summary>
1314
/// The project is configured to not parse XML documentation comments.
@@ -37,13 +38,15 @@ internal class SA0001XmlCommentAnalysisDisabled : DiagnosticAnalyzer
3738
/// <inheritdoc/>
3839
public override void Initialize(AnalysisContext context)
3940
{
41+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
42+
4043
context.RegisterCompilationStartAction(CompilationStartAction);
4144
}
4245

4346
private static void HandleCompilationStart(CompilationStartAnalysisContext context)
4447
{
4548
Analyzer analyzer = new Analyzer();
46-
context.RegisterSyntaxTreeActionHonorExclusions(analyzer.HandleSyntaxTree);
49+
context.RegisterSyntaxTreeAction(analyzer.HandleSyntaxTree);
4750
context.RegisterCompilationEndAction(analyzer.HandleCompilation);
4851
}
4952

@@ -63,6 +66,12 @@ public void HandleSyntaxTree(SyntaxTreeAnalysisContext context)
6366
{
6467
if (context.Tree.Options.DocumentationMode == DocumentationMode.None)
6568
{
69+
if (context.Tree.IsWhitespaceOnly(context.CancellationToken))
70+
{
71+
// Handling of empty documents is now the responsibility of the analyzers
72+
return;
73+
}
74+
6675
Volatile.Write(ref this.documentationAnalysisDisabled, true);
6776
}
6877
}

0 commit comments

Comments
 (0)