Skip to content

Commit a780b34

Browse files
committed
Cache StyleCop settings instances in analyzers
1 parent 88caa25 commit a780b34

File tree

2 files changed

+63
-18
lines changed

2 files changed

+63
-18
lines changed

StyleCop.Analyzers/StyleCop.Analyzers/AnalyzerExtensions.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace StyleCop.Analyzers
99
using System.Collections.Concurrent;
1010
using System.Collections.Immutable;
1111
using System.Diagnostics.CodeAnalysis;
12+
using System.Runtime.CompilerServices;
1213
using Microsoft.CodeAnalysis;
1314
using Microsoft.CodeAnalysis.Diagnostics;
1415
using StyleCop.Analyzers.Settings.ObjectModel;
@@ -32,9 +33,12 @@ public static void RegisterSyntaxTreeAction(this CompilationStartAnalysisContext
3233
context.RegisterSyntaxTreeAction(
3334
context =>
3435
{
35-
StyleCopSettings settings = context.GetStyleCopSettings(settingsFile);
36+
StyleCopSettings settings = context.GetStyleCopSettings(GetOrCreateSettingsStorage(context.Tree), settingsFile);
3637
action(context, settings);
3738
});
39+
40+
StrongBox<StyleCopSettings> GetOrCreateSettingsStorage(SyntaxTree tree)
41+
=> SettingsHelper.GetOrCreateSettingsStorage(context, tree);
3842
}
3943

4044
/// <summary>
@@ -74,10 +78,13 @@ public static void RegisterSyntaxNodeAction<TLanguageKindEnum>(this CompilationS
7478
context.RegisterSyntaxNodeAction(
7579
context =>
7680
{
77-
StyleCopSettings settings = context.GetStyleCopSettings(settingsFile);
81+
StyleCopSettings settings = context.GetStyleCopSettings(GetOrCreateSettingsStorage(context.Node.SyntaxTree), settingsFile);
7882
action(context, settings);
7983
},
8084
syntaxKinds);
85+
86+
StrongBox<StyleCopSettings> GetOrCreateSettingsStorage(SyntaxTree tree)
87+
=> SettingsHelper.GetOrCreateSettingsStorage(context, tree);
8188
}
8289

8390
private static class LanguageKindArrays<TLanguageKindEnum>

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

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace StyleCop.Analyzers
1010
using System.Diagnostics;
1111
using System.Diagnostics.CodeAnalysis;
1212
using System.IO;
13+
using System.Runtime.CompilerServices;
1314
using System.Threading;
1415
using LightJson;
1516
using LightJson.Serialization;
@@ -29,7 +30,10 @@ internal static class SettingsHelper
2930

3031
private static SourceTextValueProvider<Lazy<JsonValue>> JsonValueProvider { get; } =
3132
new SourceTextValueProvider<Lazy<JsonValue>>(
32-
text => ParseJson(text));
33+
static text => ParseJson(text));
34+
35+
private static SyntaxTreeValueProvider<StrongBox<StyleCopSettings>> SettingsStorageValueProvider { get; } =
36+
new SyntaxTreeValueProvider<StrongBox<StyleCopSettings>>(static _ => new StrongBox<StyleCopSettings>());
3337

3438
/// <summary>
3539
/// Gets the StyleCop settings from the JSON file, i.e. without adding information frmo the .editorconfig.
@@ -58,6 +62,27 @@ Lazy<JsonValue> GetJsonValue(SourceText settingsText)
5862
}
5963
}
6064

65+
[SuppressMessage("MicrosoftCodeAnalysisPerformance", "RS1012:Start action has no registered actions", Justification = "This is not a start action")]
66+
internal static StrongBox<StyleCopSettings> GetOrCreateSettingsStorage(this CompilationStartAnalysisContext context, SyntaxTree tree)
67+
{
68+
if (!context.TryGetValue(tree, SettingsStorageValueProvider, out var storage))
69+
{
70+
storage = new StrongBox<StyleCopSettings>();
71+
}
72+
73+
return storage;
74+
}
75+
76+
internal static StrongBox<StyleCopSettings> GetOrCreateSettingsStorage(this CompilationAnalysisContext context, SyntaxTree tree)
77+
{
78+
if (!context.TryGetValue(tree, SettingsStorageValueProvider, out var storage))
79+
{
80+
storage = new StrongBox<StyleCopSettings>();
81+
}
82+
83+
return storage;
84+
}
85+
6186
/// <summary>
6287
/// Gets the StyleCop settings.
6388
/// </summary>
@@ -66,11 +91,12 @@ Lazy<JsonValue> GetJsonValue(SourceText settingsText)
6691
/// deserializing the settings file, a default settings instance is returned.</para>
6792
/// </remarks>
6893
/// <param name="context">The context that will be used to determine the StyleCop settings.</param>
94+
/// <param name="settingsStorage">The storage location for caching an evaluated <see cref="StyleCopSettings"/> object.</param>
6995
/// <param name="settingsFile">Information about the StyleCop settings file.</param>
7096
/// <returns>A <see cref="StyleCopSettings"/> instance that represents the StyleCop settings for the given context.</returns>
71-
internal static StyleCopSettings GetStyleCopSettings(this SyntaxTreeAnalysisContext context, SettingsFile settingsFile)
97+
internal static StyleCopSettings GetStyleCopSettings(this SyntaxTreeAnalysisContext context, StrongBox<StyleCopSettings> settingsStorage, SettingsFile settingsFile)
7298
{
73-
return GetSettings(context.Options, context.Tree, settingsFile, DeserializationFailureBehavior.ReturnDefaultSettings);
99+
return GetSettings(context.Options, settingsStorage, context.Tree, settingsFile, DeserializationFailureBehavior.ReturnDefaultSettings);
74100
}
75101

76102
/// <summary>
@@ -87,7 +113,7 @@ internal static StyleCopSettings GetStyleCopSettings(this SyntaxTreeAnalysisCont
87113
internal static StyleCopSettings GetStyleCopSettings(this SyntaxTreeAnalysisContext context, CancellationToken cancellationToken)
88114
{
89115
var settingsFile = GetSettingsFile(context.Options, ParseJson, cancellationToken);
90-
return GetSettings(context.Options, context.Tree, settingsFile, DeserializationFailureBehavior.ReturnDefaultSettings);
116+
return GetSettings(context.Options, settingsStorage: new StrongBox<StyleCopSettings>(), context.Tree, settingsFile, DeserializationFailureBehavior.ReturnDefaultSettings);
91117
}
92118

93119
/// <summary>
@@ -98,11 +124,12 @@ internal static StyleCopSettings GetStyleCopSettings(this SyntaxTreeAnalysisCont
98124
/// deserializing the settings file, a default settings instance is returned.</para>
99125
/// </remarks>
100126
/// <param name="context">The context that will be used to determine the StyleCop settings.</param>
127+
/// <param name="settingsStorage">The storage location for caching an evaluated <see cref="StyleCopSettings"/> object.</param>
101128
/// <param name="settingsFile">The contents of the StyleCop settnigs file.</param>
102129
/// <returns>A <see cref="StyleCopSettings"/> instance that represents the StyleCop settings for the given context.</returns>
103-
internal static StyleCopSettings GetStyleCopSettings(this SyntaxNodeAnalysisContext context, SettingsFile settingsFile)
130+
internal static StyleCopSettings GetStyleCopSettings(this SyntaxNodeAnalysisContext context, StrongBox<StyleCopSettings> settingsStorage, SettingsFile settingsFile)
104131
{
105-
return GetSettings(context.Options, context.Node.SyntaxTree, settingsFile, DeserializationFailureBehavior.ReturnDefaultSettings);
132+
return GetSettings(context.Options, settingsStorage, context.Node.SyntaxTree, settingsFile, DeserializationFailureBehavior.ReturnDefaultSettings);
106133
}
107134

108135
/// <summary>
@@ -120,7 +147,7 @@ internal static StyleCopSettings GetStyleCopSettings(this SyntaxNodeAnalysisCont
120147
internal static StyleCopSettings GetStyleCopSettings(this AnalyzerOptions options, SyntaxTree tree, CancellationToken cancellationToken)
121148
{
122149
var settingsFile = GetSettingsFile(options, ParseJson, cancellationToken);
123-
return GetSettings(options, tree, settingsFile, DeserializationFailureBehavior.ReturnDefaultSettings);
150+
return GetSettings(options, settingsStorage: new StrongBox<StyleCopSettings>(), tree, settingsFile, DeserializationFailureBehavior.ReturnDefaultSettings);
124151
}
125152

126153
/// <summary>
@@ -135,7 +162,7 @@ internal static StyleCopSettings GetStyleCopSettings(this AnalyzerOptions option
135162
internal static StyleCopSettings GetStyleCopSettings(this CompilationAnalysisContext context, SyntaxTree tree, DeserializationFailureBehavior failureBehavior, CancellationToken cancellationToken)
136163
{
137164
var settingsFile = GetSettingsFile(context.Options, GetJsonValue, cancellationToken);
138-
return GetSettings(context.Options, tree, settingsFile, failureBehavior);
165+
return GetSettings(context.Options, GetOrCreateSettingsStorage(context, tree), tree, settingsFile, failureBehavior);
139166

140167
Lazy<JsonValue> GetJsonValue(SourceText settingsText)
141168
{
@@ -171,21 +198,32 @@ internal static bool IsStyleCopSettingsFile(string path)
171198
|| string.Equals(fileName, AltSettingsFileName, StringComparison.OrdinalIgnoreCase);
172199
}
173200

174-
private static StyleCopSettings GetSettings(AnalyzerOptions options, SyntaxTree tree, SettingsFile settingsFile, DeserializationFailureBehavior failureBehavior)
201+
private static StyleCopSettings GetSettings(AnalyzerOptions options, StrongBox<StyleCopSettings> settingsStorage, SyntaxTree tree, SettingsFile settingsFile, DeserializationFailureBehavior failureBehavior)
175202
{
176-
if (settingsFile != null)
203+
if (settingsStorage.Value is { } settings)
177204
{
178-
return CreateSettingsObjectFromFile(options, tree, settingsFile, failureBehavior);
205+
return settings;
179206
}
180207

181-
// TODO: Can this really be null? Review when nullable references has been enabled
182-
if (tree != null)
208+
if (settingsFile != null)
209+
{
210+
settings = CreateSettingsObjectFromFile(options, tree, settingsFile, failureBehavior);
211+
}
212+
else
183213
{
184-
var analyzerConfigOptions = options.AnalyzerConfigOptionsProvider().GetOptions(tree);
185-
return new StyleCopSettings(new JsonObject(), analyzerConfigOptions);
214+
// TODO: Can this really be null? Review when nullable references has been enabled
215+
if (tree != null)
216+
{
217+
var analyzerConfigOptions = options.AnalyzerConfigOptionsProvider().GetOptions(tree);
218+
settings = new StyleCopSettings(new JsonObject(), analyzerConfigOptions);
219+
}
220+
else
221+
{
222+
settings = new StyleCopSettings();
223+
}
186224
}
187225

188-
return new StyleCopSettings();
226+
return Interlocked.CompareExchange(ref settingsStorage.Value, settings, null) ?? settings;
189227
}
190228

191229
private static StyleCopSettings CreateSettingsObjectFromFile(AnalyzerOptions options, SyntaxTree tree, SettingsFile settingsFile, DeserializationFailureBehavior failureBehavior)

0 commit comments

Comments
 (0)