Skip to content

Commit ff3da04

Browse files
Remove analyzer cache from public surface area (#79808)
2 parents bdb4dbe + 0f1e9db commit ff3da04

File tree

13 files changed

+361
-180
lines changed

13 files changed

+361
-180
lines changed

src/EditorFeatures/Core/EditorConfigSettings/DataProvider/Analyzer/AnalyzerSettingsProvider.cs

Lines changed: 35 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -13,53 +13,70 @@
1313
using Microsoft.CodeAnalysis.Editor.EditorConfigSettings.Updater;
1414
using Microsoft.CodeAnalysis.EditorConfig;
1515
using Microsoft.CodeAnalysis.Options;
16+
using Microsoft.CodeAnalysis.PooledObjects;
1617
using Microsoft.CodeAnalysis.Shared.Extensions;
1718
using RoslynEnumerableExtensions = Microsoft.CodeAnalysis.Editor.EditorConfigSettings.Extensions.EnumerableExtensions;
1819

1920
namespace Microsoft.CodeAnalysis.Editor.EditorConfigSettings.DataProvider.Analyzer;
2021

2122
internal sealed class AnalyzerSettingsProvider : SettingsProviderBase<AnalyzerSetting, AnalyzerSettingsUpdater, AnalyzerSetting, ReportDiagnostic>
2223
{
23-
private readonly IDiagnosticAnalyzerService _analyzerService;
24-
2524
public AnalyzerSettingsProvider(
2625
string fileName,
2726
AnalyzerSettingsUpdater settingsUpdater,
2827
Workspace workspace,
2928
IGlobalOptionService optionService)
3029
: base(fileName, settingsUpdater, workspace, optionService)
3130
{
32-
_analyzerService = workspace.Services.GetRequiredService<IDiagnosticAnalyzerService>();
3331
Update();
3432
}
3533

36-
protected override void UpdateOptions(TieredAnalyzerConfigOptions options, ImmutableArray<Project> projectsInScope)
34+
protected override void UpdateOptions(
35+
TieredAnalyzerConfigOptions options, Solution solution, ImmutableArray<Project> projectsInScope)
3736
{
3837
var analyzerReferences = RoslynEnumerableExtensions.DistinctBy(projectsInScope.SelectMany(p => p.AnalyzerReferences), a => a.Id).ToImmutableArray();
3938
foreach (var analyzerReference in analyzerReferences)
4039
{
41-
var configSettings = GetSettings(analyzerReference, options.EditorConfigOptions);
40+
var configSettings = GetSettings(solution, analyzerReference, options.EditorConfigOptions);
4241
AddRange(configSettings);
4342
}
4443
}
4544

46-
private IEnumerable<AnalyzerSetting> GetSettings(AnalyzerReference analyzerReference, AnalyzerConfigOptions editorConfigOptions)
45+
private ImmutableArray<AnalyzerSetting> GetSettings(
46+
Solution solution, AnalyzerReference analyzerReference, AnalyzerConfigOptions editorConfigOptions)
4747
{
48-
IEnumerable<DiagnosticAnalyzer> csharpAnalyzers = analyzerReference.GetAnalyzers(LanguageNames.CSharp);
49-
IEnumerable<DiagnosticAnalyzer> visualBasicAnalyzers = analyzerReference.GetAnalyzers(LanguageNames.VisualBasic);
50-
var dotnetAnalyzers = csharpAnalyzers.Intersect(visualBasicAnalyzers, DiagnosticAnalyzerComparer.Instance);
51-
csharpAnalyzers = csharpAnalyzers.Except(dotnetAnalyzers, DiagnosticAnalyzerComparer.Instance);
52-
visualBasicAnalyzers = visualBasicAnalyzers.Except(dotnetAnalyzers, DiagnosticAnalyzerComparer.Instance);
48+
var service = solution.Services.GetRequiredService<IDiagnosticAnalyzerService>();
49+
var map = service.GetDiagnosticDescriptors(solution, analyzerReference);
50+
51+
using var _ = ArrayBuilder<AnalyzerSetting>.GetInstance(out var allSettings);
52+
53+
foreach (var (languages, descriptors) in map)
54+
allSettings.AddRange(ToAnalyzerSettings(descriptors, ConvertToLanguage(languages)));
55+
56+
return allSettings.ToImmutableAndClear();
57+
58+
Language ConvertToLanguage(ImmutableArray<string> languages)
59+
{
60+
Contract.ThrowIfTrue(languages.Length == 0);
61+
var language = (Language)0;
5362

54-
var csharpSettings = ToAnalyzerSetting(csharpAnalyzers, Language.CSharp);
55-
var csharpAndVisualBasicSettings = csharpSettings.Concat(ToAnalyzerSetting(visualBasicAnalyzers, Language.VisualBasic));
56-
return csharpAndVisualBasicSettings.Concat(ToAnalyzerSetting(dotnetAnalyzers, Language.CSharp | Language.VisualBasic));
63+
foreach (var languageString in languages)
64+
{
65+
language |= languageString switch
66+
{
67+
LanguageNames.CSharp => Language.CSharp,
68+
LanguageNames.VisualBasic => Language.VisualBasic,
69+
_ => throw new ArgumentException($"Unsupported language: {languageString}")
70+
};
71+
}
72+
73+
return language;
74+
}
5775

58-
IEnumerable<AnalyzerSetting> ToAnalyzerSetting(IEnumerable<DiagnosticAnalyzer> analyzers,
59-
Language language)
76+
IEnumerable<AnalyzerSetting> ToAnalyzerSettings(
77+
IEnumerable<DiagnosticDescriptor> descriptors, Language language)
6078
{
61-
return analyzers
62-
.SelectMany(a => _analyzerService.AnalyzerInfoCache.GetDiagnosticDescriptors(a))
79+
return descriptors
6380
.GroupBy(d => d.Id)
6481
.OrderBy(g => g.Key, StringComparer.CurrentCulture)
6582
.Select(g =>
@@ -72,36 +89,4 @@ IEnumerable<AnalyzerSetting> ToAnalyzerSetting(IEnumerable<DiagnosticAnalyzer> a
7289
});
7390
}
7491
}
75-
76-
private sealed class DiagnosticAnalyzerComparer : IEqualityComparer<DiagnosticAnalyzer>
77-
{
78-
public static readonly DiagnosticAnalyzerComparer Instance = new();
79-
80-
public bool Equals(DiagnosticAnalyzer? x, DiagnosticAnalyzer? y)
81-
=> (x, y) switch
82-
{
83-
(null, null) => true,
84-
(null, _) => false,
85-
(_, null) => false,
86-
_ => GetAnalyzerIdAndLastWriteTime(x) == GetAnalyzerIdAndLastWriteTime(y)
87-
};
88-
89-
public int GetHashCode(DiagnosticAnalyzer obj) => GetAnalyzerIdAndLastWriteTime(obj).GetHashCode();
90-
91-
private static (string analyzerId, DateTime lastWriteTime) GetAnalyzerIdAndLastWriteTime(DiagnosticAnalyzer analyzer)
92-
{
93-
// Get the unique ID for given diagnostic analyzer.
94-
// note that we also put version stamp so that we can detect changed analyzer.
95-
var typeInfo = analyzer.GetType().GetTypeInfo();
96-
return (analyzer.GetAnalyzerId(), GetAnalyzerLastWriteTime(typeInfo.Assembly.Location));
97-
}
98-
99-
private static DateTime GetAnalyzerLastWriteTime(string path)
100-
{
101-
if (path == null || !File.Exists(path))
102-
return default;
103-
104-
return File.GetLastWriteTimeUtc(path);
105-
}
106-
}
10792
}

src/EditorFeatures/Core/EditorConfigSettings/DataProvider/NamingStyles/NamingStyleSettingsProvider.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ public NamingStyleSettingsProvider(string fileName, NamingStyleSettingsUpdater s
2323
Update();
2424
}
2525

26-
protected override void UpdateOptions(TieredAnalyzerConfigOptions options, ImmutableArray<Project> projectsInScope)
26+
protected override void UpdateOptions(
27+
TieredAnalyzerConfigOptions options, Solution solution, ImmutableArray<Project> projectsInScope)
2728
{
2829
options.GetInitialLocationAndValue<NamingStylePreferences>(NamingStyleOptions.NamingPreferences, out var location, out var namingPreferences);
2930

src/EditorFeatures/Core/EditorConfigSettings/DataProvider/SettingsProviderBase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ internal abstract class SettingsProviderBase<TData, TOptionsUpdater, TOption, TV
3333
protected readonly Workspace Workspace;
3434
public readonly IGlobalOptionService GlobalOptions;
3535

36-
protected abstract void UpdateOptions(TieredAnalyzerConfigOptions options, ImmutableArray<Project> projectsInScope);
36+
protected abstract void UpdateOptions(TieredAnalyzerConfigOptions options, Solution solution, ImmutableArray<Project> projectsInScope);
3737

3838
protected SettingsProviderBase(string fileName, TOptionsUpdater settingsUpdater, Workspace workspace, IGlobalOptionService globalOptions)
3939
{
@@ -70,7 +70,7 @@ protected void Update()
7070
language: LanguageNames.CSharp,
7171
editorConfigFileName: FileName);
7272

73-
UpdateOptions(options, projects);
73+
UpdateOptions(options, solution, projects);
7474
}
7575

7676
public async Task<SourceText> GetChangedEditorConfigAsync(SourceText sourceText)

0 commit comments

Comments
 (0)