Skip to content

Commit 128898e

Browse files
committed
Use RegisterSyntaxTreeAction for actions which require StyleCopSettings
1 parent e8e8fd4 commit 128898e

7 files changed

Lines changed: 116 additions & 47 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers/AnalyzerExtensions.cs

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,35 +34,30 @@ private static Tuple<WeakReference<Compilation>, StrongBox<StyleCopSettings>> se
3434
/// Register an action to be executed at completion of parsing of a code document. A syntax tree action reports
3535
/// diagnostics about the <see cref="SyntaxTree"/> of a document.
3636
/// </summary>
37-
/// <remarks>This method honors exclusions.</remarks>
3837
/// <param name="context">The analysis context.</param>
3938
/// <param name="action">Action to be executed at completion of parsing of a document.</param>
40-
public static void RegisterSyntaxTreeActionHonorExclusions(this CompilationStartAnalysisContext context, Action<SyntaxTreeAnalysisContext, StyleCopSettings> action)
39+
public static void RegisterSyntaxTreeAction(this AnalysisContext context, Action<SyntaxTreeAnalysisContext, StyleCopSettings> action)
4140
{
42-
Compilation compilation = context.Compilation;
43-
ConcurrentDictionary<SyntaxTree, bool> cache = GetOrCreateGeneratedDocumentCache(compilation);
44-
StrongBox<StyleCopSettings> settingsCache = GetOrCreateStyleCopSettingsCache(compilation);
45-
4641
context.RegisterSyntaxTreeAction(
4742
c =>
4843
{
49-
if (c.IsGeneratedDocument(cache))
50-
{
51-
return;
52-
}
53-
54-
// Honor the containing document item's ExcludeFromStylecop=True
55-
// MSBuild metadata, if analyzers have access to it.
56-
//// TODO: code here
57-
58-
StyleCopSettings settings = settingsCache.Value;
59-
if (settings == null)
60-
{
61-
StyleCopSettings updatedSettings = SettingsHelper.GetStyleCopSettings(c.Options, c.CancellationToken);
62-
StyleCopSettings previous = Interlocked.CompareExchange(ref settingsCache.Value, updatedSettings, null);
63-
settings = previous ?? updatedSettings;
64-
}
44+
StyleCopSettings settings = context.GetStyleCopSettings(c.Options, c.CancellationToken);
45+
action(c, settings);
46+
});
47+
}
6548

49+
/// <summary>
50+
/// Register an action to be executed at completion of parsing of a code document. A syntax tree action reports
51+
/// diagnostics about the <see cref="SyntaxTree"/> of a document.
52+
/// </summary>
53+
/// <param name="context">The analysis context.</param>
54+
/// <param name="action">Action to be executed at completion of parsing of a document.</param>
55+
public static void RegisterSyntaxTreeAction(this CompilationStartAnalysisContext context, Action<SyntaxTreeAnalysisContext, StyleCopSettings> action)
56+
{
57+
context.RegisterSyntaxTreeAction(
58+
c =>
59+
{
60+
StyleCopSettings settings = context.GetStyleCopSettings(c.Options, c.CancellationToken);
6661
action(c, settings);
6762
});
6863
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ internal class FileHeaderAnalyzers : DiagnosticAnalyzer
171171
/// <inheritdoc/>
172172
public override void Initialize(AnalysisContext context)
173173
{
174+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
175+
174176
context.RegisterCompilationStartAction(CompilationStartAction);
175177
}
176178

@@ -181,7 +183,7 @@ private static void HandleCompilationStart(CompilationStartAnalysisContext conte
181183
// Disabling SA1633 will disable all other header related diagnostics.
182184
if (!compilation.IsAnalyzerSuppressed(SA1633Identifier))
183185
{
184-
context.RegisterSyntaxTreeActionHonorExclusions((ctx, settings) => Analyzer.HandleSyntaxTree(ctx, settings, compilation));
186+
context.RegisterSyntaxTreeAction((ctx, settings) => Analyzer.HandleSyntaxTree(ctx, settings, compilation));
185187
}
186188
}
187189

StyleCop.Analyzers/StyleCop.Analyzers/DocumentationRules/SA1649FileNameMustMatchTypeName.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ internal class SA1649FileNameMustMatchTypeName : DiagnosticAnalyzer
4141
private static readonly DiagnosticDescriptor Descriptor =
4242
new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.DocumentationRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, Description, HelpLink);
4343

44-
private static readonly Action<CompilationStartAnalysisContext> CompilationStartAction = HandleCompilationStart;
4544
private static readonly Action<SyntaxTreeAnalysisContext, StyleCopSettings> SyntaxTreeAction = Analyzer.HandleSyntaxTree;
4645

4746
/// <inheritdoc/>
@@ -51,12 +50,9 @@ internal class SA1649FileNameMustMatchTypeName : DiagnosticAnalyzer
5150
/// <inheritdoc/>
5251
public override void Initialize(AnalysisContext context)
5352
{
54-
context.RegisterCompilationStartAction(CompilationStartAction);
55-
}
53+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
5654

57-
private static void HandleCompilationStart(CompilationStartAnalysisContext context)
58-
{
59-
context.RegisterSyntaxTreeActionHonorExclusions(SyntaxTreeAction);
55+
context.RegisterSyntaxTreeAction(SyntaxTreeAction);
6056
}
6157

6258
private static class Analyzer

StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/SA1518UseLineEndingsCorrectlyAtEndOfFile.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ internal class SA1518UseLineEndingsCorrectlyAtEndOfFile : DiagnosticAnalyzer
3939

4040
private static readonly string HelpLink = "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1518.md";
4141

42-
private static readonly Action<CompilationStartAnalysisContext> CompilationStartAction = HandleCompilationStart;
4342
private static readonly Action<SyntaxTreeAnalysisContext, StyleCopSettings> SyntaxTreeAction = HandleSyntaxTree;
4443

4544
public static DiagnosticDescriptor DescriptorAllow { get; } =
@@ -58,12 +57,9 @@ internal class SA1518UseLineEndingsCorrectlyAtEndOfFile : DiagnosticAnalyzer
5857
/// <inheritdoc/>
5958
public override void Initialize(AnalysisContext context)
6059
{
61-
context.RegisterCompilationStartAction(CompilationStartAction);
62-
}
60+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
6361

64-
private static void HandleCompilationStart(CompilationStartAnalysisContext context)
65-
{
66-
context.RegisterSyntaxTreeActionHonorExclusions(SyntaxTreeAction);
62+
context.RegisterSyntaxTreeAction(SyntaxTreeAction);
6763
}
6864

6965
private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context, StyleCopSettings settings)

StyleCop.Analyzers/StyleCop.Analyzers/MaintainabilityRules/SA1402FileMayOnlyContainASingleClass.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ internal class SA1402FileMayOnlyContainASingleClass : DiagnosticAnalyzer
4141
private static readonly DiagnosticDescriptor Descriptor =
4242
new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.MaintainabilityRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, Description, HelpLink);
4343

44-
private static readonly Action<CompilationStartAnalysisContext> CompilationStartAction = HandleCompilationStart;
4544
private static readonly Action<SyntaxTreeAnalysisContext, StyleCopSettings> SyntaxTreeAction = HandleSyntaxTree;
4645

4746
/// <inheritdoc/>
@@ -51,12 +50,9 @@ internal class SA1402FileMayOnlyContainASingleClass : DiagnosticAnalyzer
5150
/// <inheritdoc/>
5251
public override void Initialize(AnalysisContext context)
5352
{
54-
context.RegisterCompilationStartAction(CompilationStartAction);
55-
}
53+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
5654

57-
private static void HandleCompilationStart(CompilationStartAnalysisContext context)
58-
{
59-
context.RegisterSyntaxTreeActionHonorExclusions(SyntaxTreeAction);
55+
context.RegisterSyntaxTreeAction(SyntaxTreeAction);
6056
}
6157

6258
private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context, StyleCopSettings settings)

StyleCop.Analyzers/StyleCop.Analyzers/Settings/SettingsHelper.cs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ internal static class SettingsHelper
2424
{
2525
internal const string SettingsFileName = "stylecop.json";
2626

27+
private static readonly SourceTextValueProvider<StyleCopSettings> SettingsValueProvider =
28+
new SourceTextValueProvider<StyleCopSettings>(
29+
text => GetStyleCopSettings(text, DeserializationFailureBehavior.ReturnDefaultSettings));
30+
2731
private static readonly bool AvoidAdditionalTextGetText;
2832

2933
private static readonly ConcurrentDictionary<Type, ConcurrentDictionary<string, FieldInfo>> FieldInfos =
@@ -81,6 +85,90 @@ internal static StyleCopSettings GetStyleCopSettings(this AnalyzerOptions option
8185
return GetStyleCopSettings(options != null ? options.AdditionalFiles : ImmutableArray.Create<AdditionalText>(), failureBehavior, cancellationToken);
8286
}
8387

88+
internal static StyleCopSettings GetStyleCopSettings(this AnalysisContext context, AnalyzerOptions options, CancellationToken cancellationToken)
89+
{
90+
return GetStyleCopSettings(context, options, DeserializationFailureBehavior.ReturnDefaultSettings, cancellationToken);
91+
}
92+
93+
internal static StyleCopSettings GetStyleCopSettings(this AnalysisContext context, AnalyzerOptions options, DeserializationFailureBehavior failureBehavior, CancellationToken cancellationToken)
94+
{
95+
SourceText text = TryGetStyleCopSettingsText(options, cancellationToken);
96+
if (text == null)
97+
{
98+
return new StyleCopSettings();
99+
}
100+
101+
if (failureBehavior == DeserializationFailureBehavior.ReturnDefaultSettings)
102+
{
103+
StyleCopSettings settings;
104+
if (!context.TryGetValue(text, SettingsValueProvider, out settings))
105+
{
106+
return new StyleCopSettings();
107+
}
108+
109+
return settings;
110+
}
111+
112+
return JsonConvert.DeserializeObject<SettingsFile>(text.ToString()).Settings;
113+
}
114+
115+
internal static StyleCopSettings GetStyleCopSettings(this CompilationStartAnalysisContext context, AnalyzerOptions options, CancellationToken cancellationToken)
116+
{
117+
return GetStyleCopSettings(context, options, DeserializationFailureBehavior.ReturnDefaultSettings, cancellationToken);
118+
}
119+
120+
#pragma warning disable RS1012 // Start action has no registered actions.
121+
internal static StyleCopSettings GetStyleCopSettings(this CompilationStartAnalysisContext context, AnalyzerOptions options, DeserializationFailureBehavior failureBehavior, CancellationToken cancellationToken)
122+
#pragma warning restore RS1012 // Start action has no registered actions.
123+
{
124+
SourceText text = TryGetStyleCopSettingsText(options, cancellationToken);
125+
if (text == null)
126+
{
127+
return new StyleCopSettings();
128+
}
129+
130+
if (failureBehavior == DeserializationFailureBehavior.ReturnDefaultSettings)
131+
{
132+
StyleCopSettings settings;
133+
if (!context.TryGetValue(text, SettingsValueProvider, out settings))
134+
{
135+
return new StyleCopSettings();
136+
}
137+
138+
return settings;
139+
}
140+
141+
return JsonConvert.DeserializeObject<SettingsFile>(text.ToString()).Settings;
142+
}
143+
144+
private static StyleCopSettings GetStyleCopSettings(SourceText text, DeserializationFailureBehavior failureBehavior)
145+
{
146+
try
147+
{
148+
var root = JsonConvert.DeserializeObject<SettingsFile>(text.ToString());
149+
return root.Settings;
150+
}
151+
catch (JsonException) when (failureBehavior == DeserializationFailureBehavior.ReturnDefaultSettings)
152+
{
153+
// The settings file is invalid -> return the default settings.
154+
}
155+
156+
return new StyleCopSettings();
157+
}
158+
159+
private static SourceText TryGetStyleCopSettingsText(this AnalyzerOptions options, CancellationToken cancellationToken)
160+
{
161+
foreach (var additionalFile in options.AdditionalFiles)
162+
{
163+
if (Path.GetFileName(additionalFile.Path).ToLowerInvariant() == SettingsFileName)
164+
{
165+
return GetText(additionalFile, cancellationToken);
166+
}
167+
}
168+
169+
return null;
170+
}
171+
84172
private static StyleCopSettings GetStyleCopSettings(ImmutableArray<AdditionalText> additionalFiles, DeserializationFailureBehavior failureBehavior, CancellationToken cancellationToken)
85173
{
86174
try

StyleCop.Analyzers/StyleCop.Analyzers/SpacingRules/SA1027UseTabsCorrectly.cs

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

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

4039
private static readonly ImmutableDictionary<string, string> ConvertToTabsProperties =
@@ -50,12 +49,9 @@ internal class SA1027UseTabsCorrectly : DiagnosticAnalyzer
5049
/// <inheritdoc/>
5150
public override void Initialize(AnalysisContext context)
5251
{
53-
context.RegisterCompilationStartAction(CompilationStartAction);
54-
}
52+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
5553

56-
private static void HandleCompilationStart(CompilationStartAnalysisContext context)
57-
{
58-
context.RegisterSyntaxTreeActionHonorExclusions(SyntaxTreeAction);
54+
context.RegisterSyntaxTreeAction(SyntaxTreeAction);
5955
}
6056

6157
private static void HandleSyntaxTree(SyntaxTreeAnalysisContext context, StyleCopSettings settings)

0 commit comments

Comments
 (0)